diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index de05fc92..24f62800 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -180,7 +180,7 @@ class AllRequestsProvider extends ChangeNotifier { return list; } - Future getAllRequests(BuildContext context, {int? typeTransaction, SearchAllRequestsModel? search}) async { + Future getAllRequests(BuildContext context, {int? typeTransaction, SearchAllRequestsModel? search, bool? isAscending}) async { if (isAllLoading == true) return -2; isAllLoading = true; if (_allRequestsAndCount == null) notifyListeners(); @@ -212,6 +212,7 @@ class AllRequestsProvider extends ChangeNotifier { if (search?.manufacture?.value?.isNotEmpty ?? false) "manufacturer": search!.manufacture!.value, if (search?.startDate != null) "from": search!.startDate!.toIso8601String(), if (search?.endDate != null) "to": search!.endDate!.toIso8601String(), + if (isAscending != null) "isAscending": isAscending, }; response = await ApiManager.instance.post(URLs.getAllRequestsAndCount, body: body); diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index 03ca5104..ce78b46f 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -270,7 +270,7 @@ class DashBoardProvider extends ChangeNotifier { } } - Future getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date, int? tabId}) async { + Future getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date, int? tabId, bool? isAscending}) async { if (showLoader) { isDetailLoading = showLoader; notifyListeners(); @@ -309,6 +309,7 @@ class DashBoardProvider extends ChangeNotifier { } if (isHighPriority) body["isHighPriority"] = true; if (isOverdue) body["isOverdue"] = true; + if (isAscending != null) body["isAscending"] = isAscending; response = await ApiManager.instance.post(url, body: body); stateCode = response.statusCode; diff --git a/lib/dashboard_latest/widgets/request_category_fragment.dart b/lib/dashboard_latest/widgets/request_category_fragment.dart index 322c4a41..a98dce35 100644 --- a/lib/dashboard_latest/widgets/request_category_fragment.dart +++ b/lib/dashboard_latest/widgets/request_category_fragment.dart @@ -16,9 +16,35 @@ import 'package:test_sa/new_views/common_widgets/tab_button.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -class RequestCategoryFragment extends StatelessWidget { +class RequestCategoryFragment extends StatefulWidget { const RequestCategoryFragment({Key? key}) : super(key: key); + @override + State createState() => _RequestCategoryFragmentState(); +} + +class _RequestCategoryFragmentState extends State { + bool isAscending = false; + + void _toggleSort(DashBoardProvider dashboardProvider, UsersTypes? userType) { + setState(() { + isAscending = !isAscending; + }); + + // Get current tab info + List tabs = CategoryTabs.getTabs(userType: userType ?? UsersTypes.normal_user, context: context); + + // Reload data with new sort order + dashboardProvider.resetRequestDataList(); + dashboardProvider.getRequestDetail( + usersType: userType ?? UsersTypes.normal_user, + showLoader: true, + status: tabs[dashboardProvider.currentListIndex].tag, + tabId: tabs[dashboardProvider.currentListIndex].id, + isAscending: isAscending, + ); + } + @override Widget build(BuildContext context) { return Consumer(builder: (context, dashboardProvider, child) { @@ -64,9 +90,9 @@ class RequestCategoryFragment extends StatelessWidget { Navigator.of(context).pushNamed('/cleaner_search'); }), Transform.flip( - flipY: false, + flipY: isAscending, child: 'dashboard/sort_descending'.toSvgAsset(width: 24, height: 24, color: AppColor.headingTextColor(context)).onPress(() { - Navigator.of(context).pushNamed('/cleaner_search'); + _toggleSort(dashboardProvider, user?.type); }), ) ], diff --git a/lib/models/search_all_requests_model.dart b/lib/models/search_all_requests_model.dart index 085bef0a..f6d7b585 100644 --- a/lib/models/search_all_requests_model.dart +++ b/lib/models/search_all_requests_model.dart @@ -13,6 +13,7 @@ class SearchAllRequestsModel { List? typeTransaction; // Now nullable DateTime? startDate, endDate; // Now nullable bool isArchived = false; + String? selectedSortOption; SearchAllRequestsModel({ this.requestNumber, @@ -26,6 +27,7 @@ class SearchAllRequestsModel { this.startDate, this.endDate, this.isArchived = false, + this.selectedSortOption, }); //older function diff --git a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart index f4e2f25e..a25c4c81 100644 --- a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart +++ b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart @@ -5,17 +5,34 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import '../../../../models/search_all_requests_model.dart'; import '../../../common_widgets/app_lazy_loading.dart'; import '../../../common_widgets/default_app_bar.dart'; import '../widgets/request_search_buttons.dart'; +enum SortOrder { + ascending, + descending; + + String get label { + switch (this) { + case SortOrder.ascending: + return "Ascending/Oldest"; + case SortOrder.descending: + return "Descending/Newest"; + } + } +} + class AllRequestsSearchPage extends StatefulWidget { static const String id = "all_requests_search_page"; final SearchAllRequestsModel? data; @@ -29,10 +46,25 @@ class AllRequestsSearchPage extends StatefulWidget { class _AllRequestsSearchPageState extends State { SearchAllRequestsModel? search; final GlobalKey _formKey = GlobalKey(); + SortOrder selectedSortOption = SortOrder.ascending; @override void initState() { search = widget.data; + + // Initialize from widget.data if available, otherwise default to Ascending + if (search?.selectedSortOption != null) { + // Match the saved sort option name to our enum + try { + selectedSortOption = SortOrder.values.firstWhere( + (e) => e.name == search!.selectedSortOption, + orElse: () => SortOrder.ascending, + ); + } catch (e) { + selectedSortOption = SortOrder.ascending; + } + } + if (search != null) { search!.requestNumber?.controller?.text = search?.requestNumber?.value ?? ""; search!.assetName?.controller?.text = search?.assetName?.value ?? ""; @@ -81,6 +113,9 @@ class _AllRequestsSearchPageState extends State { setState(() { // search!.resetSearchValues(); search?.resetSearchValuesAndController(except: null); + search!.startDate = null; + search!.endDate = null; + selectedSortOption = SortOrder.ascending; }); }), ], @@ -132,6 +167,79 @@ class _AllRequestsSearchPageState extends State { search!.searchBySelectedValue!.value = value; }, ), + 16.height, + "Sort".heading5(context), + 8.height, + Row( + children: [ + for (var element in SortOrder.values) + Padding( + padding: const EdgeInsets.only(right: 16), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: AppColor.primary10, + fillColor: WidgetStateColor.resolveWith((states) { + if (states.contains(WidgetState.selected)) { + return AppColor.primary10; + } + return Colors.grey; + }), + groupValue: selectedSortOption, + onChanged: (state) { + setState(() { + selectedSortOption = element; + }); + }, + ), + ), + 8.width, + Text( + element.label, + style: AppTextStyles.tinyFont.copyWith(color: AppColor.filterButtonTextColor(context)), + ), + ], + ), + ) + ], + ), + 16.height, + context.translation.pickDate.heading5(context), + 8.height, + Row( + children: [ + ADatePicker( + label: context.translation.from, + from: DateTime(2000), + date: search!.startDate, + onDatePicker: (date) { + setState(() { + search!.startDate = date; + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.to, + from: DateTime(2000), + date: search!.endDate, + onDatePicker: (date) { + if (search!.startDate != null && date.isBefore(search!.startDate!)) { + "End Date time must be greater then start date".showToast; + return; + } + setState(() { + search!.endDate = date; + }); + }, + ).expanded, + ], + ), ], ), ).expanded, @@ -145,10 +253,15 @@ class _AllRequestsSearchPageState extends State { void _search() async { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); + + // Save the enum name (ascending or descending) instead of label + search!.selectedSortOption = selectedSortOption.name; + final requestsProvider = Provider.of(context, listen: false); + if (search?.startDate != null) search?.endDate ??= DateTime.now(); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); requestsProvider.reset(); - await requestsProvider.getAllRequests(context, search: search); + await requestsProvider.getAllRequests(context, search: search, isAscending: selectedSortOption == SortOrder.ascending); Navigator.pop(context); Navigator.of(context).pop(search); } @@ -160,6 +273,9 @@ class _AllRequestsSearchPageState extends State { (search?.assetNo?.controller?.text.isNotEmpty ?? false) || (search?.manufacture?.controller?.text.isNotEmpty ?? false) || (search?.sn?.controller?.text.isNotEmpty ?? false) || - (search?.model?.controller?.text.isNotEmpty ?? false); + (search?.model?.controller?.text.isNotEmpty ?? false) || + (search?.startDate != null) || + (search?.endDate != null) || + selectedSortOption != SortOrder.ascending; } }