From 450cb91268b6cf1d31666e1b86829769d9c4e5e4 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 <50428976+WaseemAbbasi22@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:28:06 +0300 Subject: [PATCH] site deparment dropdown added for create traf request --- lib/controllers/api_routes/urls.dart | 1 + .../providers/api/all_requests_provider.dart | 13 ++- lib/main.dart | 2 + lib/models/new_models/traf_customer.dart | 62 +++++++++++ .../traf_module/create_traf_request_page.dart | 102 ++++++++++++++++-- .../traf_module/traf_request_model.dart | 3 +- .../lookups/customer_lookup_provider.dart | 70 ++++++++++++ 7 files changed, 241 insertions(+), 12 deletions(-) create mode 100644 lib/models/new_models/traf_customer.dart create mode 100644 lib/providers/lookups/customer_lookup_provider.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index cbfd5adc..c063e1bc 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -354,6 +354,7 @@ class URLs { static get getSiteContactInfo => "$_baseUrl/AssetGroupSiteContactInfo"; // add static get getDepartmentBasedOnSite => "$_baseUrl/TRAFDataSource/GetDepartmentBasedOnSite"; // add + static get getCustomersByUserId => "$_baseUrl/TRAFDataSource/GetCustomersByUserId"; // add // asset inventory Urls. static get getAssetInventoryById => '$_baseUrl/AssetInventory/GetAssetInventoryById'; diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index de05fc92..e3374962 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -157,15 +157,20 @@ class AllRequestsProvider extends ChangeNotifier { } // switching asset inventory to users permissions + // context.userProvider.modulesPermissionsList.forEach((module) { + // if (module.module!.value! == 8 || module.module!.value! == 9) { + // list.add(module.module!.value!); + // } + // }); context.userProvider.modulesPermissionsList.forEach((module) { - if (module.module!.value! == 8 || module.module!.value! == 9) { + if (module.module!.value! == 8) { list.add(module.module!.value!); } }); - // if (context.settingProvider.isUserFlowMedical && context.userProvider.isNurse) { - // list.add(9); // - // } + if (context.settingProvider.isUserFlowMedical && !context.userProvider.isAssessor) { + list.add(9); // + } list.add(12); if (context.userProvider.isCommissioningEngineer && context.settingProvider.isUserFlowMedical) { list = [13]; diff --git a/lib/main.dart b/lib/main.dart index fcb78f3e..878a0f53 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -134,6 +134,7 @@ import 'modules/tm_module/device_transfer/device_search_screen.dart'; import 'modules/tm_module/tasks/create_task_view.dart'; import 'modules/tm_module/gas_refill/gas_refill_request_form.dart'; import 'providers/lookups/classification_lookup_provider.dart'; +import 'providers/lookups/customer_lookup_provider.dart'; import 'providers/lookups/department_lookup_provider.dart'; import 'providers/lookups/request_type_lookup_provider.dart'; import 'providers/lookups/yes_no_lookup_provider.dart'; @@ -230,6 +231,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => RequestTypeLookupProvider(), lazy: true), ChangeNotifierProvider(create: (_) => YesNoLookupProvider(), lazy: true), ChangeNotifierProvider(create: (_) => DepartmentLookupProvider(), lazy: true), + ChangeNotifierProvider(create: (_) => CustomerLookupProvider(), lazy: true), ChangeNotifierProvider(create: (_) => EndUserStatusLookupProvider(), lazy: true), ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider(), lazy: true), ChangeNotifierProvider(create: (_) => AttachmentTypeLookupProvider(), lazy: true), diff --git a/lib/models/new_models/traf_customer.dart b/lib/models/new_models/traf_customer.dart new file mode 100644 index 00000000..4987afa1 --- /dev/null +++ b/lib/models/new_models/traf_customer.dart @@ -0,0 +1,62 @@ +import '../base.dart'; + +class TrafCustomer extends Base { + int? customerId; + int? langId; + String? nameValue; + String? customerName; + String? languageName; + int? id; + String? createdBy; + String? createdDate; + String? modifiedBy; + String? modifiedDate; + + TrafCustomer({ + this.customerId, + this.langId, + this.nameValue, + this.customerName, + this.languageName, + this.id, + this.createdBy, + this.createdDate, + this.modifiedBy, + this.modifiedDate, + }) : super(identifier: id?.toString() ?? '', name: nameValue ?? customerName); + + factory TrafCustomer.fromJson(Map json) { + return TrafCustomer( + customerId: json['customerId'], + langId: json['langId'], + nameValue: json['nameValue'], + customerName: json['customerName'], + languageName: json['languageName'], + id: json['id'], + createdBy: json['createdBy'], + createdDate: json['createdDate'], + modifiedBy: json['modifiedBy'], + modifiedDate: json['modifiedDate'], + ); + } + + Map toJson() { + return { + 'customerId': customerId, + 'langId': langId, + 'nameValue': nameValue, + 'customerName': customerName, + 'languageName': languageName, + 'id': id, + 'createdBy': createdBy, + 'createdDate': createdDate, + 'modifiedBy': modifiedBy, + 'modifiedDate': modifiedDate, + }; + } + + @override + String toString() { + return nameValue ?? customerName ?? ''; + } +} diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart index 1cc00f1c..4535cdc9 100644 --- a/lib/modules/traf_module/create_traf_request_page.dart +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -12,6 +12,7 @@ import 'package:test_sa/helper/utils.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/generic_attachment_model.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/traf_customer.dart'; import 'package:test_sa/models/new_models/traf_department.dart'; import 'package:test_sa/models/new_models/users_based_on_search_model.dart'; import 'package:test_sa/modules/cm_module/cm_request_utils.dart'; @@ -24,6 +25,7 @@ import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/multiple_item_drop_down_menu.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/lookups/customer_lookup_provider.dart'; import 'package:test_sa/providers/lookups/department_lookup_provider.dart'; import 'package:test_sa/providers/lookups/request_type_lookup_provider.dart'; import 'package:test_sa/providers/lookups/yes_no_lookup_provider.dart'; @@ -55,6 +57,9 @@ class _CreateTRAFRequestPageState extends State { Lookup? otherServicesEffects; Lookup? useInCombination; + TrafCustomer? selectedSite; + TrafDepartment? selectedDepartment; + TrafRequestDataModel? trafRequest; List abc = []; @@ -66,17 +71,42 @@ class _CreateTRAFRequestPageState extends State { FocusNode otherServicesEffectsNode = FocusNode(); FocusNode useInCombinationNode = FocusNode(); FocusNode departmentNode = FocusNode(); + FocusNode siteDepartmentNode = FocusNode(); @override void initState() { super.initState(); trafRequest = TrafRequestDataModel(id: 0, attachments: [], departments: [], qty: 1); - resetProviders(); + // Reset providers and load site data after the first frame to avoid provider lifecycle issues + WidgetsBinding.instance.addPostFrameCallback((_) { + // Only reset providers if they don't have data (first time load) + // This prevents unnecessary loading when navigating back and forth + final requestTypeProvider = Provider.of(context, listen: false); + final yesNoProvider = Provider.of(context, listen: false); + final customerProvider = Provider.of(context, listen: false); + + // Only load if not already loaded + if (requestTypeProvider.items.isEmpty) { + requestTypeProvider.getData(); + } + + if (yesNoProvider.items.isEmpty) { + yesNoProvider.getData(); + } + + // Load customer/site data using the string user ID (GUID) only if not loaded + if (customerProvider.items.isEmpty) { + final userId = context.userProvider.user?.userID; + if (userId != null && userId.isNotEmpty) { + customerProvider.getDataByUserId(userId); + } + } + }); } void resetProviders() { Provider.of(context, listen: false).reset(); - // Provider.of(context, listen: false).reset(); + Provider.of(context, listen: false).reset(); } @override @@ -184,6 +214,52 @@ class _CreateTRAFRequestPageState extends State { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, fontWeight: FontWeight.w600), ), 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: "Site", + requestById: int.tryParse(context.userProvider.user?.userID ?? ''), + initialValue: selectedSite, + onSelect: (value) { + selectedSite = value; + trafRequest?.siteId = value?.customerId; + // Reset department when site changes + selectedDepartment = null; + trafRequest?.departmentId = null; + + // Reset and fetch department data based on selected site + Provider.of(context, listen: false).reset(); + if (selectedSite != null && selectedSite!.customerId != null) { + // Fetch departments for the selected site + Provider.of(context, listen: false).getData(id: selectedSite!.customerId); + siteDepartmentNode.requestFocus(); + } + setState(() {}); + }, + ), + 12.height, + Focus( + focusNode: siteDepartmentNode, + child: SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: "Department", + requestById: null, + // Don't pass requestById to prevent auto-fetch + initialValue: selectedDepartment, + enabled: selectedSite != null, + onSelect: (value) { + selectedDepartment = value; + trafRequest?.departmentId = value?.id?.toString(); + setState(() {}); + }, + ), + ), + 12.height, AppTextFormField( initialValue: "", labelText: "How would the requested technology solve the current situation and/or serve the purpose?", @@ -461,7 +537,6 @@ class _CreateTRAFRequestPageState extends State { ), ], ).toShadowContainer(context, padding: 12, borderRadius: 20), - 16.height, Row( children: [ @@ -507,10 +582,25 @@ class _CreateTRAFRequestPageState extends State { "Pick asset".showToast; return; } + + // Validate site and department selection + if (selectedSite == null) { + "Please select a site".showToast; + return; + } + + if (selectedDepartment == null) { + "Please select a department".showToast; + return; + } + if (!_formKey.currentState!.validate()) return; trafRequest?.employeeId = context.userProvider.user?.userID; - trafRequest?.siteId = context.userProvider.user?.clientId; + // Set site and department IDs from selected dropdowns + trafRequest?.siteId = selectedSite?.customerId; + trafRequest?.departmentId = selectedDepartment?.id; + trafRequest?.trafContacts = []; trafRequest?.trafContacts = userBasedOnSearch.map((item) => TrafContacts(id: 0, trafId: 0, name: item.userName, userId: item.userId)).toList(); @@ -540,9 +630,7 @@ class _CreateTRAFRequestPageState extends State { // Process attachments similar to CreateCMRequest trafRequest?.attachments = []; for (var item in attachments) { - String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') - ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") - : item.name ?? ''; + String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? ''; trafRequest?.attachments!.add( Attachments(id: 0, trafId: 0, attachmentName: fileName), ); diff --git a/lib/modules/traf_module/traf_request_model.dart b/lib/modules/traf_module/traf_request_model.dart index 09079f3f..a9d7c40e 100644 --- a/lib/modules/traf_module/traf_request_model.dart +++ b/lib/modules/traf_module/traf_request_model.dart @@ -51,7 +51,7 @@ class TrafRequestDataModel { String? employeeEmail; int? positionId; String? positionName; - String? departmentId; + dynamic departmentId; String? departmentName; List? departments; List? trafDepartments; @@ -498,6 +498,7 @@ class TrafRequestDataModel { } data['siteId'] = siteId; + data['departmentId'] = departmentId; data['siteName'] = siteName; data['requesterExtensionNumber'] = requesterExtensionNumber; data['requesterExtensionName'] = requesterExtensionName; diff --git a/lib/providers/lookups/customer_lookup_provider.dart b/lib/providers/lookups/customer_lookup_provider.dart new file mode 100644 index 00000000..c87b54c5 --- /dev/null +++ b/lib/providers/lookups/customer_lookup_provider.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/new_models/traf_customer.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; + +class CustomerLookupProvider extends LoadingListNotifier { + @override + Future getData({int? id}) async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + // Get customers by user ID (GUID string) + // If id is null, try to get it from the current user + String? userId = id?.toString(); + + Response response = await ApiManager.instance.get( + URLs.getCustomersByUserId + "?userId=$userId", + useCache: true, + enableToastMessage: false, + ); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => TrafCustomer.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } + + // Add method to get data by string user ID (GUID) + Future getDataByUserId(String? userId) async { + if (loading == true) return -2; + if (userId == null || userId.isEmpty) return -1; + + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get( + URLs.getCustomersByUserId + "?userId=$userId", + useCache: true, + enableToastMessage: false, + ); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => TrafCustomer.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +}