From 62d5bbce7e0cc9362e0c2e0fb8e13a17b41adbe2 Mon Sep 17 00:00:00 2001 From: Rafeek-Khoudare Date: Mon, 30 Jun 2025 13:22:04 +0300 Subject: [PATCH 1/3] add isValid to basic step (1) and insure that user can go to another step using next button without filling the form --- .../add_user_dialog/view/add_user_dialog.dart | 57 ++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart index 44ba81ff..0fea43d9 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart @@ -34,7 +34,8 @@ class _AddNewUserDialogState extends State { return Dialog( child: Container( decoration: const BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(20))), width: 900, child: Column( children: [ @@ -63,7 +64,8 @@ class _AddNewUserDialogState extends State { children: [ _buildStep1Indicator(1, "Basics", _blocRole), _buildStep2Indicator(2, "Spaces", _blocRole), - _buildStep3Indicator(3, "Role & Permissions", _blocRole), + _buildStep3Indicator( + 3, "Role & Permissions", _blocRole), ], ), ), @@ -105,18 +107,32 @@ class _AddNewUserDialogState extends State { ), InkWell( onTap: () { + final isBasicsStep = currentStep == 1; + + if (isBasicsStep) { + // Validate the form first + final isValid = _blocRole.formKey.currentState + ?.validate() ?? + false; + + if (!isValid) + return; // Stop if form is not valid + } _blocRole.add(const CheckEmailEvent()); setState(() { if (currentStep < 3) { currentStep++; if (currentStep == 2) { - _blocRole.add(const CheckStepStatus(isEditUser: false)); + _blocRole.add(const CheckStepStatus( + isEditUser: false)); } else if (currentStep == 3) { - _blocRole.add(const CheckSpacesStepStatus()); + _blocRole + .add(const CheckSpacesStepStatus()); } } else { - _blocRole.add(SendInviteUsers(context: context)); + _blocRole + .add(SendInviteUsers(context: context)); } }); }, @@ -124,8 +140,11 @@ class _AddNewUserDialogState extends State { currentStep < 3 ? "Next" : "Save", style: TextStyle( color: (_blocRole.isCompleteSpaces == false || - _blocRole.isCompleteBasics == false || - _blocRole.isCompleteRolePermissions == false) && + _blocRole.isCompleteBasics == + false || + _blocRole + .isCompleteRolePermissions == + false) && currentStep == 3 ? ColorsManager.grayColor : ColorsManager.secondaryColor), @@ -196,8 +215,12 @@ class _AddNewUserDialogState extends State { label, style: TextStyle( fontSize: 16, - color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, - fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, + color: currentStep == step + ? ColorsManager.blackColor + : ColorsManager.greyColor, + fontWeight: currentStep == step + ? FontWeight.bold + : FontWeight.normal, ), ), ], @@ -260,8 +283,12 @@ class _AddNewUserDialogState extends State { label, style: TextStyle( fontSize: 16, - color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, - fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, + color: currentStep == step + ? ColorsManager.blackColor + : ColorsManager.greyColor, + fontWeight: currentStep == step + ? FontWeight.bold + : FontWeight.normal, ), ), ], @@ -318,8 +345,12 @@ class _AddNewUserDialogState extends State { label, style: TextStyle( fontSize: 16, - color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, - fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, + color: currentStep == step + ? ColorsManager.blackColor + : ColorsManager.greyColor, + fontWeight: currentStep == step + ? FontWeight.bold + : FontWeight.normal, ), ), ], From e5e88385e9d0e230921cd35b5ad7b695c0abd92b Mon Sep 17 00:00:00 2001 From: Rafeek-Khoudare Date: Mon, 30 Jun 2025 13:31:38 +0300 Subject: [PATCH 2/3] change autoValidae mode to userInteraction and give some time to check validate when typing on keyboard with debouncer --- .../add_user_dialog/view/add_user_dialog.dart | 2 +- .../add_user_dialog/view/basics_view.dart | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart index 0fea43d9..501cd02e 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/add_user_dialog.dart @@ -162,7 +162,7 @@ class _AddNewUserDialogState extends State { Widget _getFormContent() { switch (currentStep) { case 1: - return const BasicsView( + return BasicsView( userId: '', ); case 2: diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/basics_view.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/basics_view.dart index fa04c051..14022cab 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/basics_view.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/basics_view.dart @@ -1,9 +1,12 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl_phone_field/countries.dart'; import 'package:intl_phone_field/country_picker_dialog.dart'; import 'package:intl_phone_field/intl_phone_field.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; +import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; @@ -11,7 +14,9 @@ import 'package:syncrow_web/utils/style.dart'; class BasicsView extends StatelessWidget { final String? userId; - const BasicsView({super.key, this.userId = ''}); + Timer? _debounce; + + BasicsView({super.key, this.userId = ''}); @override Widget build(BuildContext context) { return BlocBuilder(builder: (context, state) { @@ -21,6 +26,7 @@ class BasicsView extends StatelessWidget { } return Form( key: _blocRole.formKey, + autovalidateMode: AutovalidateMode.onUserInteraction, child: ListView( shrinkWrap: true, children: [ @@ -208,6 +214,14 @@ class BasicsView extends StatelessWidget { fontSize: 12, color: ColorsManager.textGray), ), + + onChanged: (value) { + if (_debounce?.isActive ?? false) _debounce!.cancel(); + _debounce = Timer(const Duration(milliseconds: 800), () { + _blocRole.add(const CheckEmailEvent()); + }); + }, + validator: (value) { if (value == null || value.isEmpty) { return 'Enter Email Address'; From 15ee79688dc9e9d0a1de7004cddb99988210f0f4 Mon Sep 17 00:00:00 2001 From: Rafeek-Khoudare Date: Mon, 30 Jun 2025 13:36:52 +0300 Subject: [PATCH 3/3] reComite --- .../users_page/add_user_dialog/bloc/users_bloc.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart index 54187152..72c4501c 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart @@ -455,7 +455,7 @@ class UsersBloc extends Bloc { Future checkEmail( CheckEmailEvent event, Emitter emit) async { emit(UsersLoadingState()); - String? res = await UserPermissionApi().checkEmail( + String? res = await UserPermissionApi().checkEmail( emailController.text, ); checkEmailValid = res!;