From fe8f8160ec676c91e1d50ae1fe226154c5aedcfb Mon Sep 17 00:00:00 2001 From: mohammad Date: Mon, 6 Jan 2025 14:20:57 +0300 Subject: [PATCH] filter --- .../add_user_dialog/bloc/users_bloc.dart | 31 +- .../add_user_dialog/bloc/users_event.dart | 7 - .../view/popup_menu_filter.dart | 96 ++- .../users_table/bloc/user_table_bloc.dart | 95 ++- .../users_table/bloc/user_table_event.dart | 16 + .../users_table/bloc/user_table_state.dart | 9 + .../users_table/view/user_table.dart | 2 +- .../users_table/view/users_page.dart | 737 ++++++++++-------- 8 files changed, 580 insertions(+), 413 deletions(-) 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 730825cb..c06c0969 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 @@ -30,8 +30,8 @@ class UsersBloc extends Bloc { on(_onToggleNodeExpansion); on(_onToggleNodeCheck); on(_editInvitUser); - } + void _validateBasicsStep(ValidateBasicsStep event, Emitter emit) { if (formKey.currentState?.validate() ?? false) { emit(const BasicsStepValidState()); @@ -381,7 +381,7 @@ class UsersBloc extends Bloc { // Create a list of UUIDs to mark final uuidsToMark = res.spaces.map((space) => space.uuid).toList(); // Print all IDs and mark nodes in updatedCommunities - print('Printing and marking nodes in updatedCommunities:'); + debugPrint('Printing and marking nodes in updatedCommunities:'); _printAndMarkNodes(updatedCommunities, uuidsToMark); } else { print('updatedCommunities is empty!'); @@ -391,34 +391,27 @@ class UsersBloc extends Bloc { element.type == res.roleType.toString().toLowerCase().replaceAll("_", " ")) .uuid; - print('Role ID: $roleId'); + debugPrint('Role ID: $roleId'); roleSelected = roleId; add(PermissionEvent(roleUuid: roleSelected)); emit(ChangeStatusSteps()); - } else { - // emit(UsersErrorState("User not found")); - } - } else { - // emit(UsersErrorState("Invalid user ID")); - } + } else {} + } else {} } catch (e) { print("Failed to fetch user data: $e"); - // emit(UsersErrorState("Failed to fetch user data: $e")); } } - /// Recursively print all the node IDs, including nested children. - /// Recursively print all node IDs and mark nodes as `isChecked` if their UUID exists in the list. void _printAndMarkNodes(List nodes, List uuidsToMark, [int level = 0]) { for (final node in nodes) { - // Check if the current node's UUID exists in the list of UUIDs to mark. if (uuidsToMark.contains(node.uuid)) { - node.isChecked = true; // Mark the node as checked. - print( + node.isChecked = true; + debugPrint( '${' ' * level}MATCH FOUND: Node ID: ${node.uuid}, Title: ${node.title} is marked as checked.'); } else { - print('${' ' * level}Node ID: ${node.uuid}, Title: ${node.title}'); + debugPrint( + '${' ' * level}Node ID: ${node.uuid}, Title: ${node.title}'); } if (node.children.isNotEmpty) { _printAndMarkNodes(node.children, uuidsToMark, level + 1); @@ -453,8 +446,6 @@ class UsersBloc extends Bloc { emit(ChangeStatusSteps()); } -// Existing methods that remain in the BLoC: - void _updateChildrenCheckStatus(TreeNode node, bool isChecked) { for (var child in node.children) { child.isChecked = isChecked; @@ -477,7 +468,6 @@ class UsersBloc extends Bloc { (child.children.isEmpty || _areAllChildrenChecked(child))); } -// Private helper method to find the parent of a given node. TreeNode? _findParent(List nodes, TreeNode target) { for (var node in nodes) { if (node.children.contains(target)) { @@ -490,7 +480,4 @@ class UsersBloc extends Bloc { } return null; } - - - } diff --git a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart index 0f4631ff..c193bbf3 100644 --- a/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart +++ b/lib/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart @@ -129,8 +129,6 @@ class UpdateNodeCheckStatus extends UsersEvent { @override List get props => [node]; } - -// Define new events class ToggleNodeHighlightEvent extends UsersEvent { final TreeNode node; @@ -161,14 +159,9 @@ class ToggleNodeCheckEvent extends UsersEvent { @override List get props => []; } - -// users_event.dart - -// 1. Extend UsersEvent class ToggleNodeCheck extends UsersEvent { final TreeNode node; - // 2. Add a constructor that takes the node to toggle ToggleNodeCheck(this.node); @override List get props => []; 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 02eac036..fbadd07e 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 @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; +import 'package:syncrow_web/utils/style.dart'; Future showPopUpFilterMenu({ required BuildContext context, @@ -8,20 +11,18 @@ Future showPopUpFilterMenu({ Function()? onSortZtoA, Function()? cancelButton, required Map checkboxStates, + required RelativeRect position, + // Function(String)? onTextFieldChanged, Function()? onOkPressed, List? list, }) async { - final RenderBox overlay = - Overlay.of(context).context.findRenderObject() as RenderBox; + await showMenu( context: context, - position: RelativeRect.fromLTRB( - overlay.size.width / 4, - 240, - overlay.size.width / 4, - 0, - ), + position:position, + + color: ColorsManager.whiteColors, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10)), @@ -55,28 +56,69 @@ Future showPopUpFilterMenu({ ), const PopupMenuDivider(), const PopupMenuItem( - child: Text( - "Filter by Status", - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), + 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: SizedBox( + 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: ListView.builder( - itemCount: list?.length ?? 0, - itemBuilder: (context, index) { - final item = list![index]; - return CheckboxListTile( - title: Text(item), - value: checkboxStates[item], - onChanged: (bool? newValue) { - checkboxStates[item] = newValue ?? false; - (context as Element).markNeedsBuild(); - }, - ); - }, + 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(); + }, + ); + }, + ), ), ), ), 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 82212103..cdfef350 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 @@ -19,8 +19,9 @@ class UserTableBloc extends Bloc { on(_filterUsersByRole); on(_filterUsersByJobTitle); on(_filterUsersByCreated); - on(_filterUserActevate); + on(_filterUserStatus); on(_deleteUser); + on(_filterClear); } int itemsPerPage = 10; int currentPage = 1; @@ -31,7 +32,7 @@ class UserTableBloc extends Bloc { List roleTypes = []; List jobTitle = []; List createdBy = []; - List deActivate = []; + List status = ['active', 'invited', 'disabled']; Future _getUsers(GetUsers event, Emitter emit) async { emit(UsersLoadingState()); @@ -39,8 +40,14 @@ class UserTableBloc extends Bloc { roleTypes.clear(); jobTitle.clear(); createdBy.clear(); - deActivate.clear(); + // deActivate.clear(); users = await UserPermissionApi().fetchUsers(); + + users.sort((a, b) { + final dateA = _parseDateTime(a.createdDate); + final dateB = _parseDateTime(b.createdDate); + return dateB.compareTo(dateA); + }); for (var user in users) { roleTypes.add(user.roleType.toString()); } @@ -50,20 +57,14 @@ class UserTableBloc extends Bloc { for (var user in users) { createdBy.add(user.invitedBy.toString()); } - for (var user in users) { - deActivate.add(user.status.toString()); - } + // for (var user in users) { + // deActivate.add(user.status.toString()); + // } + initialUsers = List.from(users); roleTypes = roleTypes.toSet().toList(); jobTitle = jobTitle.toSet().toList(); createdBy = createdBy.toSet().toList(); - deActivate = deActivate.toSet().toList(); - - users.sort((a, b) { - final dateA = _parseDateTime(a.createdDate); - final dateB = _parseDateTime(b.createdDate); - return dateB.compareTo(dateA); - }); - initialUsers = List.from(users); + // deActivate = deActivate.toSet().toList(); _handlePageChange(ChangePage(1), emit); emit(UsersLoadedState(users: users)); } catch (e) { @@ -127,7 +128,7 @@ class UserTableBloc extends Bloc { if (currentSortOrder == "Asc") { emit(UsersLoadingState()); currentSortOrder = ""; - users = List.from(initialUsers); + users = List.from(users); emit(UsersLoadedState(users: users)); } else { emit(UsersLoadingState()); @@ -248,39 +249,83 @@ class UserTableBloc extends Bloc { emit(UsersLoadedState(users: paginatedUsers)); } + Set selectedRoles = {}; + Set selectedJobTitles = {}; + Set selectedCreatedBy = {}; + Set selectedStatuses = {}; + void _filterUsersByRole( FilterUsersByRoleEvent event, Emitter emit) { - emit(UsersLoadingState()); + selectedRoles = event.selectedRoles.toSet(); + final filteredUsers = initialUsers.where((user) { - return event.selectedRoles.contains(user.roleType); + if (selectedRoles.isEmpty) return true; + return selectedRoles.contains(user.roleType); }).toList(); + emit(UsersLoadedState(users: filteredUsers)); } void _filterUsersByJobTitle( FilterUsersByJobEvent event, Emitter emit) { - emit(UsersLoadingState()); - final filteredUsers = users.where((user) { - return event.selectedJob.contains(user.jobTitle); + selectedJobTitles = event.selectedJob.toSet(); + + final filteredUsers = initialUsers.where((user) { + if (selectedJobTitles.isEmpty) return true; + return selectedJobTitles.contains(user.jobTitle); }).toList(); + emit(UsersLoadedState(users: filteredUsers)); } void _filterUsersByCreated( FilterUsersByCreatedEvent event, Emitter emit) { - emit(UsersLoadingState()); + selectedCreatedBy = event.selectedCreatedBy.toSet(); + final filteredUsers = initialUsers.where((user) { - return event.selectedCreatedBy.contains(user.invitedBy); + if (selectedCreatedBy.isEmpty) return true; + return selectedCreatedBy.contains(user.invitedBy); }).toList(); + emit(UsersLoadedState(users: filteredUsers)); } - void _filterUserActevate( + void _filterUserStatus( FilterUsersByDeActevateEvent event, Emitter emit) { - emit(UsersLoadingState()); + selectedStatuses = event.selectedActivate.toSet(); + final filteredUsers = initialUsers.where((user) { - return event.selectedActivate.contains(user.status); + if (selectedStatuses.isEmpty) return true; + return selectedStatuses.contains(user.status); }).toList(); + emit(UsersLoadedState(users: filteredUsers)); } + + void _resetAllFilters(Emitter emit) { + selectedRoles.clear(); + selectedJobTitles.clear(); + selectedCreatedBy.clear(); + selectedStatuses.clear(); + emit(UsersLoadedState(users: initialUsers)); + } + + void _filterClear(FilterClearEvent event, Emitter emit) { + selectedRoles.clear(); + selectedJobTitles.clear(); + selectedCreatedBy.clear(); + selectedStatuses.clear(); + emit(UsersLoadedState(users: initialUsers)); + } } + // void _filterOptions(FilterOptionsEvent event, Emitter emit) { + // try { + // final query = event.query.toLowerCase(); + // final filteredOptions = event.fullOptions + // .where((option) => option.toLowerCase().contains(query)) + // .toList(); + // emit(FilterOptionsState(filteredOptions)); + // } catch (e) { + // emit(ErrorState(e.toString())); + // } + // } \ No newline at end of file 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 dbcd9a26..a81002ad 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 @@ -119,3 +119,19 @@ class FilterUsersByDeActevateEvent extends UserTableEvent { @override List get props => [selectedActivate]; } + +class FilterOptionsEvent extends UserTableEvent { + final String query; + final List fullOptions; + + FilterOptionsEvent({required this.query, required this.fullOptions}); + + @override + List get props => [query, fullOptions]; +} + +class FilterClearEvent extends UserTableEvent { + FilterClearEvent(); + @override + List get props => []; +} diff --git a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart index 2a132947..2433f9f5 100644 --- a/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart +++ b/lib/pages/roles_and_permission/users_page/users_table/bloc/user_table_state.dart @@ -80,3 +80,12 @@ final class ChangeTapStatus extends UserTableState { @override List get props => [select]; } + +class FilterOptionsState extends UserTableState { + final List filteredOptions; + + FilterOptionsState(this.filteredOptions); + + @override + List get props => [filteredOptions]; +} 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 4f777ee3..813e950c 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 @@ -122,7 +122,7 @@ class _DynamicTableScreenState extends State ), if (index != 1 && index != 9 && - index != 7 && + index != 8 && index != 5) FittedBox( child: IconButton( 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 8d838ba2..3a9f2187 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 @@ -110,350 +110,425 @@ class UsersPage extends StatelessWidget { if (state is UsersLoadingState) { _blocRole.add(ChangePage(_blocRole.currentPage)); - return const Center(child: CircularProgressIndicator()); } else if (state is UsersLoadedState) { return Padding( padding: const EdgeInsets.all(20), - child: ListView( - shrinkWrap: true, - children: [ - Row( - children: [ - Container( - decoration: containerDecoration.copyWith( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - ), - width: screenSize.width * 0.4, - child: TextFormField( - controller: searchController, - onChanged: (value) { - context.read().add(SearchUsers(value)); - }, - 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, - ), - ), - ), - ), - ), - const SizedBox(width: 20), - InkWell( - onTap: () { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return const AddNewUserDialog(); - }, - ).then((v) { - if (v != null) { - _blocRole.add(const GetUsers()); - } - }); - }, - child: Container( - decoration: containerWhiteDecoration, - width: screenSize.width * 0.18, - height: 50, - child: const Center( - child: Text( - 'Add New User', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - color: ColorsManager.blueColor, - ), - ), - ), - ), - ), - ], - ), - const SizedBox(height: 25), - DynamicTableScreen( - onFilter: (columnIndex) { - if (columnIndex == 0) { - showNameMenu( - context: context, - isSelected: _blocRole.currentSortOrder, - aToZTap: () { - context - .read() - .add(const SortUsersByNameAsc()); - }, - zToaTap: () { - context - .read() - .add(const SortUsersByNameDesc()); - }, - ); - } - if (columnIndex == 2) { - final Map checkboxStates = { - for (var item in _blocRole.jobTitle) - item: false, // Initialize with false - }; - - showPopUpFilterMenu( - list: _blocRole.jobTitle, - context: context, - checkboxStates: checkboxStates, - onOkPressed: () { - final selectedItems = checkboxStates.entries - .where((entry) => entry.value) - .map((entry) => entry.key) - .toList(); - Navigator.of(context).pop(); - _blocRole.add(FilterUsersByJobEvent(selectedItems)); - }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); - }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); - }, - ); - } - if (columnIndex == 3) { - final Map checkboxStates = { - for (var item in _blocRole.roleTypes) - item: false, // Initialize with false - }; - - showPopUpFilterMenu( - list: _blocRole.roleTypes, - context: context, - checkboxStates: checkboxStates, - onOkPressed: () { - final selectedItems = checkboxStates.entries - .where((entry) => entry.value) - .map((entry) => entry.key) - .toList(); - Navigator.of(context).pop(); - _blocRole.add(FilterUsersByRoleEvent(selectedItems)); - }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); - }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); - }, - ); - } - if (columnIndex == 4) { - showDateFilterMenu( - context: context, - isSelected: _blocRole.currentSortOrderDate, - aToZTap: () { - context - .read() - .add(const DateNewestToOldestEvent()); - }, - zToaTap: () { - context - .read() - .add(const DateOldestToNewestEvent()); - }, - ); - } - if (columnIndex == 6) { - final Map checkboxStates = { - for (var item in _blocRole.createdBy) - item: false, // Initialize with false - }; - - showPopUpFilterMenu( - list: _blocRole.createdBy, - context: context, - checkboxStates: checkboxStates, - onOkPressed: () { - final selectedItems = checkboxStates.entries - .where((entry) => entry.value) - .map((entry) => entry.key) - .toList(); - Navigator.of(context).pop(); - _blocRole - .add(FilterUsersByCreatedEvent(selectedItems)); - }, - onSortAtoZ: () { - context - .read() - .add(const SortUsersByNameAsc()); - }, - onSortZtoA: () { - context - .read() - .add(const SortUsersByNameDesc()); - }, - ); - } - if (columnIndex == 8) { - showDeActivateFilterMenu( - context: context, - isSelected: _blocRole.currentSortOrderDate, - aToZTap: () { - context - .read() - .add(const DateNewestToOldestEvent()); - }, - zToaTap: () { - context - .read() - .add(const DateOldestToNewestEvent()); - }, - ); - } - }, - titles: const [ - "Full Name", - "Email Address", - "Job Title", - "Role", - "Creation Date", - "Creation Time", - "Created By", - "Status", - "De/Activate", - "Action" - ], - rows: state.users.map((user) { - return [ - Text('${user.firstName} ${user.lastName}'), - Text(user.email ?? ''), - Text(user.jobTitle ?? ''), - Text(user.roleType ?? ''), - Text(user.createdDate ?? ''), - Text(user.createdTime ?? ''), - Text(user.invitedBy), - changeIconStatus( - status: - user.isEnabled == false ? 'disabled' : user.status, - userId: user.uuid, - onTap: user.status != "invited" - ? () { - final newStatus = user.status == 'active' - ? 'disabled' - : user.status == 'disabled' - ? 'invited' - : 'active'; - context.read().add( - ChangeUserStatus( - userId: user.uuid, - newStatus: user.isEnabled == false - ? 'disabled' - : user.status)); - } - : null, - ), - status( - status: - user.isEnabled == false ? 'disabled' : user.status, - ), - Row( - children: [ - // actionButton( - // title: "Activity Log", - // onTap: () {}, - // ), - actionButton( - title: "Edit", - onTap: () { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return EditUserDialog(userId: user.uuid); - }, - ).then((v) { - if (v != null) { - if (v != null) { - _blocRole.add(const GetUsers()); - } - } - }); - }, - ), - actionButton( - title: "Delete", - onTap: () { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return DeleteUserDialog( - onTapDelete: () { - _blocRole.add( - DeleteUserEvent(user.uuid, context)); - }, - ); - }, - ).then((v) { - if (v != null) { - if (v != null) { - _blocRole.add(const GetUsers()); - } - } - }); - }, - ), - ], - ), - ]; - }).toList(), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, + child: Align( + alignment: Alignment.topCenter, + child: ListView( + shrinkWrap: true, + children: [ + Row( children: [ Container( - width: 500, - child: NumberPagination( - buttonRadius: 10, - selectedButtonColor: ColorsManager.secondaryColor, - buttonUnSelectedBorderColor: ColorsManager.grayBorder, - lastPageIcon: - const Icon(Icons.keyboard_double_arrow_right), - firstPageIcon: - const Icon(Icons.keyboard_double_arrow_left), - totalPages: - (_blocRole.users.length / _blocRole.itemsPerPage) - .ceil(), - currentPage: _blocRole.currentPage, - onPageChanged: (int pageNumber) { - _blocRole.currentPage = pageNumber; + decoration: containerDecoration.copyWith( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + ), + width: screenSize.width * 0.4, + child: TextFormField( + controller: searchController, + onChanged: (value) { context .read() - .add(ChangePage(pageNumber)); + .add(SearchUsers(value)); }, + 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, + ), + ), + ), + ), + ), + const SizedBox(width: 20), + InkWell( + onTap: () { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return const AddNewUserDialog(); + }, + ).then((v) { + if (v != null) { + _blocRole.add(const GetUsers()); + } + }); + }, + child: Container( + decoration: containerWhiteDecoration, + width: screenSize.width * 0.18, + height: 50, + child: const Center( + child: Text( + 'Add New User', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + color: ColorsManager.blueColor, + ), + ), + ), ), ), ], ), - ), - ], + const SizedBox(height: 25), + DynamicTableScreen( + onFilter: (columnIndex) { + _blocRole.add(FilterClearEvent()); + + if (columnIndex == 0) { + showNameMenu( + context: context, + isSelected: _blocRole.currentSortOrder, + aToZTap: () { + context + .read() + .add(const SortUsersByNameAsc()); + }, + zToaTap: () { + context + .read() + .add(const SortUsersByNameDesc()); + }, + ); + } + if (columnIndex == 2) { + final Map checkboxStates = { + for (var item in _blocRole.jobTitle) + item: false, // Initialize with false + }; + final RenderBox overlay = Overlay.of(context) + .context + .findRenderObject() as RenderBox; + showPopUpFilterMenu( + position: RelativeRect.fromLTRB( + overlay.size.width / 4, + 240, + overlay.size.width / 4, + 0, + ), + list: _blocRole.jobTitle, + context: context, + checkboxStates: checkboxStates, + onOkPressed: () { + final selectedItems = checkboxStates.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(); + Navigator.of(context).pop(); + _blocRole.add(FilterUsersByJobEvent(selectedItems)); + }, + onSortAtoZ: () { + context + .read() + .add(const SortUsersByNameAsc()); + }, + onSortZtoA: () { + context + .read() + .add(const SortUsersByNameDesc()); + }, + ); + } + if (columnIndex == 3) { + final Map checkboxStates = { + for (var item in _blocRole.roleTypes) + item: _blocRole.selectedRoles.contains(item), + }; + final RenderBox overlay = Overlay.of(context) + .context + .findRenderObject() as RenderBox; + showPopUpFilterMenu( + position: RelativeRect.fromLTRB( + overlay.size.width / 4, + 240, + overlay.size.width / 4, + 0, + ), + list: _blocRole.roleTypes, + context: context, + checkboxStates: checkboxStates, + onOkPressed: () { + final selectedItems = checkboxStates.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(); + Navigator.of(context).pop(); + context + .read() + .add(FilterUsersByRoleEvent(selectedItems)); + }, + onSortAtoZ: () { + context + .read() + .add(const SortUsersByNameAsc()); + }, + onSortZtoA: () { + context + .read() + .add(const SortUsersByNameDesc()); + }, + ); + } + if (columnIndex == 4) { + showDateFilterMenu( + context: context, + isSelected: _blocRole.currentSortOrderDate, + aToZTap: () { + context + .read() + .add(const DateNewestToOldestEvent()); + }, + zToaTap: () { + context + .read() + .add(const DateOldestToNewestEvent()); + }, + ); + } + if (columnIndex == 6) { + final Map checkboxStates = { + for (var item in _blocRole.createdBy) + item: _blocRole.selectedCreatedBy.contains(item), + }; + final RenderBox overlay = Overlay.of(context) + .context + .findRenderObject() as RenderBox; + showPopUpFilterMenu( + position: RelativeRect.fromLTRB( + overlay.size.width / 1, + 240, + overlay.size.width / 4, + 0, + ), + list: _blocRole.createdBy, + context: context, + checkboxStates: checkboxStates, + onOkPressed: () { + final selectedItems = checkboxStates.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(); + Navigator.of(context).pop(); + _blocRole + .add(FilterUsersByCreatedEvent(selectedItems)); + }, + onSortAtoZ: () { + context + .read() + .add(const SortUsersByNameAsc()); + }, + onSortZtoA: () { + context + .read() + .add(const SortUsersByNameDesc()); + }, + ); + } + + if (columnIndex == 7) { + final Map checkboxStates = { + for (var item in _blocRole.status) + item: _blocRole.selectedCreatedBy.contains(item), + }; + final RenderBox overlay = Overlay.of(context) + .context + .findRenderObject() as RenderBox; + showPopUpFilterMenu( + position: RelativeRect.fromLTRB( + overlay.size.width / 0, + 240, + overlay.size.width / 4, + 0, + ), + list: _blocRole.status, + context: context, + checkboxStates: checkboxStates, + onOkPressed: () { + final selectedItems = checkboxStates.entries + .where((entry) => entry.value) + .map((entry) => entry.key) + .toList(); + Navigator.of(context).pop(); + _blocRole + .add(FilterUsersByCreatedEvent(selectedItems)); + }, + onSortAtoZ: () { + context + .read() + .add(const SortUsersByNameAsc()); + }, + onSortZtoA: () { + context + .read() + .add(const SortUsersByNameDesc()); + }, + ); + } + if (columnIndex == 8) { + showDeActivateFilterMenu( + context: context, + isSelected: _blocRole.currentSortOrderDate, + aToZTap: () { + context + .read() + .add(const DateNewestToOldestEvent()); + }, + zToaTap: () { + context + .read() + .add(const DateOldestToNewestEvent()); + }, + ); + } + }, + titles: const [ + "Full Name", + "Email Address", + "Job Title", + "Role", + "Creation Date", + "Creation Time", + "Created By", + "Status", + "De/Activate", + "Action" + ], + rows: state.users.map((user) { + return [ + Text('${user.firstName} ${user.lastName}'), + Text(user.email ?? ''), + Text(user.jobTitle ?? ''), + Text(user.roleType ?? ''), + Text(user.createdDate ?? ''), + Text(user.createdTime ?? ''), + Text(user.invitedBy), + status( + status: user.isEnabled == false + ? 'disabled' + : user.status, + ), + changeIconStatus( + status: user.isEnabled == false + ? 'disabled' + : user.status, + userId: user.uuid, + onTap: user.status != "invited" + ? () { + final newStatus = user.status == 'active' + ? 'disabled' + : user.status == 'disabled' + ? 'invited' + : 'active'; + context.read().add( + ChangeUserStatus( + userId: user.uuid, + newStatus: user.isEnabled == false + ? 'disabled' + : user.status)); + } + : null, + ), + Row( + children: [ + // actionButton( + // title: "Activity Log", + // onTap: () {}, + // ), + actionButton( + title: "Edit", + onTap: () { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return EditUserDialog(userId: user.uuid); + }, + ).then((v) { + if (v != null) { + if (v != null) { + _blocRole.add(const GetUsers()); + } + } + }); + }, + ), + actionButton( + title: "Delete", + onTap: () { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return DeleteUserDialog( + onTapDelete: () { + _blocRole.add(DeleteUserEvent( + user.uuid, context)); + }, + ); + }, + ).then((v) { + if (v != null) { + if (v != null) { + _blocRole.add(const GetUsers()); + } + } + }); + }, + ), + ], + ), + ]; + }).toList(), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + width: 500, + child: NumberPagination( + buttonRadius: 10, + selectedButtonColor: ColorsManager.secondaryColor, + buttonUnSelectedBorderColor: + ColorsManager.grayBorder, + lastPageIcon: + const Icon(Icons.keyboard_double_arrow_right), + firstPageIcon: + const Icon(Icons.keyboard_double_arrow_left), + totalPages: (_blocRole.users.length / + _blocRole.itemsPerPage) + .ceil(), + currentPage: _blocRole.currentPage, + onPageChanged: (int pageNumber) { + _blocRole.currentPage = pageNumber; + context + .read() + .add(ChangePage(pageNumber)); + }, + ), + ), + ], + ), + ), + ], + ), ), ); } else if (state is ErrorState) {