From 15023e5882cafec4e2380f6ec1f2712bd5ef747d Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 12 Jan 2025 15:32:03 +0300 Subject: [PATCH 1/4] fixes filter and table view and add user dialog --- .../model/roles_user_model.dart | 2 +- .../add_user_dialog/view/add_user_dialog.dart | 6 +- .../view/delete_user_dialog.dart | 55 ++- .../view/popup_menu_filter.dart | 255 +++++----- .../add_user_dialog/view/role_dropdown.dart | 6 +- .../users_table/bloc/user_table_bloc.dart | 70 ++- .../users_table/bloc/user_table_event.dart | 33 +- .../users_table/view/user_table.dart | 436 +++++++----------- .../users_table/view/users_page.dart | 108 ++--- lib/services/user_permission.dart | 13 +- 10 files changed, 496 insertions(+), 488 deletions(-) diff --git a/lib/pages/roles_and_permission/model/roles_user_model.dart b/lib/pages/roles_and_permission/model/roles_user_model.dart index 6298dbe6..44e3f493 100644 --- a/lib/pages/roles_and_permission/model/roles_user_model.dart +++ b/lib/pages/roles_and_permission/model/roles_user_model.dart @@ -42,7 +42,7 @@ class RolesUserModel { invitedBy: json['invitedBy'].toString().toLowerCase().replaceAll("_", " "), phoneNumber: json['phoneNumber'], - jobTitle: json['jobTitle'].toString(), + jobTitle: json['jobTitle'] ?? "-", createdDate: json['createdDate'], createdTime: json['createdTime'], ); 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 48df801a..f29aec8e 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 @@ -114,7 +114,7 @@ class _AddNewUserDialogState extends State { currentStep++; if (currentStep == 2) { _blocRole.add( - CheckStepStatus(isEditUser: false)); + const CheckStepStatus(isEditUser: false)); } else if (currentStep == 3) { _blocRole .add(const CheckSpacesStepStatus()); @@ -151,7 +151,7 @@ class _AddNewUserDialogState extends State { Widget _getFormContent() { switch (currentStep) { case 1: - return BasicsView( + return const BasicsView( userId: '', ); case 2: @@ -172,7 +172,7 @@ class _AddNewUserDialogState extends State { bloc.add(const CheckSpacesStepStatus()); currentStep = step; Future.delayed(const Duration(milliseconds: 500), () { - bloc.add(ValidateBasicsStep()); + bloc.add(const ValidateBasicsStep()); }); }); diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/delete_user_dialog.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/delete_user_dialog.dart index 837ee62c..10e8c273 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/delete_user_dialog.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/delete_user_dialog.dart @@ -11,7 +11,14 @@ class DeleteUserDialog extends StatefulWidget { } class _DeleteUserDialogState extends State { - int currentStep = 1; + bool isLoading = false; + bool _isDisposed = false; + + @override + void dispose() { + _isDisposed = true; + super.dispose(); + } @override Widget build(BuildContext context) { @@ -56,7 +63,7 @@ class _DeleteUserDialogState extends State { Expanded( child: InkWell( onTap: () { - Navigator.of(context).pop(true); + Navigator.of(context).pop(false); // Return false if canceled }, child: Container( padding: const EdgeInsets.all(10), @@ -76,7 +83,26 @@ class _DeleteUserDialogState extends State { )), Expanded( child: InkWell( - onTap: widget.onTapDelete, + onTap: isLoading + ? null + : () async { + setState(() { + isLoading = true; + }); + + try { + if (widget.onTapDelete != null) { + await widget.onTapDelete!(); + } + } finally { + if (!_isDisposed) { + setState(() { + isLoading = false; + }); + } + } + Navigator.of(context).pop(true); + }, child: Container( padding: const EdgeInsets.all(10), decoration: const BoxDecoration( @@ -91,13 +117,22 @@ class _DeleteUserDialogState extends State { ), ), ), - child: const Center( - child: Text( - 'Delete', - style: TextStyle( - color: ColorsManager.red, - ), - ))), + child: Center( + child: isLoading + ? const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + color: ColorsManager.red, + strokeWidth: 2.0, + ), + ) + : const Text( + 'Delete', + style: TextStyle( + color: ColorsManager.red, + ), + ))), )), ], ) diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart index 7c3c1ba5..c3a245c1 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart @@ -5,141 +5,156 @@ import 'package:syncrow_web/utils/style.dart'; Future showPopUpFilterMenu({ required BuildContext context, - Function()? onSortAtoZ, - Function()? onSortZtoA, + required Function(String value)? onSortAtoZ, // Accept a parameter + required Function(String value)? onSortZtoA, // Accept a parameter Function()? cancelButton, required Map checkboxStates, required RelativeRect position, Function()? onOkPressed, List? list, + String? isSelected, }) async { - - await showMenu( context: context, - position:position, - - + position: position, color: ColorsManager.whiteColors, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10)), ), items: [ PopupMenuItem( - onTap: onSortAtoZ, - child: ListTile( - leading: Image.asset( - Assets.AtoZIcon, - width: 25, - ), - title: const Text( - "Sort A to Z", - style: TextStyle(color: Colors.blueGrey), - ), - ), - ), - PopupMenuItem( - onTap: onSortZtoA, - child: ListTile( - leading: Image.asset( - Assets.ZtoAIcon, - width: 25, - ), - title: const Text( - "Sort Z to A", - style: TextStyle(color: Colors.blueGrey), - ), - ), - ), - const PopupMenuDivider(), - const PopupMenuItem( - child: Text( - "Filter by Status", - style: TextStyle(fontWeight: FontWeight.bold), - ) - // Container( - // decoration: containerDecoration.copyWith( - // boxShadow: [], - // borderRadius: const BorderRadius.only( - // topLeft: Radius.circular(10), topRight: Radius.circular(10))), - // child: Padding( - // padding: const EdgeInsets.all(8.0), - // child: TextFormField( - // onChanged: onTextFieldChanged, - // style: const TextStyle(color: Colors.black), - // decoration: textBoxDecoration(radios: 15)!.copyWith( - // fillColor: ColorsManager.whiteColors, - // errorStyle: const TextStyle(height: 0), - // hintStyle: context.textTheme.titleSmall?.copyWith( - // color: Colors.grey, - // fontSize: 12, - // ), - // hintText: 'Search', - // suffixIcon: SizedBox( - // child: SvgPicture.asset( - // Assets.searchIconUser, - // fit: BoxFit.none, - // ), - // ), - // ), - // // "Filter by Status", - // // style: TextStyle(fontWeight: FontWeight.bold), - // ), - // ), - // ), - ), - PopupMenuItem( - child: Container( - decoration: containerDecoration.copyWith( - boxShadow: [], - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10))), - padding: const EdgeInsets.all(10), - height: 200, - width: 400, - child: Container( - padding: const EdgeInsets.all(10), - color: Colors.white, - child: ListView.builder( - itemCount: list?.length ?? 0, - itemBuilder: (context, index) { - final item = list![index]; - return CheckboxListTile( - dense: true, - title: Text(item), - value: checkboxStates[item], - onChanged: (bool? newValue) { - checkboxStates[item] = newValue ?? false; - (context as Element).markNeedsBuild(); - }, - ); - }, - ), - ), - ), - ), - PopupMenuItem( - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - onTap: () { - Navigator.of(context).pop(); // Close the menu - }, - child: const Text("Cancel"), - ), - GestureDetector( - onTap: onOkPressed, - child: const Text( - "OK", - style: TextStyle( - color: ColorsManager.spaceColor, + enabled: false, + child: StatefulBuilder( + builder: (context, setState) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + child: ListTile( + onTap: () { + setState(() { + if (isSelected == 'Asc') { + isSelected = null; + onSortAtoZ?.call(''); + } else { + onSortAtoZ?.call('Asc'); + isSelected = 'Asc'; + } + }); + }, + leading: Image.asset( + Assets.AtoZIcon, + width: 25, + ), + title: Text( + "Sort A to Z", + style: TextStyle( + color: isSelected == "Asc" + ? ColorsManager.blackColor + : ColorsManager.grayColor), + ), + ), ), - ), - ), - ], + ListTile( + onTap: () { + setState(() { + if (isSelected == 'Desc') { + isSelected = null; + onSortZtoA?.call(''); + } else { + onSortZtoA?.call('Desc'); + isSelected = 'Desc'; + } + }); + }, + leading: Image.asset( + Assets.ZtoAIcon, + width: 25, + ), + title: Text( + "Sort Z to A", + style: TextStyle( + color: isSelected == "Desc" + ? ColorsManager.blackColor + : ColorsManager.grayColor), + ), + ), + const Divider(), + const Text( + "Filter by Status", + style: TextStyle(fontWeight: FontWeight.bold), + ), + Container( + decoration: containerDecoration.copyWith( + boxShadow: [], + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + topRight: Radius.circular(10), + bottomLeft: Radius.circular(10), + bottomRight: Radius.circular(10))), + padding: const EdgeInsets.all(10), + height: 200, + width: 400, + child: Container( + padding: const EdgeInsets.all(10), + color: Colors.white, + child: ListView.builder( + itemCount: list?.length ?? 0, + itemBuilder: (context, index) { + final item = list![index]; + return Row( + children: [ + Checkbox( + value: checkboxStates[item], + onChanged: (bool? newValue) { + checkboxStates[item] = newValue ?? false; + (context as Element).markNeedsBuild(); + }, + ), + Text( + item, + style: TextStyle(color: ColorsManager.grayColor), + ), + ], + ); + }, + ), + ), + ), + const SizedBox( + height: 10, + ), + const Divider(), + const SizedBox( + height: 10, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.of(context).pop(); // Close the menu + }, + child: const Text("Cancel"), + ), + GestureDetector( + onTap: onOkPressed, + child: const Text( + "OK", + style: TextStyle( + color: ColorsManager.spaceColor, + ), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + ], + ); + }, ), ), ], diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart index 1bc9331e..c8126dbd 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart @@ -52,14 +52,16 @@ class _RoleDropdownState extends State { SizedBox( child: DropdownButtonFormField( dropdownColor: ColorsManager.whiteColors, - alignment: Alignment.center, + // alignment: Alignment., focusColor: Colors.white, autofocus: true, value: selectedRole.isNotEmpty ? selectedRole : null, items: widget.bloc!.roles.map((role) { return DropdownMenuItem( value: role.uuid, - child: Text(role.type), + child: Text( + ' ${role.type[0].toUpperCase()}${role.type.substring(1)}', + ), ); }).toList(), onChanged: (value) { diff --git a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart index aa014bd5..b1131ca4 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart @@ -133,7 +133,10 @@ class UserTableBloc extends Bloc { } else { emit(UsersLoadingState()); currentSortOrder = "Asc"; - users.sort((a, b) => a.firstName!.compareTo(b.firstName!)); + users.sort((a, b) => a.firstName + .toString() + .toLowerCase() + .compareTo(b.firstName.toString().toLowerCase())); emit(UsersLoadedState(users: users)); } } @@ -164,6 +167,7 @@ class UserTableBloc extends Bloc { emit(UsersLoadedState(users: users)); } else { emit(UsersLoadingState()); + currentSortOrder = "NewestToOldest"; users.sort((a, b) { final dateA = _parseDateTime(a.createdDate); final dateB = _parseDateTime(b.createdDate); @@ -188,6 +192,7 @@ class UserTableBloc extends Bloc { final dateB = _parseDateTime(b.createdDate); return dateA.compareTo(dateB); }); + currentSortOrder = "OldestToNewest"; emit(UsersLoadedState(users: users)); } } @@ -210,7 +215,7 @@ class UserTableBloc extends Bloc { final query = event.query.toLowerCase(); final filteredUsers = initialUsers.where((user) { final fullName = "${user.firstName} ${user.lastName}".toLowerCase(); - final email = user.email.toLowerCase() ; + final email = user.email.toLowerCase(); return fullName.contains(query) || email.contains(query); }).toList(); emit(UsersLoadedState(users: filteredUsers)); @@ -256,49 +261,96 @@ class UserTableBloc extends Bloc { void _filterUsersByRole( FilterUsersByRoleEvent event, Emitter emit) { - selectedRoles = event.selectedRoles.toSet(); + selectedRoles = event.selectedRoles!.toSet(); final filteredUsers = initialUsers.where((user) { if (selectedRoles.isEmpty) return true; return selectedRoles.contains(user.roleType); }).toList(); + if (event.sortOrder == "Asc") { + currentSortOrder = "Asc"; + filteredUsers.sort((a, b) => a.firstName + .toString() + .toLowerCase() + .compareTo(b.firstName.toString().toLowerCase())); + } else if (event.sortOrder == "Desc") { + currentSortOrder = "Desc"; + filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!)); + } else { + currentSortOrder = ""; + } + emit(UsersLoadedState(users: filteredUsers)); } void _filterUsersByJobTitle( FilterUsersByJobEvent event, Emitter emit) { - selectedJobTitles = event.selectedJob.toSet(); - + selectedJobTitles = event.selectedJob!.toSet(); + emit(UsersLoadingState()); final filteredUsers = initialUsers.where((user) { if (selectedJobTitles.isEmpty) return true; return selectedJobTitles.contains(user.jobTitle); }).toList(); - + if (event.sortOrder == "Asc") { + currentSortOrder = "Asc"; + filteredUsers.sort((a, b) => a.firstName + .toString() + .toLowerCase() + .compareTo(b.firstName.toString().toLowerCase())); + } else if (event.sortOrder == "Desc") { + currentSortOrder = "Desc"; + filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!)); + } else { + currentSortOrder = ""; + } emit(UsersLoadedState(users: filteredUsers)); } void _filterUsersByCreated( FilterUsersByCreatedEvent event, Emitter emit) { - selectedCreatedBy = event.selectedCreatedBy.toSet(); + selectedCreatedBy = event.selectedCreatedBy!.toSet(); final filteredUsers = initialUsers.where((user) { if (selectedCreatedBy.isEmpty) return true; return selectedCreatedBy.contains(user.invitedBy); }).toList(); + if (event.sortOrder == "Asc") { + currentSortOrder = "Asc"; + filteredUsers.sort((a, b) => a.firstName + .toString() + .toLowerCase() + .compareTo(b.firstName.toString().toLowerCase())); + } else if (event.sortOrder == "Desc") { + currentSortOrder = "Desc"; + filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!)); + } else { + currentSortOrder = ""; + } emit(UsersLoadedState(users: filteredUsers)); } void _filterUserStatus( FilterUsersByDeActevateEvent event, Emitter emit) { - selectedStatuses = event.selectedActivate.toSet(); + selectedStatuses = event.selectedActivate!.toSet(); final filteredUsers = initialUsers.where((user) { if (selectedStatuses.isEmpty) return true; return selectedStatuses.contains(user.status); }).toList(); - + if (event.sortOrder == "Asc") { + currentSortOrder = "Asc"; + filteredUsers.sort((a, b) => a.firstName + .toString() + .toLowerCase() + .compareTo(b.firstName.toString().toLowerCase())); + } else if (event.sortOrder == "Desc") { + currentSortOrder = "Desc"; + filteredUsers.sort((a, b) => b.firstName!.compareTo(a.firstName!)); + } else { + currentSortOrder = ""; + } emit(UsersLoadedState(users: filteredUsers)); } diff --git a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart index a81002ad..1d9567cf 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_event.dart @@ -89,35 +89,36 @@ class DeleteUserEvent extends UserTableEvent { } class FilterUsersByRoleEvent extends UserTableEvent { - final List selectedRoles; + final List? selectedRoles; + final String? sortOrder; - FilterUsersByRoleEvent(this.selectedRoles); - @override - List get props => [selectedRoles]; + const FilterUsersByRoleEvent({this.selectedRoles, this.sortOrder}); + List get props => [selectedRoles, sortOrder]; } class FilterUsersByJobEvent extends UserTableEvent { - final List selectedJob; + final List? selectedJob; + final String? sortOrder; - FilterUsersByJobEvent(this.selectedJob); - @override - List get props => [selectedJob]; + const FilterUsersByJobEvent({this.selectedJob, this.sortOrder}); + List get props => [selectedJob, sortOrder]; } class FilterUsersByCreatedEvent extends UserTableEvent { - final List selectedCreatedBy; + final List? selectedCreatedBy; - FilterUsersByCreatedEvent(this.selectedCreatedBy); - @override - List get props => [selectedCreatedBy]; + final String? sortOrder; + + const FilterUsersByCreatedEvent({this.selectedCreatedBy, this.sortOrder}); + List get props => [selectedCreatedBy, sortOrder]; } class FilterUsersByDeActevateEvent extends UserTableEvent { - final List selectedActivate; + final List? selectedActivate; + final String? sortOrder; - FilterUsersByDeActevateEvent(this.selectedActivate); - @override - List get props => [selectedActivate]; + const FilterUsersByDeActevateEvent({this.selectedActivate, this.sortOrder}); + List get props => [selectedActivate, sortOrder]; } class FilterOptionsEvent extends UserTableEvent { diff --git a/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart b/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart index 6662a9e2..ca641cbe 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart @@ -19,19 +19,13 @@ class DynamicTableScreen extends StatefulWidget { class _DynamicTableScreenState extends State with WidgetsBindingObserver { late List columnWidths; + late double totalWidth; - // @override - // void initState() { - // super.initState(); - // // Initialize column widths with default sizes proportional to the screen width - // // Assigning placeholder values here. The actual sizes will be updated in `build`. - // } @override void initState() { super.initState(); - setState(() { - columnWidths = List.filled(widget.titles.length, 150.0); - }); + columnWidths = List.filled(widget.titles.length, 150.0); + totalWidth = columnWidths.reduce((a, b) => a + b); WidgetsBinding.instance.addObserver(this); } @@ -44,7 +38,6 @@ class _DynamicTableScreenState extends State @override void didChangeMetrics() { super.didChangeMetrics(); - // Screen size might have changed final newScreenWidth = MediaQuery.of(context).size.width; setState(() { columnWidths = List.generate(widget.titles.length, (index) { @@ -64,8 +57,6 @@ class _DynamicTableScreenState extends State @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; - - // Initialize column widths if they are still set to placeholder values if (columnWidths.every((width) => width == 120.0)) { columnWidths = List.generate(widget.titles.length, (index) { if (index == 1) { @@ -77,280 +68,193 @@ class _DynamicTableScreenState extends State }); setState(() {}); } - return Container( - child: SingleChildScrollView( - clipBehavior: Clip.none, - scrollDirection: Axis.horizontal, - child: Container( - decoration: containerDecoration.copyWith( - color: ColorsManager.whiteColors, - borderRadius: const BorderRadius.all(Radius.circular(20))), - child: FittedBox( - child: Column( - children: [ - // Header Row with Resizable Columns - Container( - width: MediaQuery.of(context).size.width, - decoration: containerDecoration.copyWith( - color: ColorsManager.circleRolesBackground, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(15), - topRight: Radius.circular(15))), - child: Row( - children: List.generate(widget.titles.length, (index) { - return Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - FittedBox( - child: Container( - padding: const EdgeInsets.only(left: 5, right: 5), - width: columnWidths[index], - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - child: Text( - widget.titles[index], - maxLines: 2, - style: const TextStyle( - overflow: TextOverflow.ellipsis, - fontWeight: FontWeight.w400, - fontSize: 13, - color: ColorsManager.grayColor, - ), + return SingleChildScrollView( + clipBehavior: Clip.none, + scrollDirection: Axis.horizontal, + child: Container( + decoration: containerDecoration.copyWith( + color: ColorsManager.whiteColors, + borderRadius: const BorderRadius.all(Radius.circular(20))), + child: FittedBox( + child: Column( + children: [ + Container( + width: totalWidth, + decoration: containerDecoration.copyWith( + color: ColorsManager.circleRolesBackground, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15))), + child: Row( + children: List.generate(widget.titles.length, (index) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + FittedBox( + child: Container( + padding: const EdgeInsets.only(left: 5, right: 5), + width: columnWidths[index], + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + child: Text( + widget.titles[index], + maxLines: 2, + style: const TextStyle( + overflow: TextOverflow.ellipsis, + fontWeight: FontWeight.w400, + fontSize: 13, + color: ColorsManager.grayColor, ), ), - if (index != 1 && - index != 9 && - index != 8 && - index != 5) - FittedBox( - child: IconButton( - icon: SvgPicture.asset( - Assets.filterTableIcon, - fit: BoxFit.none, - ), - onPressed: () { - if (widget.onFilter != null) { - widget.onFilter!(index); - } - }, + ), + if (index != 1 && + index != 9 && + index != 8 && + index != 5) + FittedBox( + child: IconButton( + icon: SvgPicture.asset( + Assets.filterTableIcon, + fit: BoxFit.none, ), - ) - ], - ), - ), - ), - GestureDetector( - onHorizontalDragUpdate: (details) { - setState(() { - columnWidths[index] = (columnWidths[index] + - details.delta.dx) - .clamp( - 150.0, 300.0); // Minimum & Maximum size - }); - }, - child: MouseRegion( - cursor: SystemMouseCursors - .resizeColumn, // Set the cursor to resize - child: Container( - color: Colors.green, - child: Container( - color: ColorsManager.boxDivider, - width: 1, - height: 50, // Height of the header cell - ), - ), - ), - ), - ], - ); - }), - ), - ), - // Data Rows with Dividers - widget.rows.isEmpty - ? Container( - child: SizedBox( - height: MediaQuery.of(context).size.height / 2, - child: Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column( - children: [ - SvgPicture.asset(Assets.emptyTable), - const SizedBox( - height: 15, + onPressed: () { + if (widget.onFilter != null) { + widget.onFilter!(index); + } + }, ), - const Text( - 'No Users', - style: TextStyle( - color: ColorsManager.lightGrayColor, - fontSize: 16, - fontWeight: FontWeight.w700), - ) - ], - ), + ) ], ), ), ), - ) - : Center( - child: Container( - // height: MediaQuery.of(context).size.height * 0.59, - width: MediaQuery.of(context).size.width, - decoration: containerDecoration.copyWith( - color: ColorsManager.whiteColors, - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(15), - bottomRight: Radius.circular(15))), - child: ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: widget.rows.length, - itemBuilder: (context, rowIndex) { - if (columnWidths - .every((width) => width == 120.0)) { - columnWidths = List.generate( - widget.titles.length, (index) { - if (index == 1) { - return screenWidth * 0.11; - } else if (index == 9) { - return screenWidth * 0.2; - } + GestureDetector( + onHorizontalDragUpdate: (details) { + setState(() { + columnWidths[index] = + (columnWidths[index] + details.delta.dx) + .clamp(150.0, 300.0); + totalWidth = columnWidths.reduce((a, b) => a + b); + }); + }, + child: MouseRegion( + cursor: SystemMouseCursors.resizeColumn, + child: Container( + color: Colors.green, + child: Container( + color: ColorsManager.boxDivider, + width: 1, + height: 50, + ), + ), + ), + ), + ], + ); + }), + ), + ), + widget.rows.isEmpty + ? SizedBox( + height: MediaQuery.of(context).size.height / 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + SvgPicture.asset(Assets.emptyTable), + const SizedBox( + height: 15, + ), + const Text( + 'No Users', + style: TextStyle( + color: ColorsManager.lightGrayColor, + fontSize: 16, + fontWeight: FontWeight.w700), + ) + ], + ), + ], + ), + ) + : Center( + child: Container( + width: totalWidth, + decoration: containerDecoration.copyWith( + color: ColorsManager.whiteColors, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(15), + bottomRight: Radius.circular(15))), + child: ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: widget.rows.length, + itemBuilder: (context, rowIndex) { + if (columnWidths.every((width) => width == 120.0)) { + columnWidths = List.generate( + widget.titles.length, (index) { + if (index == 1) { return screenWidth * 0.11; - }); - setState(() {}); - } - final row = widget.rows[rowIndex]; - return Column( - children: [ - Container( - child: Padding( - padding: const EdgeInsets.only( - left: 5, - top: 10, - right: 5, - bottom: 10), - child: Row( - children: - List.generate(row.length, (index) { - return SizedBox( - width: columnWidths[index], - child: SizedBox( - child: Padding( - padding: const EdgeInsets.only( - left: 15, right: 10), - child: row[index], - ), - ), - ); - }), - ), - ), - ), - if (rowIndex < widget.rows.length - 1) - Row( - children: List.generate( - widget.titles.length, (index) { + } else if (index == 9) { + return screenWidth * 0.2; + } + return screenWidth * 0.11; + }); + setState(() {}); + } + final row = widget.rows[rowIndex]; + return Column( + children: [ + Container( + child: Padding( + padding: const EdgeInsets.only( + left: 5, top: 10, right: 5, bottom: 10), + child: Row( + children: + List.generate(row.length, (index) { return SizedBox( width: columnWidths[index], - child: const Divider( - color: ColorsManager.boxDivider, - thickness: 1, - height: 1, + child: SizedBox( + child: Padding( + padding: const EdgeInsets.only( + left: 15, right: 10), + child: row[index], + ), ), ); }), ), - ], - ); - }, - ), + ), + ), + if (rowIndex < widget.rows.length - 1) + Row( + children: List.generate( + widget.titles.length, (index) { + return SizedBox( + width: columnWidths[index], + child: const Divider( + color: ColorsManager.boxDivider, + thickness: 1, + height: 1, + ), + ); + }), + ), + ], + ); + }, ), ), - ], - ), + ), + ], ), ), ), ); } } - - - - // Widget build(BuildContext context) { - // return Scaffold( - // body: SingleChildScrollView( - // scrollDirection: Axis.horizontal, - // child: SingleChildScrollView( - // scrollDirection: Axis.vertical, - // child: Column( - // children: [ - // // Header Row with Resizable Columns - // Container( - // color: Colors.green, - // child: Row( - // children: List.generate(widget.titles.length, (index) { - // return Row( - // children: [ - // Container( - // width: columnWidths[index], - // decoration: const BoxDecoration( - // color: Colors.green, - // ), - // child: Text( - // widget.titles[index], - // style: TextStyle(fontWeight: FontWeight.bold), - // textAlign: TextAlign.center, - // ), - // ), - // GestureDetector( - // onHorizontalDragUpdate: (details) { - // setState(() { - // columnWidths[index] = (columnWidths[index] + - // details.delta.dx) - // .clamp(50.0, 300.0); // Minimum & Maximum size - // }); - // }, - // child: MouseRegion( - // cursor: SystemMouseCursors - // .resizeColumn, // Set the cursor to resize - // child: Container( - // color: Colors.green, - // child: Container( - // color: Colors.black, - // width: 1, - // height: 50, // Height of the header cell - // ), - // ), - // ), - // ), - // ], - // ); - // }), - // ), - // ), - // // Data Rows - // ...widget.rows.map((row) { - // return Row( - // children: List.generate(row.length, (index) { - // return Container( - // width: columnWidths[index], - // child: row[index], - // ); - // }), - // ); - // }).toList(), - // ], - // ), - // ), - // ), - // ); - // } \ No newline at end of file diff --git a/lib/pages/roles_and_permission/users_page/users_table/view/users_page.dart b/lib/pages/roles_and_permission/users_page/users_table/view/users_page.dart index 1c93d44f..dae47196 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/view/users_page.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/view/users_page.dart @@ -107,7 +107,6 @@ class UsersPage extends StatelessWidget { builder: (context, state) { final screenSize = MediaQuery.of(context).size; final _blocRole = BlocProvider.of(context); - if (state is UsersLoadingState) { _blocRole.add(ChangePage(_blocRole.currentPage)); return const Center(child: CircularProgressIndicator()); @@ -189,8 +188,6 @@ class UsersPage extends StatelessWidget { const SizedBox(height: 25), DynamicTableScreen( onFilter: (columnIndex) { - _blocRole.add(FilterClearEvent()); - if (columnIndex == 0) { showNameMenu( context: context, @@ -210,11 +207,12 @@ class UsersPage extends StatelessWidget { if (columnIndex == 2) { final Map checkboxStates = { for (var item in _blocRole.jobTitle) - item: false, // Initialize with false + item: _blocRole.selectedJobTitles.contains(item), }; final RenderBox overlay = Overlay.of(context) .context .findRenderObject() as RenderBox; + showPopUpFilterMenu( position: RelativeRect.fromLTRB( overlay.size.width / 4, @@ -225,26 +223,28 @@ class UsersPage extends StatelessWidget { list: _blocRole.jobTitle, context: context, checkboxStates: checkboxStates, + isSelected: _blocRole.currentSortOrder, onOkPressed: () { + _blocRole.add(FilterClearEvent()); final selectedItems = checkboxStates.entries .where((entry) => entry.value) .map((entry) => entry.key) .toList(); Navigator.of(context).pop(); - _blocRole.add(FilterUsersByJobEvent(selectedItems)); + _blocRole.add(FilterUsersByJobEvent( + selectedJob: selectedItems, + sortOrder: _blocRole.currentSortOrder, + )); }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); + onSortAtoZ: (v) { + _blocRole.currentSortOrder = v; }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); + onSortZtoA: (v) { + _blocRole.currentSortOrder = v; }, ); } + if (columnIndex == 3) { final Map checkboxStates = { for (var item in _blocRole.roleTypes) @@ -263,32 +263,31 @@ class UsersPage extends StatelessWidget { list: _blocRole.roleTypes, context: context, checkboxStates: checkboxStates, + isSelected: _blocRole.currentSortOrder, onOkPressed: () { + _blocRole.add(FilterClearEvent()); final selectedItems = checkboxStates.entries .where((entry) => entry.value) .map((entry) => entry.key) .toList(); Navigator.of(context).pop(); - context - .read() - .add(FilterUsersByRoleEvent(selectedItems)); + context.read().add( + FilterUsersByRoleEvent( + selectedRoles: selectedItems, + sortOrder: _blocRole.currentSortOrder)); }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); + onSortAtoZ: (v) { + _blocRole.currentSortOrder = v; }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); + onSortZtoA: (v) { + _blocRole.currentSortOrder = v; }, ); } if (columnIndex == 4) { showDateFilterMenu( context: context, - isSelected: _blocRole.currentSortOrderDate, + isSelected: _blocRole.currentSortOrder, aToZTap: () { context .read() @@ -319,32 +318,30 @@ class UsersPage extends StatelessWidget { list: _blocRole.createdBy, context: context, checkboxStates: checkboxStates, + isSelected: _blocRole.currentSortOrder, onOkPressed: () { + _blocRole.add(FilterClearEvent()); final selectedItems = checkboxStates.entries .where((entry) => entry.value) .map((entry) => entry.key) .toList(); Navigator.of(context).pop(); - _blocRole - .add(FilterUsersByCreatedEvent(selectedItems)); + _blocRole.add(FilterUsersByCreatedEvent( + selectedCreatedBy: selectedItems, + sortOrder: _blocRole.currentSortOrder)); }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); + onSortAtoZ: (v) { + _blocRole.currentSortOrder = v; }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); + onSortZtoA: (v) { + _blocRole.currentSortOrder = v; }, ); } - if (columnIndex == 7) { final Map checkboxStates = { for (var item in _blocRole.status) - item: _blocRole.selectedCreatedBy.contains(item), + item: _blocRole.selectedStatuses.contains(item), }; final RenderBox overlay = Overlay.of(context) .context @@ -359,24 +356,24 @@ class UsersPage extends StatelessWidget { list: _blocRole.status, context: context, checkboxStates: checkboxStates, + isSelected: _blocRole.currentSortOrder, onOkPressed: () { + _blocRole.add(FilterClearEvent()); + final selectedItems = checkboxStates.entries .where((entry) => entry.value) .map((entry) => entry.key) .toList(); Navigator.of(context).pop(); - _blocRole - .add(FilterUsersByCreatedEvent(selectedItems)); + _blocRole.add(FilterUsersByDeActevateEvent( + selectedActivate: selectedItems, + sortOrder: _blocRole.currentSortOrder)); }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); + onSortAtoZ: (v) { + _blocRole.currentSortOrder = v; }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); + onSortZtoA: (v) { + _blocRole.currentSortOrder = v; }, ); } @@ -412,8 +409,8 @@ class UsersPage extends StatelessWidget { rows: state.users.map((user) { return [ Text('${user.firstName} ${user.lastName}'), - Text(user.email ), - Text(user.jobTitle ?? ''), + Text(user.email), + Text(user.jobTitle ?? '-'), Text(user.roleType ?? ''), Text(user.createdDate ?? ''), Text(user.createdTime ?? ''), @@ -476,11 +473,17 @@ class UsersPage extends StatelessWidget { barrierDismissible: false, builder: (BuildContext context) { return DeleteUserDialog( - onTapDelete: () { + onTapDelete: () async { + try { _blocRole.add(DeleteUserEvent( user.uuid, context)); - }, - ); + await Future.delayed( + const Duration(seconds: 2)); + return true; + } catch (e) { + return false; + } + }); }, ).then((v) { if (v != null) { @@ -504,6 +507,7 @@ class UsersPage extends StatelessWidget { SizedBox( width: 500, child: NumberPagination( + visiblePagesCount: 4, buttonRadius: 10, selectedButtonColor: ColorsManager.secondaryColor, buttonUnSelectedBorderColor: diff --git a/lib/services/user_permission.dart b/lib/services/user_permission.dart index ab05523f..527010d0 100644 --- a/lib/services/user_permission.dart +++ b/lib/services/user_permission.dart @@ -71,8 +71,8 @@ class UserPermissionApi { "firstName": firstName, "lastName": lastName, "email": email, - "jobTitle": jobTitle != '' ? jobTitle : " ", - "phoneNumber": phoneNumber != '' ? phoneNumber : " ", + "jobTitle": jobTitle != '' ? jobTitle : null, + "phoneNumber": phoneNumber != '' ? phoneNumber : null, "roleUuid": roleUuid, "projectUuid": "0e62577c-06fa-41b9-8a92-99a21fbaf51c", "spaceUuids": spaceUuids, @@ -119,13 +119,8 @@ class UserPermissionApi { ); return response ?? 'Unknown error occurred'; } on DioException catch (e) { - if (e.response != null) { - final errorMessage = e.response?.data['error']; - return errorMessage is String - ? errorMessage - : 'Error occurred while checking email'; - } - return 'Error occurred while checking email'; + final errorMessage = e.response?.data['error']; + return errorMessage; } catch (e) { return e.toString(); } From eb7eeebf1860b0b3fcdcc751542fa983b526409e Mon Sep 17 00:00:00 2001 From: mohammad Date: Mon, 13 Jan 2025 11:07:18 +0300 Subject: [PATCH 2/4] fixes add user view and table and user status --- .../add_user_dialog/view/add_user_dialog.dart | 3 +- .../add_user_dialog/view/basics_view.dart | 46 ++++++++++--------- .../view/permission_management.dart | 6 +-- .../view/popup_menu_filter.dart | 4 +- .../users_table/bloc/user_table_bloc.dart | 2 +- .../users_table/view/user_table.dart | 8 ++-- 6 files changed, 37 insertions(+), 32 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 f29aec8e..700e8f46 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 @@ -237,10 +237,11 @@ class _AddNewUserDialogState extends State { onTap: () { setState(() { currentStep = step; - bloc.add(CheckStepStatus(isEditUser: false)); + bloc.add(const CheckStepStatus(isEditUser: false)); if (step3 == 3) { bloc.add(const CheckRoleStepStatus()); } + }); }, child: Column( 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 c5025fc3..7261ba50 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 @@ -47,7 +47,9 @@ class BasicsView extends StatelessWidget { ), Row( children: [ - Expanded( + SizedBox( + width: MediaQuery.of(context).size.width * 0.18, + height: MediaQuery.of(context).size.width * 0.08, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -76,12 +78,12 @@ class BasicsView extends StatelessWidget { child: TextFormField( style: const TextStyle(color: ColorsManager.blackColor), - onChanged: (value) { - Future.delayed(const Duration(milliseconds: 200), - () { - _blocRole.add(ValidateBasicsStep()); - }); - }, + // onChanged: (value) { + // Future.delayed(const Duration(milliseconds: 200), + // () { + // _blocRole.add(const ValidateBasicsStep()); + // }); + // }, controller: _blocRole.firstNameController, decoration: inputTextFormDeco( hintText: "Enter first name", @@ -103,7 +105,9 @@ class BasicsView extends StatelessWidget { ), ), const SizedBox(width: 10), - Expanded( + SizedBox( + width: MediaQuery.of(context).size.width * 0.18, + height: MediaQuery.of(context).size.width * 0.08, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -128,12 +132,12 @@ class BasicsView extends StatelessWidget { Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( - onChanged: (value) { - Future.delayed(const Duration(milliseconds: 200), - () { - _blocRole.add(ValidateBasicsStep()); - }); - }, + // onChanged: (value) { + // Future.delayed(const Duration(milliseconds: 200), + // () { + // _blocRole.add(ValidateBasicsStep()); + // }); + // }, controller: _blocRole.lastNameController, style: const TextStyle(color: Colors.black), decoration: @@ -186,13 +190,13 @@ class BasicsView extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: TextFormField( enabled: userId != '' ? false : true, - onChanged: (value) { - Future.delayed(const Duration(milliseconds: 200), () { - _blocRole.add(CheckStepStatus( - isEditUser: userId != '' ? false : true)); - _blocRole.add(ValidateBasicsStep()); - }); - }, + // onChanged: (value) { + // Future.delayed(const Duration(milliseconds: 200), () { + // _blocRole.add(CheckStepStatus( + // isEditUser: userId != '' ? false : true)); + // _blocRole.add(ValidateBasicsStep()); + // }); + // }, controller: _blocRole.emailController, style: const TextStyle(color: ColorsManager.blackColor), decoration: inputTextFormDeco(hintText: "name@example.com") diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart index 266d431e..c5c38e76 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart @@ -128,7 +128,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - option.title, + ' ${option.title[0].toUpperCase()}${option.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w700, fontSize: 12, @@ -184,7 +184,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - subOption.title, + ' ${subOption.title[0].toUpperCase()}${subOption.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w700, fontSize: 12, @@ -246,7 +246,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - child.title, + ' ${child.title[0].toUpperCase()}${child.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w400, fontSize: 12, diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart index c3a245c1..80228657 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart @@ -5,8 +5,8 @@ import 'package:syncrow_web/utils/style.dart'; Future showPopUpFilterMenu({ required BuildContext context, - required Function(String value)? onSortAtoZ, // Accept a parameter - required Function(String value)? onSortZtoA, // Accept a parameter + required Function(String value)? onSortAtoZ, + required Function(String value)? onSortZtoA, Function()? cancelButton, required Map checkboxStates, required RelativeRect position, diff --git a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart index b1131ca4..c50667be 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_bloc.dart @@ -93,7 +93,7 @@ class UserTableBloc extends Bloc { try { emit(UsersLoadingState()); bool res = await UserPermissionApi().changeUserStatusById( - event.userId, event.newStatus == "disabled" ? true : false); + event.userId, event.newStatus == "disabled" ? false : true); if (res == true) { add(const GetUsers()); // users = users.map((user) { diff --git a/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart b/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart index ca641cbe..92229643 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/view/user_table.dart @@ -46,7 +46,7 @@ class _DynamicTableScreenState extends State 0.12; // 20% of screen width for the second column } else if (index == 9) { return newScreenWidth * - 0.2; // 25% of screen width for the tenth column + 0.1; // 25% of screen width for the tenth column } return newScreenWidth * 0.09; // Default to 10% of screen width for other columns @@ -57,14 +57,14 @@ class _DynamicTableScreenState extends State @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; - if (columnWidths.every((width) => width == 120.0)) { + if (columnWidths.every((width) => width == screenWidth * 7)) { columnWidths = List.generate(widget.titles.length, (index) { if (index == 1) { return screenWidth * 0.11; } else if (index == 9) { - return screenWidth * 0.2; + return screenWidth * 0.1; } - return screenWidth * 0.11; + return screenWidth * 0.09; }); setState(() {}); } From 20a9f19480314d00a51b2536e7da7f79f3cc4834 Mon Sep 17 00:00:00 2001 From: mohammad Date: Mon, 13 Jan 2025 14:36:17 +0300 Subject: [PATCH 3/4] check if title is not empty and remove nullable --- .../add_user_dialog/view/add_user_dialog.dart | 2 +- .../users_page/add_user_dialog/view/basics_view.dart | 1 - .../add_user_dialog/view/permission_management.dart | 6 +++--- .../add_user_dialog/view/popup_menu_filter.dart | 12 ++++++------ 4 files changed, 10 insertions(+), 11 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 700e8f46..ec35b3fd 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 @@ -155,7 +155,7 @@ class _AddNewUserDialogState extends State { userId: '', ); case 2: - return SpacesAccessView(); + return const SpacesAccessView(); case 3: return const RolesAndPermission(); default: 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 7261ba50..53d9a333 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 @@ -4,7 +4,6 @@ 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'; diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart index c5c38e76..aee84ed4 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/permission_management.dart @@ -128,7 +128,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - ' ${option.title[0].toUpperCase()}${option.title.substring(1)}', + ' ${option.title.isNotEmpty ? option.title[0].toUpperCase() : ''}${option.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w700, fontSize: 12, @@ -184,7 +184,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - ' ${subOption.title[0].toUpperCase()}${subOption.title.substring(1)}', + ' ${subOption.title.isNotEmpty ? subOption.title[0].toUpperCase() : ''}${subOption.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w700, fontSize: 12, @@ -246,7 +246,7 @@ class _PermissionManagementState extends State { ), const SizedBox(width: 8), Text( - ' ${child.title[0].toUpperCase()}${child.title.substring(1)}', + ' ${child.title.isNotEmpty ? child.title[0].toUpperCase() : ''}${child.title.substring(1)}', style: context.textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w400, fontSize: 12, diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart index 80228657..120a1a3a 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/popup_menu_filter.dart @@ -5,8 +5,8 @@ import 'package:syncrow_web/utils/style.dart'; Future showPopUpFilterMenu({ required BuildContext context, - required Function(String value)? onSortAtoZ, - required Function(String value)? onSortZtoA, + required Function(String value) onSortAtoZ, + required Function(String value) onSortZtoA, Function()? cancelButton, required Map checkboxStates, required RelativeRect position, @@ -35,9 +35,9 @@ Future showPopUpFilterMenu({ setState(() { if (isSelected == 'Asc') { isSelected = null; - onSortAtoZ?.call(''); + onSortAtoZ.call(''); } else { - onSortAtoZ?.call('Asc'); + onSortAtoZ.call('Asc'); isSelected = 'Asc'; } }); @@ -60,9 +60,9 @@ Future showPopUpFilterMenu({ setState(() { if (isSelected == 'Desc') { isSelected = null; - onSortZtoA?.call(''); + onSortZtoA.call(''); } else { - onSortZtoA?.call('Desc'); + onSortZtoA.call('Desc'); isSelected = 'Desc'; } }); From db7eaa53afadeb986fd2c0793b524892a9ceda14 Mon Sep 17 00:00:00 2001 From: mohammad Date: Mon, 13 Jan 2025 15:40:38 +0300 Subject: [PATCH 4/4] check type isNotEmpty --- .../users_page/add_user_dialog/view/role_dropdown.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart index c8126dbd..3a5ac65c 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/view/role_dropdown.dart @@ -60,7 +60,7 @@ class _RoleDropdownState extends State { return DropdownMenuItem( value: role.uuid, child: Text( - ' ${role.type[0].toUpperCase()}${role.type.substring(1)}', + ' ${role.type.isNotEmpty ? role.type[0].toUpperCase() : ''}${role.type.substring(1)}', ), ); }).toList(),