From 56328b81b463fb3e7d4bbb886b8e3c3631470f78 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 9 Oct 2025 17:47:24 +0300 Subject: [PATCH 1/9] traf module added, create, view details, update. cont --- lib/controllers/api_routes/urls.dart | 11 +- .../providers/api/oracle_code_provider.dart | 119 ++++ lib/main.dart | 33 +- .../asset_auto_complete_field.dart | 131 +++++ .../traf_module/create_traf_request_page.dart | 381 ++++++++++++ .../traf_module/traf_request_detail_page.dart | 161 +++++ .../traf_module/traf_request_item_view.dart | 0 .../traf_module/traf_request_model.dart | 551 ++++++++++++++++++ .../traf_module/traf_request_provider.dart | 32 + .../traf_module/update_traf_request_page.dart | 224 +++++++ .../common_widgets/app_text_form_field.dart | 17 +- .../multiple_item_drop_down_menu.dart | 251 ++++++++ .../single_item_drop_down_menu.dart | 86 +-- .../create_request-type_bottomsheet.dart | 3 + .../requests/gas_refill_item_view.dart | 4 +- .../classification_lookup_provider.dart | 33 ++ .../recommendation_lookup_provider.dart | 33 ++ .../lookups/request_type_lookup_provider.dart | 33 ++ .../lookups/yes_no_lookup_provider.dart | 33 ++ .../muliple_selection_bottom_sheet.dart | 172 ++++++ .../multiple_selection_fullscreen_dialog.dart | 196 +++++++ .../selection_fullscreen_dialog.dart | 4 +- 22 files changed, 2440 insertions(+), 68 deletions(-) create mode 100644 lib/controllers/providers/api/oracle_code_provider.dart create mode 100644 lib/modules/traf_module/asset_auto_complete_field.dart create mode 100644 lib/modules/traf_module/create_traf_request_page.dart create mode 100644 lib/modules/traf_module/traf_request_detail_page.dart create mode 100644 lib/modules/traf_module/traf_request_item_view.dart create mode 100644 lib/modules/traf_module/traf_request_model.dart create mode 100644 lib/modules/traf_module/traf_request_provider.dart create mode 100644 lib/modules/traf_module/update_traf_request_page.dart create mode 100644 lib/new_views/common_widgets/multiple_item_drop_down_menu.dart create mode 100644 lib/providers/lookups/classification_lookup_provider.dart create mode 100644 lib/providers/lookups/recommendation_lookup_provider.dart create mode 100644 lib/providers/lookups/request_type_lookup_provider.dart create mode 100644 lib/providers/lookups/yes_no_lookup_provider.dart create mode 100644 lib/views/widgets/bottom_sheets/muliple_selection_bottom_sheet.dart create mode 100644 lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 2cac62b1..9d4ef5db 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -4,8 +4,8 @@ class URLs { static const String appReleaseBuildNumber = "26"; // static const host1 = "https://atomsm.hmg.com"; // production url - // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + static const host1 = "https://atomsmdev.hmg.com"; // local DEV url + // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url // static String _baseUrl = "$_host/mobile"; // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis @@ -225,6 +225,10 @@ class URLs { static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; + static get getTrafRequestTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=416"; + static get getYesNoRequestTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; + static get getClassificationTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=450"; + static get getRecommendationTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=451"; static get getWoFrames => "$_baseUrl/Lookups/GetLookup?lookupEnum=1254"; @@ -247,6 +251,9 @@ class URLs { static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName="; + //Traf + static get getTRAFById => "$_baseUrl/TRAF/GetTRAFById"; // get + //gas refill static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get // todo check edits with backend diff --git a/lib/controllers/providers/api/oracle_code_provider.dart b/lib/controllers/providers/api/oracle_code_provider.dart new file mode 100644 index 00000000..df0acb98 --- /dev/null +++ b/lib/controllers/providers/api/oracle_code_provider.dart @@ -0,0 +1,119 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/service_request/spare_parts.dart'; + +class OracleCodeProvider extends ChangeNotifier { + // number of items call in each request + final pageItemNumber = 20; + + //reset provider data + void reset() { + _parts = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int? _stateCode; + + int? get stateCode => _stateCode; + + // true if there is next pagein product list and false if not + bool _nextPage = true; + + bool get nextPage => _nextPage; + + // contain user data + // when user not login or register _user = null + List? _parts; + + List? get parts => _parts; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading = false; + + bool get isLoading => _loading; + + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + // Future getParts({String? title}) async { + // if (_loading == true) return -2; + // _loading = true; + // notifyListeners(); + // late Response response; + // try { + // response = await ApiManager.instance.post(URLs.getPartNumber, body: {if (title != null && title.isNotEmpty) "partName": title}); + // _stateCode = response.statusCode; + // if (response.statusCode >= 200 && response.statusCode < 300) { + // // client's request was successfully received + // List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + // List page = categoriesListJson.map((part) => SparePart.fromJson(part)).toList(); + // _parts ??= []; + // _parts!.addAll(page.map((e) => SparePartsWorkOrders(sparePart: e)).toList()); + // _nextPage = page.length >= pageItemNumber; + // } + // _loading = false; + // notifyListeners(); + // return response.statusCode; + // } catch (error) { + // _loading = false; + // _stateCode = -1; + // notifyListeners(); + // return -1; + // } + // } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future> getAssetByOracleCode(String oracleCode) async { + late Response response; + try { + response = await ApiManager.instance.post(URLs.getPartNumber, body: {"oracleCode": oracleCode}); + List page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + page = categoriesListJson.map((part) => SparePart.fromJson(part, false)).toList(); + } + return page; + } catch (error) { + return []; + } + } +// // Implement this only for spare part request for now show and search on display name .... +// +// Future> getPartsListByDisplayName({num? assetId, String? displayName}) async { +// late Response response; +// try { +// response = await ApiManager.instance.post(URLs.getPartNumber, body: {"displayName": displayName, }); +// List page = []; +// if (response.statusCode >= 200 && response.statusCode < 300) { +// // client's request was successfully received +// List categoriesListJson = json.decode(response.body)["data"]; +// page = categoriesListJson.map((part) => SparePart.fromJson(part,true)).toList(); +// } +// return page; +// } catch (error) { +// return []; +// } +// } +} diff --git a/lib/main.dart b/lib/main.dart index e60fb1e8..30daa9c1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:test_sa/controllers/providers/api/devices_provider.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart'; import 'package:test_sa/controllers/providers/api/hospitals_provider.dart'; import 'package:test_sa/controllers/providers/api/notifications_provider.dart'; +import 'package:test_sa/controllers/providers/api/oracle_code_provider.dart'; import 'package:test_sa/controllers/providers/api/parts_provider.dart'; import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; @@ -28,6 +29,9 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/report/servic import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart'; import 'package:test_sa/modules/cm_module/views/nurse/create_new_request_view.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/create_task_view.dart'; +import 'package:test_sa/modules/traf_module/create_traf_request_page.dart'; +import 'package:test_sa/modules/traf_module/traf_request_provider.dart'; +import 'package:test_sa/modules/traf_module/update_traf_request_page.dart'; import 'package:test_sa/new_views/app_style/app_themes.dart'; import 'package:test_sa/new_views/pages/help_center_page.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; @@ -47,6 +51,7 @@ import 'package:test_sa/providers/gas_request_providers/gas_status_provider.dart import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/providers/lookups/recommendation_lookup_provider.dart'; import 'package:test_sa/providers/ppm_asset_availability_provider.dart'; import 'package:test_sa/providers/ppm_checklist_status_provider.dart'; import 'package:test_sa/providers/ppm_device_status_provider.dart'; @@ -93,6 +98,9 @@ import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; import 'dashboard_latest/dashboard_provider.dart'; import 'new_views/pages/gas_refill_request_form.dart'; +import 'providers/lookups/classification_lookup_provider.dart'; +import 'providers/lookups/request_type_lookup_provider.dart'; +import 'providers/lookups/yes_no_lookup_provider.dart'; import 'providers/service_request_providers/loan_availability_provider.dart'; import 'providers/service_request_providers/reject_reason_provider.dart'; @@ -121,7 +129,8 @@ void main() async { } else { await Firebase.initializeApp(); } - SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(statusBarColor: Colors.transparent, + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.white, systemNavigationBarIconBrightness: Brightness.dark, )); @@ -179,21 +188,18 @@ class MyApp extends StatelessWidget { //new providers according to new Api's.. ChangeNotifierProvider(create: (_) => DashBoardProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestDetailProvider()), - // ChangeNotifierProvider(create: (_) => PreventiveMaintenanceVisitsProvider()), + ChangeNotifierProvider(create: (_) => ClassificationLookupProvider()), + ChangeNotifierProvider(create: (_) => RecommendationLookupProvider()), ChangeNotifierProvider(create: (_) => PpmProvider()), ChangeNotifierProvider(create: (_) => PartsProvider()), - ///todo deleted - //ChangeNotifierProvider(create: (_) => ServiceReportReasonsProvider()), - //ChangeNotifierProvider(create: (_) => ServiceReportStatusProvider()), - ///todo deleted - //ChangeNotifierProvider(create: (_) => ServiceReportEquipmentStatusProvider()), - //ChangeNotifierProvider(create: (_) => ServiceReportTypesProvider()), + ChangeNotifierProvider(create: (_) => RequestTypeLookupProvider()), + ChangeNotifierProvider(create: (_) => YesNoLookupProvider()), ChangeNotifierProvider(create: (_) => ServiceStatusProvider()), ChangeNotifierProvider(create: (_) => ServiceReportLastCallsProvider()), - ///todo deleted - //ChangeNotifierProvider(create: (_) => GasCylinderSizesProvider()), + ChangeNotifierProvider(create: (_) => OracleCodeProvider()), + ///todo deleted //ChangeNotifierProvider(create: (_) => GasCylinderTypesProvider()), ChangeNotifierProvider(create: (_) => GasStatusProvider()), @@ -202,8 +208,8 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => DeviceTransferProvider()), ChangeNotifierProvider(create: (_) => AssetTransferStatusProvider()), - ///todo deleted - //ChangeNotifierProvider(create: (_) => AssignedToProvider()), + ChangeNotifierProvider(create: (_) => TrafRequestProvider()), + ///todo deleted //ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()), //ChangeNotifierProvider(create: (_) => PentryVisitStatusProvider()), @@ -312,7 +318,8 @@ class MyApp extends StatelessWidget { GasRefillRequestForm.routeName: (_) => const GasRefillRequestForm(), // ServiceRequestsPage.id: (_) => const ServiceRequestsPage(), CreateTaskView.id: (_) => const CreateTaskView(), - //ReportIssuesPage.id: (_) => ReportIssuesPage(), + CreateTRAFRequestPage.id: (_) => CreateTRAFRequestPage(), + UpdateTrafRequestPage.id: (_) => UpdateTrafRequestPage(), RequestGasRefill.id: (_) => const RequestGasRefill(), UpdateGasRefillRequest.id: (_) => const UpdateGasRefillRequest(), // CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), diff --git a/lib/modules/traf_module/asset_auto_complete_field.dart b/lib/modules/traf_module/asset_auto_complete_field.dart new file mode 100644 index 00000000..df4a042e --- /dev/null +++ b/lib/modules/traf_module/asset_auto_complete_field.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/oracle_code_provider.dart'; +import 'package:test_sa/controllers/providers/api/parts_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../../../extensions/text_extensions.dart'; +import '../../../models/service_request/spare_parts.dart'; +import '../../../new_views/app_style/app_text_style.dart'; + +class AssetAutoCompleteField extends StatefulWidget { + final String initialValue; + final num? assetId; + final bool clearAfterPick, byName; + final Function(SparePartsWorkOrders) onPick; + + const AssetAutoCompleteField({Key? key, required this.byName, required this.initialValue, this.assetId, required this.onPick, this.clearAfterPick = true}) : super(key: key); + + @override + _AssetAutoCompleteFieldState createState() => _AssetAutoCompleteFieldState(); +} + +class _AssetAutoCompleteFieldState extends State { + late OracleCodeProvider _oracleCodeProvider; + + late TextEditingController _controller; + + bool loading = false; + + @override + void initState() { + _controller = TextEditingController(text: widget.initialValue); + super.initState(); + _oracleCodeProvider = Provider.of(context, listen: false); + } + + @override + void didUpdateWidget(covariant AssetAutoCompleteField oldWidget) { + if (widget.initialValue != oldWidget.initialValue) { + _controller = TextEditingController(text: widget.initialValue); + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10)); + return Container( + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Autocomplete( + optionsBuilder: (TextEditingValue textEditingValue) async { + if (textEditingValue.text.isEmpty) { + if (loading) { + setState(() { + loading = false; + }); + } + return const Iterable.empty(); + } + if (!loading) { + setState(() { + loading = true; + }); + } + List workOrders = (await _oracleCodeProvider.getAssetByOracleCode(textEditingValue.text)).map((e) => SparePartsWorkOrders(sparePart: e)).toList(); + setState(() { + loading = false; + }); + return workOrders; + }, + displayStringForOption: (SparePartsWorkOrders option) => widget.byName ? option.sparePart?.partName ?? "" : option.sparePart?.partNo ?? "", + fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { + return TextField( + controller: _controller, + focusNode: fieldFocusNode, + style: AppTextStyles.bodyText.copyWith(color: AppColor.black10), + textAlign: TextAlign.start, + decoration: InputDecoration( + border: border, + disabledBorder: border, + focusedBorder: border, + enabledBorder: border, + errorBorder: border, + contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth), + constraints: const BoxConstraints(), + suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8), + filled: true, + fillColor: AppColor.fieldBgColor(context), + errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), + floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20), + labelText: context.translation.oracleCode, + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)), + suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null, + ), + textInputAction: TextInputAction.search, + onChanged: (text) { + fieldTextEditingController.text = text; + }, + onSubmitted: (String value) { + onFieldSubmitted(); + }, + ); + }, + onSelected: (SparePartsWorkOrders selection) { + if (widget.clearAfterPick) { + _controller.clear(); + } else { + _controller.text = widget.byName ? (selection.sparePart?.partName ?? "") : (selection.sparePart?.partNo ?? ""); + } + widget.onPick(selection); + }, + ), + ); + } +} diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart new file mode 100644 index 00000000..f1b62e0e --- /dev/null +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -0,0 +1,381 @@ +import 'package:flutter/material.dart'; +import 'package:provider/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/models/device/asset.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/modules/traf_module/asset_auto_complete_field.dart'; +import 'package:test_sa/modules/traf_module/traf_request_detail_page.dart'; +import 'package:test_sa/modules/traf_module/update_traf_request_page.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/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/loading_list_notifier.dart'; +import 'package:test_sa/providers/lookups/request_type_lookup_provider.dart'; +import 'package:test_sa/providers/lookups/yes_no_lookup_provider.dart'; +import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; + +import 'traf_request_model.dart'; + +class CreateTRAFRequestPage extends StatefulWidget { + static const String id = "/create-TRAF"; + + CreateTRAFRequestPage({Key? key}) : super(key: key); + + @override + _CreateTRAFRequestPageState createState() { + return _CreateTRAFRequestPageState(); + } +} + +class _CreateTRAFRequestPageState extends State { + final GlobalKey _formKey = GlobalKey(); + + bool _acknowledgement = false; + + Asset? asset; + + Lookup? requestType; + Lookup? isUsedSolelyOrShared; + Lookup? otherServicesEffects; + Lookup? useInCombination; + + TrafRequestDataModel? trafRequest; + + List abc = []; + + @override + void initState() { + super.initState(); + trafRequest = TrafRequestDataModel(); + resetProviders(); + } + + void resetProviders() { + Provider.of(context, listen: false).reset(); + // Provider.of(context, listen: false).reset(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const DefaultAppBar(title: "TRAF Request"), + body: Form( + key: _formKey, + child: Column( + children: [ + ListView(padding: const EdgeInsets.all(16), children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // SingleItemDropDownMenu( + // context: context, + // height: 56.toScreenHeight, + // title: context.translation.taskType, + // showShadow: false, + // backgroundColor: AppColor.fieldBgColor(context), + // showAsBottomSheet: true, + // initialValue: selectedType, + // onSelect: (type) {}, + // ), + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: context.translation.requestType, + initialValue: requestType, + onSelect: (value) { + requestType = value; + trafRequest?.requestTypeId = value?.value; + setState(() {}); + }, + ), + if (requestType?.value == 1) ...[ + 12.height, + AssetAutoCompleteField( + // assetId: widget.assetId, + clearAfterPick: false, + byName: false, + initialValue: "", + onPick: (part) { + // model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); + // setState(() {}); + }, + ), + ], + if (requestType?.value == 2) ...[ + 12.height, + AssetPicker( + device: asset, + editable: false, + showLoading: false, + borderColor: AppColor.black20, + backgroundColor: AppColor.white936, + onPick: (asset) async { + this.asset = asset; + setState(() {}); + // pendingAssetServiceRequest = null; + // _serviceRequest.device = asset; + // await checkAssetForPendingServiceRequest(asset.id!.toInt()); + // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + // showPendingRequestBottomSheet(); + // } + }, + ), + ], + 12.height, + Text( + "Request Details", + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, fontWeight: FontWeight.w600), + ), + 12.height, + AppTextFormField( + initialValue: "", + labelText: "How would the requested technology solve the current situation and/or serve the purpose?", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + makeMultiLinesNull: true, + onChange: (value) { + trafRequest?.purposeAnswer = value; + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + labelText: "What is the current practice?", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + makeMultiLinesNull: true, + onChange: (value) { + trafRequest?.currentPractise = value; + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + makeMultiLinesNull: true, + labelText: "Census Q1", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.number, + onChange: (value) { + trafRequest?.censusQ1 = int.tryParse(value); + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + makeMultiLinesNull: true, + labelText: "Census Q2", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.number, + onChange: (value) { + trafRequest?.censusQ2 = int.tryParse(value); + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + makeMultiLinesNull: true, + labelText: "Census Q3", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.number, + onChange: (value) { + trafRequest?.censusQ3 = int.tryParse(value); + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + makeMultiLinesNull: true, + labelText: "Census Q4", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.number, + onChange: (value) { + trafRequest?.censusQ4 = int.tryParse(value); + }, + ), + + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + height: 80, + title: "List down names & contact information of users going to use the technology & specify if they are part-time or full time?", + initialValue: isUsedSolelyOrShared, + onSelect: (value) { + // isUsedSolelyOrShared = value; + setState(() {}); + }, + ), + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + height: 80, + title: "Is the requesting department going to use the technology solely or shared with other departments?", + initialValue: isUsedSolelyOrShared, + onSelect: (value) { + isUsedSolelyOrShared = value; + trafRequest?.usingSolelyOrSharedId = value?.value; + setState(() {}); + }, + ), + if (isUsedSolelyOrShared?.value == 1) ...[ + 12.height, + MultipleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + showCancel: true, + title: "Please specify departments and relations", + initialValue: abc, + onSelect: (value) { + abc = value ?? []; + // setState(() { + // + // }); + }, + ), + ], + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + height: 80, + title: "Would other services be effected by acquiring the new equipment?", + initialValue: otherServicesEffects, + onSelect: (value) { + otherServicesEffects = value; + trafRequest?.isEffectedId = value?.value; + setState(() {}); + }, + ), + if (otherServicesEffects?.value == 1) ...[ + 12.height, + AppTextFormField( + initialValue: "", + // makeMultiLinesNull: true, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + labelText: "List down these services and stat how would it be effected", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + onChange: (value) { + trafRequest?.effectedServices = value; + }, + ), + ], + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + height: 80, + title: "Is the equipment going to be used with combination of other equipment to accomplish a specific procedure?", + initialValue: useInCombination, + onSelect: (value) { + useInCombination = value; + trafRequest?.isCombinationId = value?.value; + setState(() {}); + }, + ), + if (useInCombination?.value == 1) ...[ + 12.height, + AppTextFormField( + initialValue: "", + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + labelText: "kindly describe in detail", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + onChange: (value) { + trafRequest?.usedWithCombination = value; + }, + ), + ] + // 23.height, + // AttachmentPicker( + // label: context.translation.attachImage, + // attachment: attachments, + // buttonColor: AppColor.black10, + // onlyImages: false, + // buttonIcon: 'image-plus'.toSvgAsset(color: context.isDark ? AppColor.primary10 : AppColor.neutral120), + // //verify this if not required delete this .. + // onChange: (attachments) { + // attachments = attachments; + // setState(() {}); + // }, + // ), + ], + ).toShadowContainer(context, padding: 12, borderRadius: 20), + 16.height, + Row( + children: [ + Checkbox( + value: _acknowledgement, + visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0), + activeColor: AppColor.blueStatus(context), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onChanged: (value) { + setState(() { + _acknowledgement = value!; + }); + }), + 12.width, + "I acknowledge the information filled above is correct".addTranslation.bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120).expanded, + ], + ), + ]).expanded, + FooterActionButton.footerContainer( + context: context, + child: AppFilledButton( + buttonColor: AppColor.primary10, + label: context.translation.submitRequest, + onPressed: _acknowledgement ? _submit : null, + // buttonColor: AppColor.primary10, + ), + ), + ], + ), + ), + ); + } + + void _submit() { + Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: 27))); + } +} diff --git a/lib/modules/traf_module/traf_request_detail_page.dart b/lib/modules/traf_module/traf_request_detail_page.dart new file mode 100644 index 00000000..4b763736 --- /dev/null +++ b/lib/modules/traf_module/traf_request_detail_page.dart @@ -0,0 +1,161 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/enums/user_types.dart'; +import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/modules/traf_module/traf_request_provider.dart'; +import 'package:test_sa/modules/traf_module/update_traf_request_page.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/default_app_bar.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; + +import 'traf_request_model.dart'; + +class TrafRequestDetailPage extends StatefulWidget { + static const String id = "/details-TRAF"; + + final int trafId; + + TrafRequestDetailPage({Key? key, required this.trafId}) : super(key: key); + + @override + _TrafRequestDetailPageState createState() { + return _TrafRequestDetailPageState(); + } +} + +class _TrafRequestDetailPageState extends State { + @override + void initState() { + super.initState(); + Provider.of(context, listen: false).getTRAFById(widget.trafId); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool isEngineer = (Provider.of(context, listen: false).user?.type) == UsersTypes.engineer; + return Scaffold( + appBar: const DefaultAppBar(title: "TRAF Request"), + body: Selector( + selector: (_, myModel) => myModel.isLoading, // Selects only the userName + builder: (_, isLoading, __) { + if (isLoading) return const ALoading(); + TrafRequestProvider trafProvider = Provider.of(context, listen: false); + + return Column( + children: [ + ListView( + padding: const EdgeInsets.all(16), + children: [ + requesterInformation(trafProvider.trafRequestDataModel!), + 12.height, + requestInformation(trafProvider.trafRequestDataModel!), + if (trafProvider.trafRequestDataModel!.requestTypeId == 733) ...[ + 12.height, + assetInformation(trafProvider.trafRequestDataModel!), + ] + ], + ).expanded, + // if (isEngineer) + FooterActionButton.footerContainer( + context: context, + child: AppFilledButton( + buttonColor: AppColor.primary10, + label: "Update", + onPressed: () { + Navigator.pushNamed(context, UpdateTrafRequestPage.id); + }), + ), + ], + ); + }, + )); + } + + Widget requesterInformation(TrafRequestDataModel data) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Requester Information", + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + '${context.translation.employeeId}: ${data.employeeId ?? '-'}'.bodyText(context), + '${context.translation.name}: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer + '${context.translation.email}: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer + 'Position: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer + '${context.translation.site}: ${data.siteName ?? '-'}'.bodyText(context), + '${context.translation.department}: ${data.departments ?? '-'}'.bodyText(context), + 'Requester Extension: ${data.requesterExtensionName ?? '-'}'.bodyText(context), + '${context.translation.extensionNo}: ${data.requesterExtensionNumber ?? '-'}'.bodyText(context), + ], + ).toShadowContainer(context, borderRadius: 20, padding: 12); + } + + Widget requestInformation(TrafRequestDataModel data) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "TRAF Request Information", + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + 'TRAF No: ${data.reqCode ?? '-'}'.bodyText(context), + 'Request type: ${data.requestTypeName ?? '-'}'.bodyText(context), + 4.height, + 'What is the current practice?:\n${data.currentPractise ?? '-'}'.bodyText(context), + 4.height, + 'Census Q1: ${data.censusQ1 ?? '-'}'.bodyText(context), + 'Census Q2: ${data.censusQ2 ?? '-'}'.bodyText(context), + 'Census Q3: ${data.censusQ3 ?? '-'}'.bodyText(context), + 'Census Q4: ${data.censusQ4 ?? '-'}'.bodyText(context), + 4.height, + 'List down names & contact information of users going to use the technology & specify if they are part-time or full time?:\n${data.trafContacts ?? '-'}'.bodyText(context), + 4.height, + 'Is the requesting department going to use the technology solely or shared with other departments?:\n${data.usingSolelyOrSharedId ?? '-'}'.bodyText(context), + 4.height, + 'Would other services be effected by acquiring the new equipment?:\n${data.effectedServices ?? '-'}'.bodyText(context), + 4.height, + 'Is the equipment going to be used with combination of other equipment to accomplish a specific procedure?:\n${data.usedWithCombination ?? '-'}'.bodyText(context), + ], + ).toShadowContainer(context, borderRadius: 20, padding: 12); + } + + Widget assetInformation(TrafRequestDataModel data) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Asset Information", + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + 'Last price & PO: ${data.poNumber ?? '-'}'.bodyText(context), + 'The quantity of the same asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Existing asset under SLA: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Age of the asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Total Maintenance Cost (TMC): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Net Book Value (NBV): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Mean Time Between Failure (MTBF): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Down Time (DT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Up Time (UT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Purchased Price: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + ], + ).toShadowContainer(context, borderRadius: 20, padding: 12); + } +} diff --git a/lib/modules/traf_module/traf_request_item_view.dart b/lib/modules/traf_module/traf_request_item_view.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/modules/traf_module/traf_request_model.dart b/lib/modules/traf_module/traf_request_model.dart new file mode 100644 index 00000000..5705b6d0 --- /dev/null +++ b/lib/modules/traf_module/traf_request_model.dart @@ -0,0 +1,551 @@ +class TrafRequestModel { + List? trafRequestDataModel; + int? totalRows; + int? count; + String? message; + String? title; + String? innerMessage; + int? responseCode; + bool? isSuccess; + + TrafRequestModel({this.trafRequestDataModel, this.totalRows, this.count, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess}); + + TrafRequestModel.fromJson(Map json) { + if (json['TrafRequestDataModel'] != null) { + trafRequestDataModel = []; + json['TrafRequestDataModel'].forEach((v) { + trafRequestDataModel!.add(new TrafRequestDataModel.fromJson(v)); + }); + } + totalRows = json['totalRows']; + count = json['count']; + message = json['message']; + title = json['title']; + innerMessage = json['innerMessage']; + responseCode = json['responseCode']; + isSuccess = json['isSuccess']; + } + + Map toJson() { + final Map data = new Map(); + if (this.trafRequestDataModel != null) { + data['TrafRequestDataModel'] = this.trafRequestDataModel!.map((v) => v.toJson()).toList(); + } + data['totalRows'] = this.totalRows; + data['count'] = this.count; + data['message'] = this.message; + data['title'] = this.title; + data['innerMessage'] = this.innerMessage; + data['responseCode'] = this.responseCode; + data['isSuccess'] = this.isSuccess; + return data; + } +} + +class TrafRequestDataModel { + int? reqNo; + String? reqCode; + String? employeeId; + String? employeeName; + String? employeeEmail; + int? positionId; + String? positionName; + List? departments; + int? siteId; + String? siteName; + String? requesterExtensionNumber; + String? requesterExtensionName; + int? requesterExtensionPositionId; + String? requesterExtensionPositionName; + int? requestTypeId; + String? requestTypeName; + int? assetNDId; + int? modelId; + String? modelName; + int? manufacturerId; + String? manufacturerName; + int? assetId; + String? assetSerialNo; + String? assetNumber; + String? assetName; + int? assetAssetNDId; + int? qty; + String? purposeAnswer; + String? currentPractise; + int? censusQ1; + int? censusQ2; + int? censusQ3; + int? censusQ4; + List? trafContacts; + int? usingSolelyOrSharedId; + String? usingSolelyOrSharedName; + int? isEffectedId; + String? isEffectedName; + String? effectedServices; + int? isCombinationId; + String? isCombinationName; + String? usedWithCombination; + String? comment; + List? attachments; + int? isBudgetId; + String? isBudgetName; + String? firstLineManagerId; + String? firstLineManagerName; + int? firstLineManagerApprovalId; + String? firstLineManagerApprovalName; + int? tlapiId; + String? tlapiName; + String? assessorEmployeeId; + String? assessorEmployeeName; + String? secondLineManagerId; + String? secondLineManagerName; + int? secondLineManagerApprovalId; + String? secondLineManagerApprovalName; + String? hospitalManagementId; + String? hospitalManagementName; + int? hospitalManagementApprovalId; + String? hospitalManagementApprovalName; + List? oracleCodes; + String? assessorTeamLeaderId; + String? assessorTeamLeaderName; + int? assessorTeamLeaderApprovalId; + String? assessorTeamLeaderApprovalName; + int? statusOfDRId; + String? statusOfDRName; + int? statusOfRequesterId; + String? statusOfRequesterName; + bool? approved; + String? approvalUserId; + String? approvalUserName; + String? approvalDate; + String? docDate; + String? approvalDocDate; + String? isAssigned; + String? poNumber; + int? apiDirectorId; + String? apiDirectorName; + int? apiDirectorApprovalId; + String? apiDirectorApprovalName; + List? trafAssessIds; + List? trafPRIds; + List? trafOfferIds; + int? id; + String? createdBy; + String? createdDate; + String? modifiedBy; + String? modifiedDate; + + TrafRequestDataModel( + {this.reqNo, + this.reqCode, + this.employeeId, + this.employeeName, + this.employeeEmail, + this.positionId, + this.positionName, + this.departments, + this.siteId, + this.siteName, + this.requesterExtensionNumber, + this.requesterExtensionName, + this.requesterExtensionPositionId, + this.requesterExtensionPositionName, + this.requestTypeId, + this.requestTypeName, + this.assetNDId, + this.modelId, + this.modelName, + this.manufacturerId, + this.manufacturerName, + this.assetId, + this.assetSerialNo, + this.assetNumber, + this.assetName, + this.assetAssetNDId, + this.qty, + this.purposeAnswer, + this.currentPractise, + this.censusQ1, + this.censusQ2, + this.censusQ3, + this.censusQ4, + this.trafContacts, + this.usingSolelyOrSharedId, + this.usingSolelyOrSharedName, + this.isEffectedId, + this.isEffectedName, + this.effectedServices, + this.isCombinationId, + this.isCombinationName, + this.usedWithCombination, + this.comment, + this.attachments, + this.isBudgetId, + this.isBudgetName, + this.firstLineManagerId, + this.firstLineManagerName, + this.firstLineManagerApprovalId, + this.firstLineManagerApprovalName, + this.tlapiId, + this.tlapiName, + this.assessorEmployeeId, + this.assessorEmployeeName, + this.secondLineManagerId, + this.secondLineManagerName, + this.secondLineManagerApprovalId, + this.secondLineManagerApprovalName, + this.hospitalManagementId, + this.hospitalManagementName, + this.hospitalManagementApprovalId, + this.hospitalManagementApprovalName, + this.oracleCodes, + this.assessorTeamLeaderId, + this.assessorTeamLeaderName, + this.assessorTeamLeaderApprovalId, + this.assessorTeamLeaderApprovalName, + this.statusOfDRId, + this.statusOfDRName, + this.statusOfRequesterId, + this.statusOfRequesterName, + this.approved, + this.approvalUserId, + this.approvalUserName, + this.approvalDate, + this.docDate, + this.approvalDocDate, + this.isAssigned, + this.poNumber, + this.apiDirectorId, + this.apiDirectorName, + this.apiDirectorApprovalId, + this.apiDirectorApprovalName, + this.trafAssessIds, + this.trafPRIds, + this.trafOfferIds, + this.id, + this.createdBy, + this.createdDate, + this.modifiedBy, + this.modifiedDate}); + + TrafRequestDataModel.fromJson(Map json) { + reqNo = json['reqNo']; + reqCode = json['reqCode']; + employeeId = json['employeeId']; + employeeName = json['employeeName']; + employeeEmail = json['employeeEmail']; + positionId = json['positionId']; + positionName = json['positionName']; + if (json['departments'] != null) { + departments = []; + json['departments'].forEach((v) { + departments!.add(new Departments.fromJson(v)); + }); + } + siteId = json['siteId']; + siteName = json['siteName']; + requesterExtensionNumber = json['requesterExtensionNumber']; + requesterExtensionName = json['requesterExtensionName']; + requesterExtensionPositionId = json['requesterExtensionPositionId']; + requesterExtensionPositionName = json['requesterExtensionPositionName']; + requestTypeId = json['requestTypeId']; + requestTypeName = json['requestTypeName']; + assetNDId = json['assetNDId']; + modelId = json['modelId']; + modelName = json['modelName']; + manufacturerId = json['manufacturerId']; + manufacturerName = json['manufacturerName']; + assetId = json['assetId']; + assetSerialNo = json['assetSerialNo']; + assetNumber = json['assetNumber']; + assetName = json['assetName']; + assetAssetNDId = json['assetAssetNDId']; + qty = json['qty']; + purposeAnswer = json['purposeAnswer']; + currentPractise = json['currentPractise']; + censusQ1 = json['censusQ1']; + censusQ2 = json['censusQ2']; + censusQ3 = json['censusQ3']; + censusQ4 = json['censusQ4']; + if (json['trafContacts'] != null) { + trafContacts = []; + json['trafContacts'].forEach((v) { + trafContacts!.add(new TrafContacts.fromJson(v)); + }); + } + usingSolelyOrSharedId = json['usingSolelyOrSharedId']; + usingSolelyOrSharedName = json['usingSolelyOrSharedName']; + isEffectedId = json['isEffectedId']; + isEffectedName = json['isEffectedName']; + effectedServices = json['effectedServices']; + isCombinationId = json['isCombinationId']; + isCombinationName = json['isCombinationName']; + usedWithCombination = json['usedWithCombination']; + comment = json['comment']; + if (json['attachments'] != null) { + attachments = []; + json['attachments'].forEach((v) { + attachments!.add(new Attachments.fromJson(v)); + }); + } + isBudgetId = json['isBudgetId']; + isBudgetName = json['isBudgetName']; + firstLineManagerId = json['firstLineManagerId']; + firstLineManagerName = json['firstLineManagerName']; + firstLineManagerApprovalId = json['firstLineManagerApprovalId']; + firstLineManagerApprovalName = json['firstLineManagerApprovalName']; + tlapiId = json['tlapiId']; + tlapiName = json['tlapiName']; + assessorEmployeeId = json['assessorEmployeeId']; + assessorEmployeeName = json['assessorEmployeeName']; + secondLineManagerId = json['secondLineManagerId']; + secondLineManagerName = json['secondLineManagerName']; + secondLineManagerApprovalId = json['secondLineManagerApprovalId']; + secondLineManagerApprovalName = json['secondLineManagerApprovalName']; + hospitalManagementId = json['hospitalManagementId']; + hospitalManagementName = json['hospitalManagementName']; + hospitalManagementApprovalId = json['hospitalManagementApprovalId']; + hospitalManagementApprovalName = json['hospitalManagementApprovalName']; + if (json['oracleCodes'] != null) { + oracleCodes = []; + json['oracleCodes'].forEach((v) { + oracleCodes!.add(new OracleCodes.fromJson(v)); + }); + } + assessorTeamLeaderId = json['assessorTeamLeaderId']; + assessorTeamLeaderName = json['assessorTeamLeaderName']; + assessorTeamLeaderApprovalId = json['assessorTeamLeaderApprovalId']; + assessorTeamLeaderApprovalName = json['assessorTeamLeaderApprovalName']; + statusOfDRId = json['statusOfDRId']; + statusOfDRName = json['statusOfDRName']; + statusOfRequesterId = json['statusOfRequesterId']; + statusOfRequesterName = json['statusOfRequesterName']; + approved = json['approved']; + approvalUserId = json['approvalUserId']; + approvalUserName = json['approvalUserName']; + approvalDate = json['approvalDate']; + docDate = json['docDate']; + approvalDocDate = json['approvalDocDate']; + isAssigned = json['isAssigned']; + poNumber = json['poNumber']; + apiDirectorId = json['apiDirectorId']; + apiDirectorName = json['apiDirectorName']; + apiDirectorApprovalId = json['apiDirectorApprovalId']; + apiDirectorApprovalName = json['apiDirectorApprovalName']; + trafAssessIds = json['trafAssessIds'].cast(); + trafPRIds = json['trafPRIds'].cast(); + trafOfferIds = json['trafOfferIds'].cast(); + id = json['id']; + createdBy = json['createdBy']; + createdDate = json['createdDate']; + modifiedBy = json['modifiedBy']; + modifiedDate = json['modifiedDate']; + } + + Map toJson() { + final Map data = new Map(); + data['reqNo'] = this.reqNo; + data['reqCode'] = this.reqCode; + data['employeeId'] = this.employeeId; + data['employeeName'] = this.employeeName; + data['employeeEmail'] = this.employeeEmail; + data['positionId'] = this.positionId; + data['positionName'] = this.positionName; + if (this.departments != null) { + data['departments'] = this.departments!.map((v) => v.toJson()).toList(); + } + data['siteId'] = this.siteId; + data['siteName'] = this.siteName; + data['requesterExtensionNumber'] = this.requesterExtensionNumber; + data['requesterExtensionName'] = this.requesterExtensionName; + data['requesterExtensionPositionId'] = this.requesterExtensionPositionId; + data['requesterExtensionPositionName'] = this.requesterExtensionPositionName; + data['requestTypeId'] = this.requestTypeId; + data['requestTypeName'] = this.requestTypeName; + data['assetNDId'] = this.assetNDId; + data['modelId'] = this.modelId; + data['modelName'] = this.modelName; + data['manufacturerId'] = this.manufacturerId; + data['manufacturerName'] = this.manufacturerName; + data['assetId'] = this.assetId; + data['assetSerialNo'] = this.assetSerialNo; + data['assetNumber'] = this.assetNumber; + data['assetName'] = this.assetName; + data['assetAssetNDId'] = this.assetAssetNDId; + data['qty'] = this.qty; + data['purposeAnswer'] = this.purposeAnswer; + data['currentPractise'] = this.currentPractise; + data['censusQ1'] = this.censusQ1; + data['censusQ2'] = this.censusQ2; + data['censusQ3'] = this.censusQ3; + data['censusQ4'] = this.censusQ4; + if (this.trafContacts != null) { + data['trafContacts'] = this.trafContacts!.map((v) => v.toJson()).toList(); + } + data['usingSolelyOrSharedId'] = this.usingSolelyOrSharedId; + data['usingSolelyOrSharedName'] = this.usingSolelyOrSharedName; + data['isEffectedId'] = this.isEffectedId; + data['isEffectedName'] = this.isEffectedName; + data['effectedServices'] = this.effectedServices; + data['isCombinationId'] = this.isCombinationId; + data['isCombinationName'] = this.isCombinationName; + data['usedWithCombination'] = this.usedWithCombination; + data['comment'] = this.comment; + if (this.attachments != null) { + data['attachments'] = this.attachments!.map((v) => v.toJson()).toList(); + } + data['isBudgetId'] = this.isBudgetId; + data['isBudgetName'] = this.isBudgetName; + data['firstLineManagerId'] = this.firstLineManagerId; + data['firstLineManagerName'] = this.firstLineManagerName; + data['firstLineManagerApprovalId'] = this.firstLineManagerApprovalId; + data['firstLineManagerApprovalName'] = this.firstLineManagerApprovalName; + data['tlapiId'] = this.tlapiId; + data['tlapiName'] = this.tlapiName; + data['assessorEmployeeId'] = this.assessorEmployeeId; + data['assessorEmployeeName'] = this.assessorEmployeeName; + data['secondLineManagerId'] = this.secondLineManagerId; + data['secondLineManagerName'] = this.secondLineManagerName; + data['secondLineManagerApprovalId'] = this.secondLineManagerApprovalId; + data['secondLineManagerApprovalName'] = this.secondLineManagerApprovalName; + data['hospitalManagementId'] = this.hospitalManagementId; + data['hospitalManagementName'] = this.hospitalManagementName; + data['hospitalManagementApprovalId'] = this.hospitalManagementApprovalId; + data['hospitalManagementApprovalName'] = this.hospitalManagementApprovalName; + if (this.oracleCodes != null) { + data['oracleCodes'] = this.oracleCodes!.map((v) => v.toJson()).toList(); + } + data['assessorTeamLeaderId'] = this.assessorTeamLeaderId; + data['assessorTeamLeaderName'] = this.assessorTeamLeaderName; + data['assessorTeamLeaderApprovalId'] = this.assessorTeamLeaderApprovalId; + data['assessorTeamLeaderApprovalName'] = this.assessorTeamLeaderApprovalName; + data['statusOfDRId'] = this.statusOfDRId; + data['statusOfDRName'] = this.statusOfDRName; + data['statusOfRequesterId'] = this.statusOfRequesterId; + data['statusOfRequesterName'] = this.statusOfRequesterName; + data['approved'] = this.approved; + data['approvalUserId'] = this.approvalUserId; + data['approvalUserName'] = this.approvalUserName; + data['approvalDate'] = this.approvalDate; + data['docDate'] = this.docDate; + data['approvalDocDate'] = this.approvalDocDate; + data['isAssigned'] = this.isAssigned; + data['poNumber'] = this.poNumber; + data['apiDirectorId'] = this.apiDirectorId; + data['apiDirectorName'] = this.apiDirectorName; + data['apiDirectorApprovalId'] = this.apiDirectorApprovalId; + data['apiDirectorApprovalName'] = this.apiDirectorApprovalName; + data['trafAssessIds'] = this.trafAssessIds; + data['trafPRIds'] = this.trafPRIds; + data['trafOfferIds'] = this.trafOfferIds; + data['id'] = this.id; + data['createdBy'] = this.createdBy; + data['createdDate'] = this.createdDate; + data['modifiedBy'] = this.modifiedBy; + data['modifiedDate'] = this.modifiedDate; + return data; + } +} + +class TrafContacts { + int? id; + int? trafId; + String? name; + String? telephone; + String? notes; + + TrafContacts({this.id, this.trafId, this.name, this.telephone, this.notes}); + + TrafContacts.fromJson(Map json) { + id = json['id']; + trafId = json['trafId']; + name = json['name']; + telephone = json['telephone']; + notes = json['notes']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['trafId'] = this.trafId; + data['name'] = this.name; + data['telephone'] = this.telephone; + data['notes'] = this.notes; + return data; + } +} + +class OracleCodes { + int? id; + int? assetNDId; + int? codeTypeId; + String? codeTypeName; + int? codeTypeValue; + String? codeValue; + + OracleCodes({this.id, this.assetNDId, this.codeTypeId, this.codeTypeName, this.codeTypeValue, this.codeValue}); + + OracleCodes.fromJson(Map json) { + id = json['id']; + assetNDId = json['assetNDId']; + codeTypeId = json['codeTypeId']; + codeTypeName = json['codeTypeName']; + codeTypeValue = json['codeTypeValue']; + codeValue = json['codeValue']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['assetNDId'] = this.assetNDId; + data['codeTypeId'] = this.codeTypeId; + data['codeTypeName'] = this.codeTypeName; + data['codeTypeValue'] = this.codeTypeValue; + data['codeValue'] = this.codeValue; + return data; + } +} + +class Departments { + int? id; + int? trafId; + int? departmentId; + + Departments({this.id, this.trafId, this.departmentId}); + + Departments.fromJson(Map json) { + id = json['id']; + trafId = json['trafId']; + departmentId = json['departmentId']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['trafId'] = this.trafId; + data['departmentId'] = this.departmentId; + return data; + } +} + +class Attachments { + int? id; + int? trafId; + String? attachmentName; + + Attachments({this.id, this.trafId, this.attachmentName}); + + Attachments.fromJson(Map json) { + id = json['id']; + trafId = json['trafId']; + attachmentName = json['attachmentName']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['trafId'] = this.trafId; + data['attachmentName'] = this.attachmentName; + return data; + } +} diff --git a/lib/modules/traf_module/traf_request_provider.dart b/lib/modules/traf_module/traf_request_provider.dart new file mode 100644 index 00000000..85459f5c --- /dev/null +++ b/lib/modules/traf_module/traf_request_provider.dart @@ -0,0 +1,32 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; + +import 'traf_request_model.dart'; + +class TrafRequestProvider extends ChangeNotifier { + bool isLoading = false; + + TrafRequestDataModel? trafRequestDataModel; + + Future getTRAFById(int trafId) async { + try { + isLoading = true; + notifyListeners(); + Response response = await ApiManager.instance.get("${URLs.getTRAFById}?tRAFId=$trafId"); + if (response.statusCode >= 200 && response.statusCode < 300) { + trafRequestDataModel = TrafRequestDataModel.fromJson(json.decode(response.body)["data"]); + } + isLoading = false; + notifyListeners(); + return 0; + } catch (error) { + isLoading = false; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/modules/traf_module/update_traf_request_page.dart b/lib/modules/traf_module/update_traf_request_page.dart new file mode 100644 index 00000000..4fcea820 --- /dev/null +++ b/lib/modules/traf_module/update_traf_request_page.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/generic_attachment_model.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/modules/traf_module/traf_request_model.dart'; +import 'package:test_sa/modules/traf_module/traf_request_provider.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/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/classification_lookup_provider.dart'; +import 'package:test_sa/providers/lookups/recommendation_lookup_provider.dart'; +import 'package:test_sa/providers/lookups/request_type_lookup_provider.dart'; +import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; +import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; + +class UpdateTrafRequestPage extends StatefulWidget { + static const String id = "/update-TRAF"; + + UpdateTrafRequestPage({Key? key}) : super(key: key); + + @override + _UpdateTrafRequestPageState createState() { + return _UpdateTrafRequestPageState(); + } +} + +class _UpdateTrafRequestPageState extends State { + Lookup? requestType; + Lookup? assessorRecommendation; + Lookup? classificationType; + late TrafRequestProvider trafRequestProvider; + + late TrafRequestDataModel trafRequest; + + List abc = []; + + List _deviceList = []; + Asset? asset; + List attachments = []; + + @override + void initState() { + super.initState(); + Provider.of(context, listen: false).reset(); + Provider.of(context, listen: false).reset(); + trafRequestProvider = Provider.of(context, listen: false); + trafRequest = trafRequestProvider.trafRequestDataModel!; + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const DefaultAppBar(title: "Update TRAF Request"), + body: Column( + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: "Classification", + initialValue: classificationType, + onSelect: (value) { + classificationType = value; + // trafRequest?.requestTypeId = value?.value; + setState(() {}); + }, + ), + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: context.translation.requestType, + initialValue: requestType, + onSelect: (value) { + requestType = value; + setState(() {}); + }, + ), + if (requestType?.id == 732) ...[ + 12.height, + AppTextFormField( + initialValue: "", + makeMultiLinesNull: true, + labelText: "Recommended Quantity", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + textInputType: TextInputType.number, + onChange: (value) { + trafRequest.qty = int.tryParse(value); + }, + ), + ], + if (requestType?.id == 733) ...[ + 12.height, + AssetPicker( + device: asset, + editable: false, + showLoading: false, + + // borderColor: AppColor.black20, + // backgroundColor: AppColor.white936, + onPick: (asset) async { + this.asset = asset; + setState(() {}); + // pendingAssetServiceRequest = null; + // _serviceRequest.device = asset; + // await checkAssetForPendingServiceRequest(asset.id!.toInt()); + // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + // showPendingRequestBottomSheet(); + // } + }, + ), + ], + // 12.height, + // MultipleItemDropDownMenu( + // context: context, + // showAsBottomSheet: true, + // backgroundColor: AppColor.neutral100, + // showShadow: false, + // showCancel: true, + // title: "Please specify departments and relations", + // initialValue: abc, + // onSelect: (value) { + // abc = value ?? []; + // // setState(() { + // // + // // }); + // }, + // ), + 12.height, + Text( + "Quantity to be Transfer", + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, fontWeight: FontWeight.w500), + ), + 8.height, + AssetPicker( + deviceList: _deviceList, + showLoading: false, + borderColor: AppColor.black20, + buttonColor: AppColor.white936, + multiSelection: true, + onAssetRemove: (itemId) { + _deviceList.removeWhere((asset) => asset.id?.toInt() == itemId); + setState(() {}); + }, + onMultiAssetPick: (assetList) { + _deviceList.addAll(assetList); + final seenIds = {}; + _deviceList = _deviceList.where((item) => seenIds.add(item.id)).toList(); + setState(() {}); + }, + ), + 12.height, + SingleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + title: "Assessor Recommendation", + initialValue: assessorRecommendation, + onSelect: (value) { + assessorRecommendation = value; + // trafRequest?.requestTypeId = value?.value; + setState(() {}); + }, + ), + 12.height, + AppTextFormField( + initialValue: "", + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + labelText: "Assessor comment", + backgroundColor: AppColor.fieldBgColor(context), + labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), + showShadow: false, + onChange: (value) { + trafRequest?.comment = value; // todo confirm parameter shaheer + }, + ), + 12.height, + AttachmentPicker( + label: context.translation.attachFiles, + attachment: attachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + ], + ).toShadowContainer(context, borderRadius: 20, padding: 12), + ).expanded, + FooterActionButton.footerContainer( + context: context, + child: AppFilledButton(buttonColor: AppColor.primary10, label: "Update", onPressed: () {} + // buttonColor: AppColor.primary10, + ), + ), + ], + )); + } +} diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index 2434230c..02cb825b 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -25,6 +25,7 @@ class AppTextFormField extends StatefulWidget { final TextStyle? style; final TextStyle? labelStyle; final TextStyle? hintStyle; + final TextStyle? floatingLabelStyle; final bool enable; final TextAlign? textAlign; final FocusNode? node; @@ -58,6 +59,7 @@ class AppTextFormField extends StatefulWidget { this.hintText, this.labelText, this.hintStyle, + this.floatingLabelStyle, this.textInputType = TextInputType.text, this.initialValue, // Provide default value this.enable = true, @@ -183,12 +185,16 @@ class _AppTextFormFieldState extends State { onChanged: widget.onChange, obscureText: widget.obscureText ?? false, keyboardType: widget.textInputType, - maxLines: widget.makeMultiLinesNull ? null:widget.textInputType == TextInputType.multiline ? 4 : 1, + maxLines: widget.makeMultiLinesNull + ? null + : widget.textInputType == TextInputType.multiline + ? 4 + : 1, obscuringCharacter: "*", controller: widget.controller, textInputAction: widget.textInputType == TextInputType.multiline ? null : widget.textInputAction ?? TextInputAction.next, onEditingComplete: widget.onAction ?? () => FocusScope.of(context).nextFocus(), - style: widget.style ?? AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500,color:context.isDark?AppColor.white10: AppColor.black10), + style: widget.style ?? AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.black10), onTap: widget.onTap, decoration: InputDecoration( alignLabelWithHint: widget.alignLabelWithHint, @@ -208,9 +214,12 @@ class _AppTextFormFieldState extends State { ? (widget.enableColor ?? AppColor.neutral40) : AppColor.background(context)), errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), - floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.neutral20), + floatingLabelStyle: widget.floatingLabelStyle ?? AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.neutral20), hintText: widget.hintText ?? "", - labelText: (widget.showSpeechToText && _speechToText.isListening) ? "Listening..." : widget.labelText ?? "", + // labelText: (widget.showSpeechToText && _speechToText.isListening) ? "Listening..." : widget.labelText ?? "", + label: Text( + (widget.showSpeechToText && _speechToText.isListening) ? "Listening..." : widget.labelText ?? "", + ), labelStyle: widget.labelStyle, hintStyle: widget.labelStyle, prefixIcon: widget.prefixIcon ?? diff --git a/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart new file mode 100644 index 00000000..723b3faf --- /dev/null +++ b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart @@ -0,0 +1,251 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/app_loading_manager.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/views/widgets/bottom_sheets/selection_bottom_sheet.dart'; +import 'package:test_sa/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart'; +import 'package:test_sa/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart'; + +import '../../models/base.dart'; +import '../app_style/app_color.dart'; + +class MultipleItemDropDownMenu extends StatefulWidget { + final BuildContext context; + final Function(List?)? onSelect; // Now accepts nullable values + final List initialValue; + final T? disableValue; + final bool enabled; + final bool showAsBottomSheet; + final bool showAsFullScreenDialog; + final List? staticData; + final String title; + final double? height; + final bool showShadow; + final bool showCancel; + final Color? backgroundColor; // Now nullable + final bool? loading; // Now nullable + + /// To use a static data (without calling API) + /// just send [NullableLoadingProvider] as generic data type and fill the [staticData] + const MultipleItemDropDownMenu({ + Key? key, + this.title = "", + required this.context, + this.onSelect, + this.initialValue = const [], + this.disableValue, + this.enabled = true, + this.height, + this.showAsBottomSheet = false, + this.showAsFullScreenDialog = true, + this.staticData, // Provide a default empty list + this.showShadow = true, + this.showCancel = false, + this.backgroundColor, + this.loading, + }) : super(key: key); + + @override + State> createState() => _MultipleItemDropDownMenuState(); +} + +class _MultipleItemDropDownMenuState extends State> { + List _selectedItem = []; + X? provider; + + @override + void initState() { + if (X != NullableLoadingProvider) { + provider = Provider.of(widget.context); + } + + if (widget.initialValue.isNotEmpty) { + // Get the source list + final sourceList = (X == NullableLoadingProvider ? widget.staticData : provider?.items); + + if (sourceList != null && sourceList.isNotEmpty) { + // Collect matches based on identifier + final results = sourceList.where((element) => widget.initialValue!.any((init) => init.identifier == element.identifier)).toList(); + + if (results.isNotEmpty) { + _selectedItem + ..clear() + ..addAll(results.cast()); + + // Call onSelect if items changed + if (widget.onSelect != null) { + widget.onSelect!(_selectedItem); + } + } + } + } + + // if (widget.initialValue != null) { + // final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier); + // if (result?.isNotEmpty ?? false) _selectedItem.add(result!.first as T); + // if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) { + // widget.onSelect!(_selectedItem); // Non-null assertion after null check + // } + // } + super.initState(); + } + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant MultipleItemDropDownMenu oldWidget) { + if (widget.initialValue.isNotEmpty) { + // Get the source list + final sourceList = (X == NullableLoadingProvider ? widget.staticData : provider?.items); + + if (sourceList != null && sourceList.isNotEmpty) { + // Collect matches based on identifier + final results = sourceList.where((element) => widget.initialValue!.any((init) => init.identifier == element.identifier)).toList(); + + if (results.isNotEmpty) { + _selectedItem + ..clear() + ..addAll(results.cast()); + + // Call onSelect if items changed + if (widget.onSelect != null) { + widget.onSelect!(_selectedItem); + } + } + } + } + + // if (widget.initialValue != null) { + // final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier); + // + // if (result?.isNotEmpty ?? false) { + // _selectedItem.add(result!.first as T); + // } else { + // _selectedItem = []; + // } + // // if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) { + // // widget.onSelect!(_selectedItem); // Non-null assertion after null check + // // } + // } else { + // _selectedItem = []; + // } + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + final isEmpty = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.isEmpty ?? true; + return AppLoadingManager( + isLoading: widget.loading ?? ((X == NullableLoadingProvider) ? false : provider?.loading ?? false), + // Provide default value if null + isFailedLoading: (X == NullableLoadingProvider) ? false : provider?.items == null, + stateCode: (X == NullableLoadingProvider) ? 200 : provider?.stateCode, + onRefresh: () async { + if (X != NullableLoadingProvider) { + provider?.reset(); + await provider?.getData(); + } + }, + child: Container( + // height: widget.height ?? 60.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + decoration: BoxDecoration( + color: context.isDark && (widget.enabled == false || isEmpty) + ? AppColor.neutral20 + : (widget.enabled == false || isEmpty) + ? AppColor.neutral40 + : widget.backgroundColor ?? AppColor.background(context), + borderRadius: BorderRadius.circular(10), + boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.title, + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + ), + if (_selectedItem.isEmpty) + Text( + context.translation.select, + style: Theme.of(context).textTheme.bodyLarge, + ) + else + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 8), + separatorBuilder: (cxt, index) => const Divider( + thickness: 1, + color: Colors.white, + ), + itemBuilder: (cxt, index) => Text( + _selectedItem[index].name ?? "", // Null-aware operator for value.name + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.black10), + ), + itemCount: _selectedItem.length, + ), + ], + ) + .onPress( + widget.enabled && widget.showAsFullScreenDialog + ? () { + openDialog(); + } + : null, + ) + .expanded, + if (widget.enabled) const PositionedDirectional(end: 0, child: Icon(Icons.keyboard_arrow_down_rounded)), + ], + ), + ), + ); + } + + void openDialog() async { + Widget child = MultipleSelectionFullScreenDialog( + // Specify generic type + items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List) ?? [], + // Provide default empty list if null + selectedItem: _selectedItem, + disableItem: widget.disableValue, + title: widget.title, + showCancel: widget.showCancel, + onSelect: (selectedT) { + setState(() { + _selectedItem = selectedT; + }); + widget.onSelect!(selectedT); + }, + builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name + ); + pushRouter(child); + // final selectedT = await pushRouter(child); + // if (selectedT != null) { + // setState(() { + // _selectedItem = selectedT; + // }); + // widget.onSelect!(selectedT); // Non-null assertion after null check + // } + } + + Future pushRouter(Widget child) async { + // PageRoute pRoute = !Platform.isIOS ? CupertinoPageRoute(fullscreenDialog: true, builder: (context) => child) : MaterialPageRoute(fullscreenDialog: true, builder: (context) => child); + + return await Navigator.of(context).push(CupertinoPageRoute(fullscreenDialog: true, builder: (context) => child)); + } +} diff --git a/lib/new_views/common_widgets/single_item_drop_down_menu.dart b/lib/new_views/common_widgets/single_item_drop_down_menu.dart index c36af1a3..02e0e16a 100644 --- a/lib/new_views/common_widgets/single_item_drop_down_menu.dart +++ b/lib/new_views/common_widgets/single_item_drop_down_menu.dart @@ -168,50 +168,50 @@ class _SingleItemDropDownMenuState( - // Specify return type - context: context, - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - clipBehavior: Clip.antiAliasWithSaveLayer, - builder: (BuildContext context) => SelectionBottomSheet( - // Specify generic type - items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List) ?? [], - // Provide default empty list if null - selectedItem: _selectedItem, - title: widget.title, - showCancel: widget.showCancel, - onSelect: (selectedT) { - setState(() { - _selectedItem = selectedT; - }); - widget.onSelect!(selectedT); - }, - builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name - ), - ); - // if (selectedT != null) { - // setState(() { - // _selectedItem = selectedT; - // }); - // widget.onSelect!(selectedT); // Non-null assertion after null check - // } - } - : null) - : null), + ), ], - ), + ).onPress(widget.enabled && widget.showAsFullScreenDialog + ? () { + openDialog(); + } + : widget.enabled + ? (widget.showAsBottomSheet + ? () async { + final selectedT = await showModalBottomSheet( + // Specify return type + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => SelectionBottomSheet( + // Specify generic type + items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List) ?? [], + // Provide default empty list if null + selectedItem: _selectedItem, + title: widget.title, + showCancel: widget.showCancel, + onSelect: (selectedT) { + setState(() { + _selectedItem = selectedT; + }); + widget.onSelect!(selectedT); + }, + builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name + ), + ); + // if (selectedT != null) { + // setState(() { + // _selectedItem = selectedT; + // }); + // widget.onSelect!(selectedT); // Non-null assertion after null check + // } + } + : null) + : null), ], ), ), diff --git a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart index edd2ba89..ff090f7b 100644 --- a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart +++ b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart @@ -3,9 +3,11 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_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/modules/cm_module/views/nurse/create_new_request_view.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/create_task_view.dart'; +import 'package:test_sa/modules/traf_module/create_traf_request_page.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/pages/gas_refill_request_form.dart'; import 'package:test_sa/views/pages/device_transfer/create__device_transfer_request.dart'; @@ -101,6 +103,7 @@ class CreateRequestModel { list.add(CreateRequestModel(context.translation.transferAsset, "add_icon", CreateDeviceTransferRequest.id)); //TODO uncommit this to enable task. list.add(CreateRequestModel(context.translation.task, "add_icon", CreateTaskView.id)); + list.add(CreateRequestModel("Traf".addTranslation, "add_icon", CreateTRAFRequestPage.id)); } return list; } diff --git a/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart b/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart index bad36d00..397ac41c 100644 --- a/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart +++ b/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart @@ -21,9 +21,7 @@ class GasRefillItemView extends StatelessWidget { @override Widget build(BuildContext context) { - if (requestData != null) { - return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -144,6 +142,6 @@ class GasRefillItemView extends StatelessWidget { }); } - return const SizedBox(); + return const SizedBox(); } } diff --git a/lib/providers/lookups/classification_lookup_provider.dart b/lib/providers/lookups/classification_lookup_provider.dart new file mode 100644 index 00000000..87b57efb --- /dev/null +++ b/lib/providers/lookups/classification_lookup_provider.dart @@ -0,0 +1,33 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class ClassificationLookupProvider extends LoadingListNotifier { + @override + Future getData() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getClassificationTypeLookup); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/lookups/recommendation_lookup_provider.dart b/lib/providers/lookups/recommendation_lookup_provider.dart new file mode 100644 index 00000000..a0bbe48a --- /dev/null +++ b/lib/providers/lookups/recommendation_lookup_provider.dart @@ -0,0 +1,33 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class RecommendationLookupProvider extends LoadingListNotifier { + @override + Future getData() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getRecommendationTypeLookup); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/lookups/request_type_lookup_provider.dart b/lib/providers/lookups/request_type_lookup_provider.dart new file mode 100644 index 00000000..cc94de62 --- /dev/null +++ b/lib/providers/lookups/request_type_lookup_provider.dart @@ -0,0 +1,33 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class RequestTypeLookupProvider extends LoadingListNotifier { + @override + Future getData() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getTrafRequestTypeLookup); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/lookups/yes_no_lookup_provider.dart b/lib/providers/lookups/yes_no_lookup_provider.dart new file mode 100644 index 00000000..a089069b --- /dev/null +++ b/lib/providers/lookups/yes_no_lookup_provider.dart @@ -0,0 +1,33 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class YesNoLookupProvider extends LoadingListNotifier { + @override + Future getData() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getYesNoRequestTypeLookup); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/views/widgets/bottom_sheets/muliple_selection_bottom_sheet.dart b/lib/views/widgets/bottom_sheets/muliple_selection_bottom_sheet.dart new file mode 100644 index 00000000..a9abe36e --- /dev/null +++ b/lib/views/widgets/bottom_sheets/muliple_selection_bottom_sheet.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_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'; + +typedef SelectionBuilderString = String Function(dynamic); + +class MultipleSelectionBottomSheet extends StatefulWidget { + final List? items; + final List selectedItem; // Now nullable + final String title; + final SelectionBuilderString builderString; + final bool showCancel; + final Function(List) onSelect; + + const MultipleSelectionBottomSheet({Key? key, this.items = const [], this.selectedItem = const [], this.title = "", required this.builderString, this.showCancel = false, required this.onSelect}) + : super(key: key); + + @override + _MultipleSelectionBottomSheetState createState() => _MultipleSelectionBottomSheetState(); +} + +class _MultipleSelectionBottomSheetState extends State> { + late List _selectedValue; // Now nullable + + String query = ""; + + List? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList(); + + @override + void initState() { + _selectedValue = widget.selectedItem; + super.initState(); + } + + FocusNode searchFocusNode = FocusNode(); + + @override + void dispose() { + searchFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height * .7, + color: Theme.of(context).scaffoldBackgroundColor, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + widget.title.heading5(context).expanded, + if (widget.showCancel) + AnimatedOpacity( + opacity: _selectedValue != null ? 1 : 0, + duration: const Duration(milliseconds: 250), + child: Container( + height: 30, + decoration: BoxDecoration(color: const Color(0xffF63939).withOpacity(.75), borderRadius: BorderRadius.circular(30)), + padding: const EdgeInsets.only(left: 8, right: 12, top: 4, bottom: 4), + alignment: Alignment.center, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.clear, color: Colors.white, size: 16), + 4.width, + const Text( + "Clear", + style: TextStyle(fontSize: 14, color: Colors.white), + ) + ], + ), + ).onPress(_selectedValue.isNotEmpty + ? () { + Navigator.pop(context); + widget.onSelect([]); + } + : null), + ), + ], + ).paddingOnly(top: 16, start: 16, end: 16, bottom: 0), + TextField( + onChanged: (queryString) { + query = queryString; + setState(() {}); + }, + style: const TextStyle(fontSize: 14), + focusNode: searchFocusNode, + decoration: InputDecoration( + hintText: 'Search by name', + labelText: 'Search', + labelStyle: TextStyle(color: AppColor.textColor(context)), + filled: true, + fillColor: AppColor.fieldBgColor(context), + hintStyle: const TextStyle(fontSize: 14), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: AppColor.blueStatus(context), width: 2.0), + borderRadius: const BorderRadius.all(Radius.circular(12.0)), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: AppColor.blueStatus(context), width: 1.0), + borderRadius: const BorderRadius.all(Radius.circular(12.0)), + ), + contentPadding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + ), + ).paddingOnly(top: 16, start: 16, end: 16, bottom: 16), + Expanded( + // Wrap ListView with Expanded + child: ListView.builder( + itemCount: filteredList?.length, + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) => Theme( + data: Theme.of(context).copyWith( + radioTheme: RadioThemeData( + fillColor: MaterialStateColor.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return AppColor.textColor(context); // Active color + } + return Colors.grey; // Inactive color + }), + ), + ), + child: CheckboxListTile( + value: checkItContains(filteredList![index]), + dense: true, + // groupValue: _selectedValue, + activeColor: AppColor.textColor(context), + contentPadding: const EdgeInsets.only(left: 16, right: 16), + onChanged: (value) { + if (value == true) { + _selectedValue.add(filteredList![index]); + } else if (value == false) { + _selectedValue.remove(filteredList![index]); + } + searchFocusNode.unfocus(); + setState(() {}); + }, + title: Text( + widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + ), + ), + ), + 8.height, + if (_selectedValue.isNotEmpty) + FooterActionButton.footerContainer( + context: context, + child: AppFilledButton( + label: context.translation.select, + maxWidth: true, + onPressed: () { + Navigator.pop(context); + widget.onSelect(_selectedValue); + }, + )), + ], + ), + ); + } + + bool? checkItContains(T) { + return widget.items?.contains(T); + } +} diff --git a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart new file mode 100644 index 00000000..806b9de3 --- /dev/null +++ b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/base.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'; + +typedef SelectionBuilderString = String Function(dynamic); + +class MultipleSelectionFullScreenDialog extends StatefulWidget { + final List? items; + final List selectedItem; // Now nullable + final T? disableItem; // Now nullable + final String title; + final bool showCancel; + final SelectionBuilderString builderString; + final Function(List) onSelect; + + const MultipleSelectionFullScreenDialog( + {Key? key, this.items, this.selectedItem = const [], this.disableItem, this.title = "", required this.builderString, this.showCancel = false, required this.onSelect}) + : super(key: key); + + @override + _SelectionBottomSheetState createState() => _SelectionBottomSheetState(); +} + +class _SelectionBottomSheetState extends State> { + late List _selectedValue; // Now nullable + + String query = ""; + + List? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList(); + + @override + void initState() { + _selectedValue = widget.selectedItem; + super.initState(); + } + + FocusNode searchFocusNode = FocusNode(); + + @override + void dispose() { + searchFocusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + for (var abc in filteredList ?? []) { + print(abc.toJson()); + } + return Scaffold( + appBar: AppBar( + title: widget.title.heading5(context), + actions: [ + if (widget.showCancel) + AnimatedContainer( + height: 24, + duration: const Duration(milliseconds: 250), + margin: const EdgeInsets.only(right: 16), + decoration: BoxDecoration(color: _selectedValue.isNotEmpty ? const Color(0xffF63939).withOpacity(.75) : Colors.grey.withOpacity(.75), borderRadius: BorderRadius.circular(30)), + padding: const EdgeInsets.only(left: 4, right: 8, top: 4, bottom: 4), + alignment: Alignment.center, + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Icons.clear, color: Colors.white, size: 16), + 4.width, + const Text( + "Clear", + style: TextStyle(fontSize: 14, color: Colors.white, height: 1), + ) + ], + ).onPress(_selectedValue.isNotEmpty + ? () { + Navigator.pop(context); + widget.onSelect([]); + } + : null), + ), + ], + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SearchBar( + focusNode: searchFocusNode, + elevation: WidgetStateProperty.all(0), + backgroundColor: WidgetStateProperty.all(context.isDark ? AppColor.neutral120 : null), + leading: Icon(Icons.search, color: AppColor.iconColor(context)), + textStyle: WidgetStateProperty.all( + TextStyle(color: AppColor.textColor(context), fontSize: 16.0), + ), + hintStyle: WidgetStateProperty.all( + TextStyle(color: AppColor.textColor(context), fontSize: 14.0), + ), + hintText: 'Search by name', + onChanged: (queryString) { + query = queryString; + setState(() {}); + }, + ).paddingOnly(top: 16, start: 16, end: 16, bottom: 8), + // TextField( + // onChanged: (queryString) { + // query = queryString; + // setState(() {}); + // }, + // style: const TextStyle(fontSize: 14), + // focusNode: searchFocusNode, + // decoration: InputDecoration( + // hintText: 'Search by name', + // labelText: 'Search', + // hintStyle: const TextStyle(fontSize: 14), + // focusedBorder: OutlineInputBorder( + // borderSide: BorderSide(color: AppColor.blueStatus(context), width: 2.0), + // borderRadius: const BorderRadius.all(Radius.circular(12.0)), + // ), + // enabledBorder: OutlineInputBorder( + // borderSide: BorderSide(color: AppColor.blueStatus(context), width: 1.0), + // borderRadius: const BorderRadius.all(Radius.circular(12.0)), + // ), + // contentPadding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + // ), + // ), + 8.height, + Expanded( + child: ListView.builder( + itemCount: filteredList?.length, + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) { + bool isDisabledItem = widget.disableItem != null && widget.disableItem?.identifier == filteredList![index].identifier; + return Theme( + data: Theme.of(context).copyWith( + radioTheme: RadioThemeData( + fillColor: MaterialStateColor.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return AppColor.iconColor(context); // Active color + } + return Colors.grey; // Inactive color + }), + ), + ), + child: CheckboxListTile( + value: checkItContains(filteredList![index]), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + activeColor: AppColor.textColor(context), + contentPadding: const EdgeInsets.only(left: 16, right: 16), + onChanged: (value) { + // if (checkItContains(filteredList![index]) ?? false) { + // _selectedValue.remove(filteredList![index]); + // } else { + // _selectedValue.add(filteredList![index]); + // } + if (value == true) { + _selectedValue.add(filteredList![index]); + } else if (value == false) { + _selectedValue.remove(filteredList![index]); + } + searchFocusNode.unfocus(); + setState(() {}); + }, + title: Text( + widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ), + ); + }), + ), + 8.height, + if (_selectedValue.isNotEmpty) + FooterActionButton.footerContainer( + context: context, + child: AppFilledButton( + label: context.translation.select, + maxWidth: true, + onPressed: () { + Navigator.pop(context); + widget.onSelect(_selectedValue); + }, + )), + ], + ), + ); + } + + bool? checkItContains(T) { + return _selectedValue.contains(T); + } +} diff --git a/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart index ce08754f..b7227dda 100644 --- a/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart +++ b/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart @@ -87,9 +87,7 @@ class _SelectionBottomSheetState extends State(0), - backgroundColor: WidgetStateProperty.all( - AppColor.fieldBgColor(context), // Your custom background color - ), + backgroundColor: WidgetStateProperty.all(context.isDark ? AppColor.neutral120 : null), leading: Icon(Icons.search, color: AppColor.iconColor(context)), textStyle: WidgetStateProperty.all( TextStyle(color: AppColor.textColor(context), fontSize: 16.0), From 76acdddabcffc699e4b4737cad9c920ac05cde65 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 15 Oct 2025 07:02:36 +0300 Subject: [PATCH 2/9] asset by oracle code api added, departments lookup added. --- lib/controllers/api_routes/urls.dart | 6 ++ .../providers/api/oracle_code_provider.dart | 9 +- lib/main.dart | 2 + ..._auto_complete_by_dynamic_codes_model.dart | 27 +++++ lib/models/new_models/traf_department.dart | 101 ++++++++++++++++++ .../asset_auto_complete_field.dart | 15 +-- .../traf_module/create_traf_request_page.dart | 18 ++-- .../multiple_item_drop_down_menu.dart | 4 +- .../single_item_drop_down_menu.dart | 4 +- .../asset_transfer_status_provider.dart | 2 +- lib/providers/department_provider.dart | 2 +- .../cylinder_size_provider.dart | 2 +- .../cylinder_type_provider.dart | 2 +- .../gas_status_provider.dart | 2 +- .../gas_types_provider.dart | 2 +- .../gas_request_providers/site_provider.dart | 4 +- lib/providers/loading_list_notifier.dart | 4 +- .../classification_lookup_provider.dart | 2 +- .../lookups/department_lookup_provider.dart | 34 ++++++ .../recommendation_lookup_provider.dart | 2 +- .../lookups/request_type_lookup_provider.dart | 2 +- .../lookups/yes_no_lookup_provider.dart | 2 +- .../ppm_asset_availability_provider.dart | 2 +- .../ppm_checklist_status_provider.dart | 2 +- lib/providers/ppm_device_status_provider.dart | 2 +- .../ppm_electrical_safety_provider.dart | 2 +- lib/providers/ppm_service_provider.dart | 2 +- lib/providers/ppm_task_status_provider.dart | 2 +- lib/providers/ppm_visit_status_provider.dart | 2 +- .../commissioning_status_provider.dart | 2 +- .../equipment_status_provider.dart | 2 +- .../first_action_provider.dart | 2 +- .../last_situation_provider.dart | 2 +- .../loan_availability_provider.dart | 2 +- .../priority_provider.dart | 2 +- .../reject_reason_provider.dart | 2 +- .../requested_through_provider.dart | 2 +- .../type_of_request_provider.dart | 2 +- .../task_job_provider.dart | 14 +-- .../work_order/activity_status_provider.dart | 2 +- .../need_visit_reminder_time_provider.dart | 2 +- lib/providers/work_order/reason_provider.dart | 2 +- .../work_order/retirement_type_provider.dart | 2 +- .../work_order/service_type_provider.dart | 2 +- .../supplier_engineer_provider.dart | 2 +- lib/providers/work_order/vendor_provider.dart | 2 +- .../work_order/wo_frame_provider.dart | 2 +- .../multiple_selection_fullscreen_dialog.dart | 3 - 48 files changed, 246 insertions(+), 67 deletions(-) create mode 100644 lib/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart create mode 100644 lib/models/new_models/traf_department.dart create mode 100644 lib/providers/lookups/department_lookup_provider.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 9d4ef5db..d7835fa9 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -225,9 +225,13 @@ class URLs { static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; + static get getTrafRequestTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=416"; + static get getYesNoRequestTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; + static get getClassificationTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=450"; + static get getRecommendationTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=451"; static get getWoFrames => "$_baseUrl/Lookups/GetLookup?lookupEnum=1254"; @@ -253,6 +257,7 @@ class URLs { //Traf static get getTRAFById => "$_baseUrl/TRAF/GetTRAFById"; // get + static get getAssetNDAutoCompleteByDynamicCodes => "$_baseUrl/AssetNameDefinition/GetAssetNDAutoCompleteByDynamicCodes"; // get //gas refill static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get @@ -302,4 +307,5 @@ class URLs { static get addComment => "$_baseUrl/CallRequest/AddHistoryComment"; // add static get getSiteContactInfo => "$_baseUrl/AssetGroupSiteContactInfo"; // add + static get getDepartmentBasedOnSite => "$_baseUrl/TRAFDataSource/GetDepartmentBasedOnSite"; // add } diff --git a/lib/controllers/providers/api/oracle_code_provider.dart b/lib/controllers/providers/api/oracle_code_provider.dart index df0acb98..ea8b0978 100644 --- a/lib/controllers/providers/api/oracle_code_provider.dart +++ b/lib/controllers/providers/api/oracle_code_provider.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; import 'package:test_sa/models/service_request/spare_parts.dart'; class OracleCodeProvider extends ChangeNotifier { @@ -84,15 +85,15 @@ class OracleCodeProvider extends ChangeNotifier { /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getAssetByOracleCode(String oracleCode) async { + Future> getAssetByOracleCode(String oracleCode) async { late Response response; try { - response = await ApiManager.instance.post(URLs.getPartNumber, body: {"oracleCode": oracleCode}); - List page = []; + response = await ApiManager.instance.post(URLs.getAssetNDAutoCompleteByDynamicCodes, body: {"codeValue": oracleCode}); + List page = []; if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List categoriesListJson = json.decode(response.body)["data"]; - page = categoriesListJson.map((part) => SparePart.fromJson(part, false)).toList(); + page = categoriesListJson.map((part) => AssetNDAutoCompleteByDynamicCodesModel.fromJson(part)).toList(); } return page; } catch (error) { diff --git a/lib/main.dart b/lib/main.dart index 30daa9c1..f2f5a281 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -99,6 +99,7 @@ import 'controllers/providers/settings/setting_provider.dart'; import 'dashboard_latest/dashboard_provider.dart'; import 'new_views/pages/gas_refill_request_form.dart'; import 'providers/lookups/classification_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'; import 'providers/service_request_providers/loan_availability_provider.dart'; @@ -209,6 +210,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => AssetTransferStatusProvider()), ChangeNotifierProvider(create: (_) => TrafRequestProvider()), + ChangeNotifierProvider(create: (_) => DepartmentLookupProvider()), ///todo deleted //ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()), diff --git a/lib/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart b/lib/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart new file mode 100644 index 00000000..4d5ae14e --- /dev/null +++ b/lib/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart @@ -0,0 +1,27 @@ +class AssetNDAutoCompleteByDynamicCodesModel { + int? id; + String? assetName; + int? codeTypeId; + String? codeValue; + String? displayName; + + AssetNDAutoCompleteByDynamicCodesModel({this.id, this.assetName, this.codeTypeId, this.codeValue, this.displayName}); + + AssetNDAutoCompleteByDynamicCodesModel.fromJson(Map json) { + id = json['id']; + assetName = json['assetName']; + codeTypeId = json['codeTypeId']; + codeValue = json['codeValue']; + displayName = json['displayName']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['assetName'] = this.assetName; + data['codeTypeId'] = this.codeTypeId; + data['codeValue'] = this.codeValue; + data['displayName'] = this.displayName; + return data; + } +} diff --git a/lib/models/new_models/traf_department.dart b/lib/models/new_models/traf_department.dart new file mode 100644 index 00000000..5a2e256d --- /dev/null +++ b/lib/models/new_models/traf_department.dart @@ -0,0 +1,101 @@ +import 'package:test_sa/models/new_models/room_model.dart'; + +import '../base.dart'; + +class TrafDepartment extends Base { + TrafDepartment({ + this.departmentName, this.departmentCode, this.ntCode, this.costCenterNumber, this.costCenterName, this.name, this.id, this.createdBy, this.createdDate, this.modifiedBy, this.modifiedDate + }) : super(identifier: id?.toString() ?? '', name: departmentName); // Handle potential null id + + TrafDepartment.fromJson(Map json) { + departmentName = json['departmentName'] ?? json['name']; + departmentCode = json['departmentCode']; + ntCode = json['ntCode']; + costCenterNumber = json['costCenterNumber']; + costCenterName = json['costCenterName']; + name = json['name']; + id = json['id']; + createdBy = json['createdBy']; + createdDate = json['createdDate']; + modifiedBy = json['modifiedBy']; + modifiedDate = json['modifiedDate']; + } + + num? id; // Now nullable + String? departmentName; // Now nullable + String? departmentCode; // Now nullable + String? ntCode; + String? costCenterNumber; + String? costCenterName; + String? name; + String? createdBy; + String? createdDate; + String? modifiedBy; + String? modifiedDate; + + // TrafDepartment copyWith({ + // num? id, // Parameters are now nullable + // String? departmentName, + // String? departmentCode, + // String? departmentId, + // String? ntCode, + // List? rooms, + // }) => + // TrafDepartment( + // id: id ?? this.id, + // departmentName: departmentName ?? this.departmentName, + // departmentCode: departmentCode ?? this.departmentCode, + // departmentId: departmentId ?? this.departmentId, + // ntCode: ntCode ?? this.ntCode, + // rooms: rooms ?? this.rooms, + // ); + + +} + +// class TrafDepartment extends Base { +// String? departmentName; +// String? departmentCode; +// Null? ntCode; +// Null? costCenterNumber; +// Null? costCenterName; +// String? name; +// int? id; +// String? createdBy; +// String? createdDate; +// Null? modifiedBy; +// Null? modifiedDate; +// +// TrafDepartment( +// {this.departmentName, this.departmentCode, this.ntCode, this.costCenterNumber, this.costCenterName, this.name, this.id, this.createdBy, this.createdDate, this.modifiedBy, this.modifiedDate}); +// +// TrafDepartment.fromJson(Map json) { +// departmentName = json['departmentName']; +// departmentCode = json['departmentCode']; +// ntCode = json['ntCode']; +// costCenterNumber = json['costCenterNumber']; +// costCenterName = json['costCenterName']; +// name = json['name']; +// id = json['id']; +// createdBy = json['createdBy']; +// createdDate = json['createdDate']; +// modifiedBy = json['modifiedBy']; +// modifiedDate = json['modifiedDate']; +// } +// +// Map toJson() { +// final Map data = new Map(); +// data['departmentName'] = this.departmentName; +// data['departmentCode'] = this.departmentCode; +// data['ntCode'] = this.ntCode; +// data['costCenterNumber'] = this.costCenterNumber; +// data['costCenterName'] = this.costCenterName; +// data['name'] = this.name; +// data['id'] = this.id; +// data['createdBy'] = this.createdBy; +// data['createdDate'] = this.createdDate; +// data['modifiedBy'] = this.modifiedBy; +// data['modifiedDate'] = this.modifiedDate; +// return data; +// } +// } diff --git a/lib/modules/traf_module/asset_auto_complete_field.dart b/lib/modules/traf_module/asset_auto_complete_field.dart index df4a042e..0abb378b 100644 --- a/lib/modules/traf_module/asset_auto_complete_field.dart +++ b/lib/modules/traf_module/asset_auto_complete_field.dart @@ -7,6 +7,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/views/app_style/sizing.dart'; @@ -18,7 +19,7 @@ class AssetAutoCompleteField extends StatefulWidget { final String initialValue; final num? assetId; final bool clearAfterPick, byName; - final Function(SparePartsWorkOrders) onPick; + final Function(AssetNDAutoCompleteByDynamicCodesModel) onPick; const AssetAutoCompleteField({Key? key, required this.byName, required this.initialValue, this.assetId, required this.onPick, this.clearAfterPick = true}) : super(key: key); @@ -63,7 +64,7 @@ class _AssetAutoCompleteFieldState extends State { borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), - child: Autocomplete( + child: Autocomplete( optionsBuilder: (TextEditingValue textEditingValue) async { if (textEditingValue.text.isEmpty) { if (loading) { @@ -71,20 +72,20 @@ class _AssetAutoCompleteFieldState extends State { loading = false; }); } - return const Iterable.empty(); + return const Iterable.empty(); } if (!loading) { setState(() { loading = true; }); } - List workOrders = (await _oracleCodeProvider.getAssetByOracleCode(textEditingValue.text)).map((e) => SparePartsWorkOrders(sparePart: e)).toList(); + List workOrders = (await _oracleCodeProvider.getAssetByOracleCode(textEditingValue.text)); setState(() { loading = false; }); return workOrders; }, - displayStringForOption: (SparePartsWorkOrders option) => widget.byName ? option.sparePart?.partName ?? "" : option.sparePart?.partNo ?? "", + displayStringForOption: (AssetNDAutoCompleteByDynamicCodesModel option) => widget.byName ? option.displayName ?? "" : option.codeValue ?? "", fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { return TextField( controller: _controller, @@ -117,11 +118,11 @@ class _AssetAutoCompleteFieldState extends State { }, ); }, - onSelected: (SparePartsWorkOrders selection) { + onSelected: (AssetNDAutoCompleteByDynamicCodesModel selection) { if (widget.clearAfterPick) { _controller.clear(); } else { - _controller.text = widget.byName ? (selection.sparePart?.partName ?? "") : (selection.sparePart?.partNo ?? ""); + _controller.text = widget.byName ? (selection.displayName ?? "") : (selection.codeValue ?? ""); } widget.onPick(selection); }, diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart index f1b62e0e..b52287f4 100644 --- a/lib/modules/traf_module/create_traf_request_page.dart +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -7,6 +7,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/traf_department.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/traf_module/asset_auto_complete_field.dart'; import 'package:test_sa/modules/traf_module/traf_request_detail_page.dart'; @@ -18,6 +19,7 @@ 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/loading_list_notifier.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'; import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; @@ -50,6 +52,7 @@ class _CreateTRAFRequestPageState extends State { TrafRequestDataModel? trafRequest; List abc = []; + List departments = []; @override void initState() { @@ -106,9 +109,8 @@ class _CreateTRAFRequestPageState extends State { if (requestType?.value == 1) ...[ 12.height, AssetAutoCompleteField( - // assetId: widget.assetId, clearAfterPick: false, - byName: false, + byName: true, initialValue: "", onPick: (part) { // model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); @@ -218,7 +220,6 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.censusQ4 = int.tryParse(value); }, ), - 12.height, SingleItemDropDownMenu( context: context, @@ -245,21 +246,26 @@ class _CreateTRAFRequestPageState extends State { onSelect: (value) { isUsedSolelyOrShared = value; trafRequest?.usingSolelyOrSharedId = value?.value; + if (isUsedSolelyOrShared?.value != 1) { + departments = []; + Provider.of(context, listen: false).reset(); + } setState(() {}); }, ), if (isUsedSolelyOrShared?.value == 1) ...[ 12.height, - MultipleItemDropDownMenu( + MultipleItemDropDownMenu( context: context, showAsBottomSheet: true, backgroundColor: AppColor.neutral100, showShadow: false, showCancel: true, + requestById: context.userProvider.user?.clientId, title: "Please specify departments and relations", - initialValue: abc, + initialValue: departments, onSelect: (value) { - abc = value ?? []; + departments = value ?? []; // setState(() { // // }); diff --git a/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart index 723b3faf..9c579f97 100644 --- a/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart +++ b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart @@ -28,6 +28,7 @@ class MultipleItemDropDownMenu ex final bool showCancel; final Color? backgroundColor; // Now nullable final bool? loading; // Now nullable + final int? requestById; // Now nullable /// To use a static data (without calling API) /// just send [NullableLoadingProvider] as generic data type and fill the [staticData] @@ -47,6 +48,7 @@ class MultipleItemDropDownMenu ex this.showCancel = false, this.backgroundColor, this.loading, + this.requestById, }) : super(key: key); @override @@ -150,7 +152,7 @@ class _MultipleItemDropDownMenuState exte final bool showCancel; final Color? backgroundColor; // Now nullable final bool? loading; // Now nullable + final int? requestById; /// To use a static data (without calling API) /// just send [NullableLoadingProvider] as generic data type and fill the [staticData] @@ -46,6 +47,7 @@ class SingleItemDropDownMenu exte this.showCancel = false, this.backgroundColor, this.loading, + this.requestById, }) : super(key: key); @override @@ -106,7 +108,7 @@ class _SingleItemDropDownMenuState { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/department_provider.dart b/lib/providers/department_provider.dart index 96a2d814..78041d0f 100644 --- a/lib/providers/department_provider.dart +++ b/lib/providers/department_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class DepartmentProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/gas_request_providers/cylinder_size_provider.dart b/lib/providers/gas_request_providers/cylinder_size_provider.dart index 379d84d6..5e8d4409 100644 --- a/lib/providers/gas_request_providers/cylinder_size_provider.dart +++ b/lib/providers/gas_request_providers/cylinder_size_provider.dart @@ -9,7 +9,7 @@ import '../loading_list_notifier.dart'; class CylinderSizeProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/gas_request_providers/cylinder_type_provider.dart b/lib/providers/gas_request_providers/cylinder_type_provider.dart index a4d9ba98..356af1d3 100644 --- a/lib/providers/gas_request_providers/cylinder_type_provider.dart +++ b/lib/providers/gas_request_providers/cylinder_type_provider.dart @@ -9,7 +9,7 @@ import '../loading_list_notifier.dart'; class CylinderTypesProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/gas_request_providers/gas_status_provider.dart b/lib/providers/gas_request_providers/gas_status_provider.dart index f375b100..7057a503 100644 --- a/lib/providers/gas_request_providers/gas_status_provider.dart +++ b/lib/providers/gas_request_providers/gas_status_provider.dart @@ -9,7 +9,7 @@ import '../loading_list_notifier.dart'; class GasStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/gas_request_providers/gas_types_provider.dart b/lib/providers/gas_request_providers/gas_types_provider.dart index 7f539739..78d724f3 100644 --- a/lib/providers/gas_request_providers/gas_types_provider.dart +++ b/lib/providers/gas_request_providers/gas_types_provider.dart @@ -9,7 +9,7 @@ import '../../controllers/api_routes/urls.dart'; class GasTypesProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/gas_request_providers/site_provider.dart b/lib/providers/gas_request_providers/site_provider.dart index 430a50e3..d497a88d 100644 --- a/lib/providers/gas_request_providers/site_provider.dart +++ b/lib/providers/gas_request_providers/site_provider.dart @@ -10,7 +10,7 @@ import '../../controllers/api_routes/urls.dart'; class SiteProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); @@ -35,7 +35,7 @@ class SiteProvider extends LoadingListNotifier { class MappedSiteProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/loading_list_notifier.dart b/lib/providers/loading_list_notifier.dart index 2fee42b0..134f2a29 100644 --- a/lib/providers/loading_list_notifier.dart +++ b/lib/providers/loading_list_notifier.dart @@ -3,7 +3,7 @@ import 'package:test_sa/models/base.dart'; class NullableLoadingProvider extends LoadingListNotifier { @override - Future getData() { + Future getData({int? id}) { return Future.value(); } } @@ -28,5 +28,5 @@ abstract class LoadingListNotifier extends ChangeNotifier { stateCode = null; } - Future getData(); + Future getData({int? id}); } diff --git a/lib/providers/lookups/classification_lookup_provider.dart b/lib/providers/lookups/classification_lookup_provider.dart index 87b57efb..9e56dfa3 100644 --- a/lib/providers/lookups/classification_lookup_provider.dart +++ b/lib/providers/lookups/classification_lookup_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class ClassificationLookupProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/lookups/department_lookup_provider.dart b/lib/providers/lookups/department_lookup_provider.dart new file mode 100644 index 00000000..fcd0fe8e --- /dev/null +++ b/lib/providers/lookups/department_lookup_provider.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/new_models/traf_department.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class DepartmentLookupProvider extends LoadingListNotifier { + @override + Future getData({int? id}) async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getDepartmentBasedOnSite + "?customerId=$id"); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => TrafDepartment.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/lookups/recommendation_lookup_provider.dart b/lib/providers/lookups/recommendation_lookup_provider.dart index a0bbe48a..e096656f 100644 --- a/lib/providers/lookups/recommendation_lookup_provider.dart +++ b/lib/providers/lookups/recommendation_lookup_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class RecommendationLookupProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/lookups/request_type_lookup_provider.dart b/lib/providers/lookups/request_type_lookup_provider.dart index cc94de62..ba709ccc 100644 --- a/lib/providers/lookups/request_type_lookup_provider.dart +++ b/lib/providers/lookups/request_type_lookup_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class RequestTypeLookupProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/lookups/yes_no_lookup_provider.dart b/lib/providers/lookups/yes_no_lookup_provider.dart index a089069b..e3b87d66 100644 --- a/lib/providers/lookups/yes_no_lookup_provider.dart +++ b/lib/providers/lookups/yes_no_lookup_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class YesNoLookupProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_asset_availability_provider.dart b/lib/providers/ppm_asset_availability_provider.dart index 456ad99e..219647c6 100644 --- a/lib/providers/ppm_asset_availability_provider.dart +++ b/lib/providers/ppm_asset_availability_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PpmAssetAvailabilityProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_checklist_status_provider.dart b/lib/providers/ppm_checklist_status_provider.dart index d6b62a80..2744482e 100644 --- a/lib/providers/ppm_checklist_status_provider.dart +++ b/lib/providers/ppm_checklist_status_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PpmChecklistStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_device_status_provider.dart b/lib/providers/ppm_device_status_provider.dart index 378ddcf1..ea49ade0 100644 --- a/lib/providers/ppm_device_status_provider.dart +++ b/lib/providers/ppm_device_status_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PPMDeviceStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_electrical_safety_provider.dart b/lib/providers/ppm_electrical_safety_provider.dart index a681b927..c67dfbf5 100644 --- a/lib/providers/ppm_electrical_safety_provider.dart +++ b/lib/providers/ppm_electrical_safety_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PpmElectricalSafetyProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_service_provider.dart b/lib/providers/ppm_service_provider.dart index 0238c803..2e0a2d41 100644 --- a/lib/providers/ppm_service_provider.dart +++ b/lib/providers/ppm_service_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PpmServiceProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_task_status_provider.dart b/lib/providers/ppm_task_status_provider.dart index ed7a7943..2b1e86a8 100644 --- a/lib/providers/ppm_task_status_provider.dart +++ b/lib/providers/ppm_task_status_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PpmTaskStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/ppm_visit_status_provider.dart b/lib/providers/ppm_visit_status_provider.dart index 19625daa..dc72c873 100644 --- a/lib/providers/ppm_visit_status_provider.dart +++ b/lib/providers/ppm_visit_status_provider.dart @@ -9,7 +9,7 @@ import 'loading_list_notifier.dart'; class PPMVisitStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading ?? false) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/commissioning_status_provider.dart b/lib/providers/service_request_providers/commissioning_status_provider.dart index 60e07ff9..bba116b8 100644 --- a/lib/providers/service_request_providers/commissioning_status_provider.dart +++ b/lib/providers/service_request_providers/commissioning_status_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class CommissioningStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/equipment_status_provider.dart b/lib/providers/service_request_providers/equipment_status_provider.dart index 7280aa58..5f2f9fad 100644 --- a/lib/providers/service_request_providers/equipment_status_provider.dart +++ b/lib/providers/service_request_providers/equipment_status_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class EquipmentStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/first_action_provider.dart b/lib/providers/service_request_providers/first_action_provider.dart index 32123215..4908e3b2 100644 --- a/lib/providers/service_request_providers/first_action_provider.dart +++ b/lib/providers/service_request_providers/first_action_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class FirstActionStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/last_situation_provider.dart b/lib/providers/service_request_providers/last_situation_provider.dart index f61a9d4f..56794e0f 100644 --- a/lib/providers/service_request_providers/last_situation_provider.dart +++ b/lib/providers/service_request_providers/last_situation_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class LastSituationProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/loan_availability_provider.dart b/lib/providers/service_request_providers/loan_availability_provider.dart index 8118f46e..8d6d7f5d 100644 --- a/lib/providers/service_request_providers/loan_availability_provider.dart +++ b/lib/providers/service_request_providers/loan_availability_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class LoanAvailabilityProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; diff --git a/lib/providers/service_request_providers/priority_provider.dart b/lib/providers/service_request_providers/priority_provider.dart index 4850d1e9..87af53a2 100644 --- a/lib/providers/service_request_providers/priority_provider.dart +++ b/lib/providers/service_request_providers/priority_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class PriorityProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/reject_reason_provider.dart b/lib/providers/service_request_providers/reject_reason_provider.dart index e7311c58..f8c6d880 100644 --- a/lib/providers/service_request_providers/reject_reason_provider.dart +++ b/lib/providers/service_request_providers/reject_reason_provider.dart @@ -10,7 +10,7 @@ import '../../models/lookup.dart'; class RejectReasonProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/requested_through_provider.dart b/lib/providers/service_request_providers/requested_through_provider.dart index 72e481ff..de0ef414 100644 --- a/lib/providers/service_request_providers/requested_through_provider.dart +++ b/lib/providers/service_request_providers/requested_through_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class RequestedThroughProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/service_request_providers/type_of_request_provider.dart b/lib/providers/service_request_providers/type_of_request_provider.dart index ef9f306f..ba651ff9 100644 --- a/lib/providers/service_request_providers/type_of_request_provider.dart +++ b/lib/providers/service_request_providers/type_of_request_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class TypeOfRequestProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; diff --git a/lib/providers/task_request_provider/task_job_provider.dart b/lib/providers/task_request_provider/task_job_provider.dart index b66e10cf..8b9b74fc 100644 --- a/lib/providers/task_request_provider/task_job_provider.dart +++ b/lib/providers/task_request_provider/task_job_provider.dart @@ -11,7 +11,7 @@ import '../../controllers/api_routes/urls.dart'; class TaskTypeProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { print('get data called...'); if (loading == true) return -2; loading = true; @@ -39,7 +39,7 @@ class TaskTypeProvider extends LoadingListNotifier { } class TaskEvaluatorUserProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); @@ -65,7 +65,7 @@ class TaskEvaluatorUserProvider extends LoadingListNotifier { class TaskJobTypeOfAlertProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); @@ -90,7 +90,7 @@ class TaskJobTypeOfAlertProvider extends LoadingListNotifier { } class TaskJobRiskLevelProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); @@ -115,7 +115,7 @@ class TaskJobRiskLevelProvider extends LoadingListNotifier { } class TaskJobResourceProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); @@ -140,7 +140,7 @@ class TaskJobResourceProvider extends LoadingListNotifier { } class TaskJobActionNeededProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); @@ -165,7 +165,7 @@ class TaskJobActionNeededProvider extends LoadingListNotifier { } class TaskJobImpactStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/activity_status_provider.dart b/lib/providers/work_order/activity_status_provider.dart index 21e0afa9..afa606e4 100644 --- a/lib/providers/work_order/activity_status_provider.dart +++ b/lib/providers/work_order/activity_status_provider.dart @@ -10,7 +10,7 @@ import '../../models/lookup.dart'; class ActivityStatusProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/need_visit_reminder_time_provider.dart b/lib/providers/work_order/need_visit_reminder_time_provider.dart index 2f82d41f..1247ee18 100644 --- a/lib/providers/work_order/need_visit_reminder_time_provider.dart +++ b/lib/providers/work_order/need_visit_reminder_time_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class NeedVisitReminderTimeProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/reason_provider.dart b/lib/providers/work_order/reason_provider.dart index d077fef2..a5ea7e6e 100644 --- a/lib/providers/work_order/reason_provider.dart +++ b/lib/providers/work_order/reason_provider.dart @@ -11,7 +11,7 @@ class ReasonProvider extends LoadingListNotifier { String? serviceRequestId; @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/retirement_type_provider.dart b/lib/providers/work_order/retirement_type_provider.dart index 436e9cc7..038f13a7 100644 --- a/lib/providers/work_order/retirement_type_provider.dart +++ b/lib/providers/work_order/retirement_type_provider.dart @@ -12,7 +12,7 @@ class RetirementTypeProvider extends LoadingListNotifier { String? serviceRequestId; @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; print('get data called...'); loading = true; diff --git a/lib/providers/work_order/service_type_provider.dart b/lib/providers/work_order/service_type_provider.dart index 0313f09e..1df3616c 100644 --- a/lib/providers/work_order/service_type_provider.dart +++ b/lib/providers/work_order/service_type_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class ServiceTypeProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/supplier_engineer_provider.dart b/lib/providers/work_order/supplier_engineer_provider.dart index e1bbf62e..490b990e 100644 --- a/lib/providers/work_order/supplier_engineer_provider.dart +++ b/lib/providers/work_order/supplier_engineer_provider.dart @@ -8,7 +8,7 @@ import 'package:test_sa/providers/loading_list_notifier.dart'; class SupplierEngineerProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/vendor_provider.dart b/lib/providers/work_order/vendor_provider.dart index 071189bf..52a2a77c 100644 --- a/lib/providers/work_order/vendor_provider.dart +++ b/lib/providers/work_order/vendor_provider.dart @@ -8,7 +8,7 @@ import 'package:test_sa/providers/loading_list_notifier.dart'; class VendorProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/providers/work_order/wo_frame_provider.dart b/lib/providers/work_order/wo_frame_provider.dart index 0c92841a..cacebf4c 100644 --- a/lib/providers/work_order/wo_frame_provider.dart +++ b/lib/providers/work_order/wo_frame_provider.dart @@ -9,7 +9,7 @@ import '../../models/lookup.dart'; class WoFrameProvider extends LoadingListNotifier { @override - Future getData() async { + Future getData({int? id}) async { if (loading == true) return -2; loading = true; notifyListeners(); diff --git a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart index 806b9de3..a4d4628b 100644 --- a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart +++ b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart @@ -50,9 +50,6 @@ class _SelectionBottomSheetState extends State Date: Thu, 16 Oct 2025 09:02:31 +0300 Subject: [PATCH 3/9] add traf payload added. --- lib/controllers/api_routes/urls.dart | 1 + .../traf_module/create_traf_request_page.dart | 61 ++++++++++++------- .../traf_module/traf_request_model.dart | 2 + .../traf_module/traf_request_provider.dart | 18 ++++++ .../traf_module/update_traf_request_page.dart | 29 +++++++-- .../multiple_item_drop_down_menu.dart | 5 +- 6 files changed, 87 insertions(+), 29 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index d7835fa9..6627c7c3 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -256,6 +256,7 @@ class URLs { static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName="; //Traf + static get addTRAF => "$_baseUrl/TRAF/AddTRAF"; // get static get getTRAFById => "$_baseUrl/TRAF/GetTRAFById"; // get static get getAssetNDAutoCompleteByDynamicCodes => "$_baseUrl/AssetNameDefinition/GetAssetNDAutoCompleteByDynamicCodes"; // get diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart index b52287f4..012e7ab7 100644 --- a/lib/modules/traf_module/create_traf_request_page.dart +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -5,6 +5,7 @@ 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/helper/utils.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/traf_department.dart'; @@ -25,6 +26,7 @@ import 'package:test_sa/providers/lookups/yes_no_lookup_provider.dart'; import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; import 'traf_request_model.dart'; +import 'traf_request_provider.dart'; class CreateTRAFRequestPage extends StatefulWidget { static const String id = "/create-TRAF"; @@ -57,13 +59,13 @@ class _CreateTRAFRequestPageState extends State { @override void initState() { super.initState(); - trafRequest = TrafRequestDataModel(); + trafRequest = TrafRequestDataModel(id: 0); resetProviders(); } void resetProviders() { Provider.of(context, listen: false).reset(); - // Provider.of(context, listen: false).reset(); + Provider.of(context, listen: false).reset(); } @override @@ -102,7 +104,13 @@ class _CreateTRAFRequestPageState extends State { initialValue: requestType, onSelect: (value) { requestType = value; - trafRequest?.requestTypeId = value?.value; + trafRequest?.requestTypeId = value?.id; + if (requestType?.value == 1) { + trafRequest?.assetId = null; + trafRequest?.qty = null; + } else if (requestType?.value == 2) { + trafRequest?.assetNDId = null; + } setState(() {}); }, ), @@ -112,7 +120,8 @@ class _CreateTRAFRequestPageState extends State { clearAfterPick: false, byName: true, initialValue: "", - onPick: (part) { + onPick: (asset) { + trafRequest?.assetNDId = asset.id; // model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); // setState(() {}); }, @@ -128,6 +137,8 @@ class _CreateTRAFRequestPageState extends State { backgroundColor: AppColor.white936, onPick: (asset) async { this.asset = asset; + trafRequest?.assetId = asset.id?.toInt(); + trafRequest?.qty = 1; setState(() {}); // pendingAssetServiceRequest = null; // _serviceRequest.device = asset; @@ -248,6 +259,7 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.usingSolelyOrSharedId = value?.value; if (isUsedSolelyOrShared?.value != 1) { departments = []; + trafRequest?.departments = []; Provider.of(context, listen: false).reset(); } setState(() {}); @@ -266,9 +278,14 @@ class _CreateTRAFRequestPageState extends State { initialValue: departments, onSelect: (value) { departments = value ?? []; - // setState(() { - // - // }); + trafRequest?.departments = departments + .map((element) => Departments( + id: element.id!.toInt(), + trafId: element.id!.toInt(), + departmentId: element.id!.toInt(), + )) + .toList(); + // setState(() {}); }, ), ], @@ -284,6 +301,10 @@ class _CreateTRAFRequestPageState extends State { onSelect: (value) { otherServicesEffects = value; trafRequest?.isEffectedId = value?.value; + if (otherServicesEffects?.value != 1) { + trafRequest?.effectedServices = null; + } + setState(() {}); }, ), @@ -315,6 +336,9 @@ class _CreateTRAFRequestPageState extends State { onSelect: (value) { useInCombination = value; trafRequest?.isCombinationId = value?.value; + if (useInCombination?.value != 1) { + trafRequest?.usedWithCombination = null; + } setState(() {}); }, ), @@ -333,19 +357,6 @@ class _CreateTRAFRequestPageState extends State { }, ), ] - // 23.height, - // AttachmentPicker( - // label: context.translation.attachImage, - // attachment: attachments, - // buttonColor: AppColor.black10, - // onlyImages: false, - // buttonIcon: 'image-plus'.toSvgAsset(color: context.isDark ? AppColor.primary10 : AppColor.neutral120), - // //verify this if not required delete this .. - // onChange: (attachments) { - // attachments = attachments; - // setState(() {}); - // }, - // ), ], ).toShadowContainer(context, padding: 12, borderRadius: 20), 16.height, @@ -371,7 +382,8 @@ class _CreateTRAFRequestPageState extends State { child: AppFilledButton( buttonColor: AppColor.primary10, label: context.translation.submitRequest, - onPressed: _acknowledgement ? _submit : null, + disableButton: !_acknowledgement, + onPressed: _verifyAndSubmit, // buttonColor: AppColor.primary10, ), ), @@ -381,7 +393,12 @@ class _CreateTRAFRequestPageState extends State { ); } - void _submit() { + void _verifyAndSubmit() async { + trafRequest?.employeeId = context.userProvider.user?.userID; + trafRequest?.siteId = context.userProvider.user?.clientId; + // Utils.showLoading(context); + // await Provider.of(context, listen: false).addTraf(trafRequest!.toJson()); + // Utils.hideLoading(context); Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: 27))); } } diff --git a/lib/modules/traf_module/traf_request_model.dart b/lib/modules/traf_module/traf_request_model.dart index 5705b6d0..c8a35cb4 100644 --- a/lib/modules/traf_module/traf_request_model.dart +++ b/lib/modules/traf_module/traf_request_model.dart @@ -393,6 +393,8 @@ class TrafRequestDataModel { data['comment'] = this.comment; if (this.attachments != null) { data['attachments'] = this.attachments!.map((v) => v.toJson()).toList(); + } else { + data['attachments'] = []; } data['isBudgetId'] = this.isBudgetId; data['isBudgetName'] = this.isBudgetName; diff --git a/lib/modules/traf_module/traf_request_provider.dart b/lib/modules/traf_module/traf_request_provider.dart index 85459f5c..1f1dd385 100644 --- a/lib/modules/traf_module/traf_request_provider.dart +++ b/lib/modules/traf_module/traf_request_provider.dart @@ -12,6 +12,24 @@ class TrafRequestProvider extends ChangeNotifier { TrafRequestDataModel? trafRequestDataModel; + Future addTraf(Map body) async { + try { + isLoading = true; + notifyListeners(); + Response response = await ApiManager.instance.post(URLs.addTRAF, body: body); + if (response.statusCode >= 200 && response.statusCode < 300) { + // trafRequestDataModel = TrafRequestDataModel.fromJson(json.decode(response.body)["data"]); + } + isLoading = false; + notifyListeners(); + return 0; + } catch (error) { + isLoading = false; + notifyListeners(); + return -1; + } + } + Future getTRAFById(int trafId) async { try { isLoading = true; diff --git a/lib/modules/traf_module/update_traf_request_page.dart b/lib/modules/traf_module/update_traf_request_page.dart index 4fcea820..77fab5a1 100644 --- a/lib/modules/traf_module/update_traf_request_page.dart +++ b/lib/modules/traf_module/update_traf_request_page.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; @@ -6,6 +9,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/generic_attachment_model.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/traf_module/traf_request_model.dart'; import 'package:test_sa/modules/traf_module/traf_request_provider.dart'; @@ -54,6 +58,7 @@ class _UpdateTrafRequestPageState extends State { Provider.of(context, listen: false).reset(); trafRequestProvider = Provider.of(context, listen: false); trafRequest = trafRequestProvider.trafRequestDataModel!; + attachments = trafRequest.attachments?.map((item) => GenericAttachmentModel(id: item.id, name: item.attachmentName)).toList() ?? []; } @override @@ -82,8 +87,8 @@ class _UpdateTrafRequestPageState extends State { initialValue: classificationType, onSelect: (value) { classificationType = value; - // trafRequest?.requestTypeId = value?.value; - setState(() {}); + trafRequest?.cla = value?.value; + // setState(() {}); }, ), 12.height, @@ -184,8 +189,9 @@ class _UpdateTrafRequestPageState extends State { initialValue: assessorRecommendation, onSelect: (value) { assessorRecommendation = value; + trafRequest?.requestTypeId = value?.value; // trafRequest?.requestTypeId = value?.value; - setState(() {}); + // setState(() {}); }, ), 12.height, @@ -208,13 +214,28 @@ class _UpdateTrafRequestPageState extends State { buttonColor: AppColor.black10, onlyImages: false, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + onChange: (attachment) { + attachments = attachment; + }, ), ], ).toShadowContainer(context, borderRadius: 20, padding: 12), ).expanded, FooterActionButton.footerContainer( context: context, - child: AppFilledButton(buttonColor: AppColor.primary10, label: "Update", onPressed: () {} + child: AppFilledButton( + buttonColor: AppColor.primary10, + label: "Update", + onPressed: () { + trafRequest.attachments = []; + for (var item in attachments) { + String fileName = + ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? ''; + trafRequest.attachments!.add( + Attachments(id: item.id, trafId: item.id, attachmentName: fileName), + ); + } + } // buttonColor: AppColor.primary10, ), ), diff --git a/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart index 9c579f97..d0df92fa 100644 --- a/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart +++ b/lib/new_views/common_widgets/multiple_item_drop_down_menu.dart @@ -71,7 +71,7 @@ class _MultipleItemDropDownMenuState widget.initialValue!.any((init) => init.identifier == element.identifier)).toList(); + final results = sourceList.where((element) => widget.initialValue!.any((init) => init.name == element.name)).toList(); if (results.isNotEmpty) { _selectedItem @@ -106,11 +106,10 @@ class _MultipleItemDropDownMenuState widget.initialValue!.any((init) => init.identifier == element.identifier)).toList(); + final results = sourceList.where((element) => widget.initialValue!.any((init) => init.name == element.name)).toList(); if (results.isNotEmpty) { _selectedItem ..clear() From 144951caecb1770d2eeed3c4777967b2a153cf5e Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 16 Oct 2025 17:01:05 +0300 Subject: [PATCH 4/9] traf request creation completed. --- lib/controllers/api_routes/urls.dart | 3 +- .../providers/api/all_requests_provider.dart | 25 +++- .../providers/api/search_user_provider.dart | 64 +++++++++ lib/main.dart | 2 + .../users_based_on_search_model.dart | 44 ++++++ .../traf_module/create_traf_request_page.dart | 120 ++++++++++------ .../traf_module/traf_request_detail_page.dart | 21 ++- .../traf_module/traf_request_model.dart | 16 ++- .../traf_module/update_traf_request_page.dart | 2 +- .../users_auto_complete_field.dart | 134 ++++++++++++++++++ .../create_request-type_bottomsheet.dart | 2 +- .../my_request/all_requests_filter_page.dart | 4 + .../my_request/my_requests_page.dart | 3 + 13 files changed, 384 insertions(+), 56 deletions(-) create mode 100644 lib/controllers/providers/api/search_user_provider.dart create mode 100644 lib/models/new_models/users_based_on_search_model.dart create mode 100644 lib/modules/traf_module/users_auto_complete_field.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 6627c7c3..7fc41288 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -258,7 +258,7 @@ class URLs { //Traf static get addTRAF => "$_baseUrl/TRAF/AddTRAF"; // get static get getTRAFById => "$_baseUrl/TRAF/GetTRAFById"; // get - static get getAssetNDAutoCompleteByDynamicCodes => "$_baseUrl/AssetNameDefinition/GetAssetNDAutoCompleteByDynamicCodes"; // get + static get getAssetNDAutoCompleteByDynamicCodes => "$_baseUrl/AssetNameDefinition/GetAssetNDAutoCompleteByDynamicCodes"; // get// get //gas refill static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get @@ -294,6 +294,7 @@ class URLs { static get getTaskEvaluatorUser => "$_baseUrl/Account/GetUserByRoleValue?value=R-2"; // get static get getNurses => "$_baseUrl/Account/GetUserByRoleValue?value=R-7"; // get static get getNursesBySiteId => "$_baseUrl/Account/GetUserByRoleValueSiteAndAssetGroupBySiteId?value=R-7"; // get + static get getUsersBasedOnSearch => "$_baseUrl/Account/GetUsersBasedOnSearch"; // get // pentry static get getPentry => "$_baseUrl/return/pentry/details"; // get diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 54fd7776..722dafbc 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart'; import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; @@ -130,6 +131,28 @@ class AllRequestsProvider extends ChangeNotifier { SearchAllRequestsModel? searchedModel; + List getStatues(BuildContext context) { + List list = [1, 2, 3, 4]; + + if (context.userProvider.user!.type != UsersTypes.normal_user) { + list.add(5); + } + list.add(6); // task module + + if (context.settingProvider.isUserFlowMedical && context.userProvider.user!.type != UsersTypes.normal_user) { + list.add(7); // task mod + } + if (context.userProvider.user!.type != UsersTypes.normal_user) { + list.add(8); // + } + + if (context.userProvider.user!.type == UsersTypes.normal_user) { + list.add(9); // + } + + return list; + } + Future getAllRequests(BuildContext context, {int? typeTransaction, SearchAllRequestsModel? search}) async { if (isAllLoading == true) return -2; isAllLoading = true; @@ -143,7 +166,7 @@ class AllRequestsProvider extends ChangeNotifier { } final type = typeTransaction == null ? search?.typeTransaction == null || (search?.typeTransaction?.isEmpty ?? false) - ? [1, 2, 3, 4, 5, 6,7] + ? [1, 2, 3, 4, 5, 6, 7] : search!.typeTransaction : [typeTransaction]; List status = (search?.statuses == null || (search?.statuses?.isEmpty ?? false)) ? (((search?.isArchived ?? false) ? [3] : [1, 2, 4])) : search!.statuses!; diff --git a/lib/controllers/providers/api/search_user_provider.dart b/lib/controllers/providers/api/search_user_provider.dart new file mode 100644 index 00000000..2804e8a6 --- /dev/null +++ b/lib/controllers/providers/api/search_user_provider.dart @@ -0,0 +1,64 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; +import 'package:test_sa/models/new_models/users_based_on_search_model.dart'; +import 'package:test_sa/models/service_request/spare_parts.dart'; + +class UserSearchProvider extends ChangeNotifier { + // number of items call in each request + final pageItemNumber = 20; + + //reset provider data + void reset() { + _parts = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int? _stateCode; + + int? get stateCode => _stateCode; + + // true if there is next pagein product list and false if not + bool _nextPage = true; + + bool get nextPage => _nextPage; + + // contain user data + // when user not login or register _user = null + List? _parts; + + List? get parts => _parts; + + bool _loading = false; + + bool get isLoading => _loading; + + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + Future> getUsersBasedOnSearch(String query) async { + late Response response; + try { + response = await ApiManager.instance.get(URLs.getUsersBasedOnSearch + "?searchText=$query"); + List page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body); + page = categoriesListJson.map((part) => UsersBasedOnSearchModel.fromJson(part)).toList(); + } + return page; + } catch (error) { + return []; + } + } +} diff --git a/lib/main.dart b/lib/main.dart index f2f5a281..70880a3b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,6 +19,7 @@ import 'package:test_sa/controllers/providers/api/notifications_provider.dart'; import 'package:test_sa/controllers/providers/api/oracle_code_provider.dart'; import 'package:test_sa/controllers/providers/api/parts_provider.dart'; import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; +import 'package:test_sa/controllers/providers/api/search_user_provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart'; @@ -211,6 +212,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => TrafRequestProvider()), ChangeNotifierProvider(create: (_) => DepartmentLookupProvider()), + ChangeNotifierProvider(create: (_) => UserSearchProvider()), ///todo deleted //ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()), diff --git a/lib/models/new_models/users_based_on_search_model.dart b/lib/models/new_models/users_based_on_search_model.dart new file mode 100644 index 00000000..54480f91 --- /dev/null +++ b/lib/models/new_models/users_based_on_search_model.dart @@ -0,0 +1,44 @@ +class UsersBasedOnSearchModel { + String? userId; + String? userName; + String? email; + String? employeeId; + int? languageId; + String? extensionNo; + String? phoneNumber; + bool? isActive; + + UsersBasedOnSearchModel( + {this.userId, + this.userName, + this.email, + this.employeeId, + this.languageId, + this.extensionNo, + this.phoneNumber, + this.isActive}); + + UsersBasedOnSearchModel.fromJson(Map json) { + userId = json['userId']; + userName = json['userName']; + email = json['email']; + employeeId = json['employeeId']; + languageId = json['languageId']; + extensionNo = json['extensionNo']; + phoneNumber = json['phoneNumber']; + isActive = json['isActive']; + } + + Map toJson() { + final Map data = new Map(); + data['userId'] = this.userId; + data['userName'] = this.userName; + data['email'] = this.email; + data['employeeId'] = this.employeeId; + data['languageId'] = this.languageId; + data['extensionNo'] = this.extensionNo; + data['phoneNumber'] = this.phoneNumber; + data['isActive'] = this.isActive; + return data; + } +} diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart index 012e7ab7..8cac2b05 100644 --- a/lib/modules/traf_module/create_traf_request_page.dart +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -9,10 +9,12 @@ import 'package:test_sa/helper/utils.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.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/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/traf_module/asset_auto_complete_field.dart'; import 'package:test_sa/modules/traf_module/traf_request_detail_page.dart'; import 'package:test_sa/modules/traf_module/update_traf_request_page.dart'; +import 'package:test_sa/modules/traf_module/users_auto_complete_field.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'; @@ -43,7 +45,6 @@ class _CreateTRAFRequestPageState extends State { final GlobalKey _formKey = GlobalKey(); bool _acknowledgement = false; - Asset? asset; Lookup? requestType; @@ -54,18 +55,24 @@ class _CreateTRAFRequestPageState extends State { TrafRequestDataModel? trafRequest; List abc = []; + List departments = []; + List userBasedOnSearch = []; + + FocusNode otherServicesEffectsNode = FocusNode(); + FocusNode useInCombinationNode = FocusNode(); + FocusNode departmentNode = FocusNode(); @override void initState() { super.initState(); - trafRequest = TrafRequestDataModel(id: 0); + trafRequest = TrafRequestDataModel(id: 0, attachments: [], departments: [], qty: 1); resetProviders(); } void resetProviders() { Provider.of(context, listen: false).reset(); - Provider.of(context, listen: false).reset(); + // Provider.of(context, listen: false).reset(); } @override @@ -107,7 +114,7 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.requestTypeId = value?.id; if (requestType?.value == 1) { trafRequest?.assetId = null; - trafRequest?.qty = null; + // trafRequest?.qty = 0; } else if (requestType?.value == 2) { trafRequest?.assetNDId = null; } @@ -138,7 +145,7 @@ class _CreateTRAFRequestPageState extends State { onPick: (asset) async { this.asset = asset; trafRequest?.assetId = asset.id?.toInt(); - trafRequest?.qty = 1; + // trafRequest?.qty = 1; setState(() {}); // pendingAssetServiceRequest = null; // _serviceRequest.device = asset; @@ -232,19 +239,42 @@ class _CreateTRAFRequestPageState extends State { }, ), 12.height, - SingleItemDropDownMenu( - context: context, - showAsBottomSheet: true, - backgroundColor: AppColor.neutral100, - showShadow: false, - height: 80, - title: "List down names & contact information of users going to use the technology & specify if they are part-time or full time?", - initialValue: isUsedSolelyOrShared, - onSelect: (value) { - // isUsedSolelyOrShared = value; + SearchUserAutoCompleteField( + clearAfterPick: true, + byName: true, + initialValue: "", + onPick: (user) { + userBasedOnSearch.add(user); + FocusScope.of(context).unfocus(); + // model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); setState(() {}); }, ), + if (userBasedOnSearch.isNotEmpty) ...[ + // 12.height, + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(left: 12, right: 12), + itemBuilder: (cxt, index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + dense: true, + contentPadding: EdgeInsets.zero, + title: Text("Name: ${userBasedOnSearch[index].userName ?? ""}"), + subtitle: Text("Email: ${userBasedOnSearch[index].email ?? ""}\nPhone: ${userBasedOnSearch[index].phoneNumber ?? ""}"), + trailing: const Icon(Icons.delete_rounded, color: Color(0xffF63939), size: 20).onPress(() { + userBasedOnSearch.removeAt(index); + setState(() {}); + }), + ), + ], + ), + separatorBuilder: (cxt, index) => Divider(thickness: 1, height: 1, color: context.isDark ? AppColor.neutral20 : AppColor.neutral30), + itemCount: userBasedOnSearch.length) + ], 12.height, SingleItemDropDownMenu( context: context, @@ -259,34 +289,33 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.usingSolelyOrSharedId = value?.value; if (isUsedSolelyOrShared?.value != 1) { departments = []; - trafRequest?.departments = []; + trafRequest?.trafDepartments = []; Provider.of(context, listen: false).reset(); + FocusScope.of(context).unfocus(); + } else { + departmentNode.requestFocus(); } setState(() {}); }, ), if (isUsedSolelyOrShared?.value == 1) ...[ 12.height, - MultipleItemDropDownMenu( - context: context, - showAsBottomSheet: true, - backgroundColor: AppColor.neutral100, - showShadow: false, - showCancel: true, - requestById: context.userProvider.user?.clientId, - title: "Please specify departments and relations", - initialValue: departments, - onSelect: (value) { - departments = value ?? []; - trafRequest?.departments = departments - .map((element) => Departments( - id: element.id!.toInt(), - trafId: element.id!.toInt(), - departmentId: element.id!.toInt(), - )) - .toList(); - // setState(() {}); - }, + Focus( + focusNode: departmentNode, + child: MultipleItemDropDownMenu( + context: context, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + showCancel: true, + requestById: context.userProvider.user?.clientId, + title: "Please specify departments and relations", + initialValue: departments, + onSelect: (value) { + departments = value ?? []; + trafRequest?.trafDepartments = departments.map((element) => Departments(id: 0, trafId: 0, departmentId: element.id!.toInt())).toList(); + }, + ), ), ], 12.height, @@ -303,8 +332,10 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.isEffectedId = value?.value; if (otherServicesEffects?.value != 1) { trafRequest?.effectedServices = null; + FocusScope.of(context).unfocus(); + } else { + otherServicesEffectsNode.requestFocus(); } - setState(() {}); }, ), @@ -315,6 +346,7 @@ class _CreateTRAFRequestPageState extends State { // makeMultiLinesNull: true, textInputType: TextInputType.multiline, alignLabelWithHint: true, + node: otherServicesEffectsNode, labelText: "List down these services and stat how would it be effected", backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), @@ -338,6 +370,9 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.isCombinationId = value?.value; if (useInCombination?.value != 1) { trafRequest?.usedWithCombination = null; + FocusScope.of(context).unfocus(); + } else { + useInCombinationNode.requestFocus(); } setState(() {}); }, @@ -348,6 +383,7 @@ class _CreateTRAFRequestPageState extends State { initialValue: "", textInputType: TextInputType.multiline, alignLabelWithHint: true, + node: useInCombinationNode, labelText: "kindly describe in detail", backgroundColor: AppColor.fieldBgColor(context), labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)), @@ -396,9 +432,13 @@ class _CreateTRAFRequestPageState extends State { void _verifyAndSubmit() async { trafRequest?.employeeId = context.userProvider.user?.userID; trafRequest?.siteId = context.userProvider.user?.clientId; - // Utils.showLoading(context); - // await Provider.of(context, listen: false).addTraf(trafRequest!.toJson()); - // Utils.hideLoading(context); + trafRequest?.trafContacts = []; + trafRequest?.trafContacts = userBasedOnSearch.map((item) => TrafContacts(id: 0, trafId: 0, name: item.userName)).toList(); + + Utils.showLoading(context); + await Provider.of(context, listen: false).addTraf(trafRequest!.toJson()); + Utils.hideLoading(context); + Navigator.pop(context); Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: 27))); } } diff --git a/lib/modules/traf_module/traf_request_detail_page.dart b/lib/modules/traf_module/traf_request_detail_page.dart index 4b763736..5682b444 100644 --- a/lib/modules/traf_module/traf_request_detail_page.dart +++ b/lib/modules/traf_module/traf_request_detail_page.dart @@ -51,7 +51,6 @@ class _TrafRequestDetailPageState extends State { builder: (_, isLoading, __) { if (isLoading) return const ALoading(); TrafRequestProvider trafProvider = Provider.of(context, listen: false); - return Column( children: [ ListView( @@ -66,16 +65,16 @@ class _TrafRequestDetailPageState extends State { ] ], ).expanded, - // if (isEngineer) - FooterActionButton.footerContainer( - context: context, - child: AppFilledButton( - buttonColor: AppColor.primary10, - label: "Update", - onPressed: () { - Navigator.pushNamed(context, UpdateTrafRequestPage.id); - }), - ), + // // if (isEngineer) + // FooterActionButton.footerContainer( + // context: context, + // child: AppFilledButton( + // buttonColor: AppColor.primary10, + // label: "Update", + // onPressed: () { + // Navigator.pushNamed(context, UpdateTrafRequestPage.id); + // }), + // ), ], ); }, diff --git a/lib/modules/traf_module/traf_request_model.dart b/lib/modules/traf_module/traf_request_model.dart index c8a35cb4..0d1eedf1 100644 --- a/lib/modules/traf_module/traf_request_model.dart +++ b/lib/modules/traf_module/traf_request_model.dart @@ -51,6 +51,7 @@ class TrafRequestDataModel { int? positionId; String? positionName; List? departments; + List? trafDepartments; int? siteId; String? siteName; String? requesterExtensionNumber; @@ -144,6 +145,7 @@ class TrafRequestDataModel { this.positionId, this.positionName, this.departments, + this.trafDepartments, this.siteId, this.siteName, this.requesterExtensionNumber, @@ -242,6 +244,12 @@ class TrafRequestDataModel { departments!.add(new Departments.fromJson(v)); }); } + if (json['trafDepartments'] != null) { + trafDepartments = []; + json['trafDepartments'].forEach((v) { + trafDepartments!.add(new Departments.fromJson(v)); + }); + } siteId = json['siteId']; siteName = json['siteName']; requesterExtensionNumber = json['requesterExtensionNumber']; @@ -354,6 +362,9 @@ class TrafRequestDataModel { if (this.departments != null) { data['departments'] = this.departments!.map((v) => v.toJson()).toList(); } + if (this.trafDepartments != null) { + data['trafDepartments'] = this.trafDepartments!.map((v) => v.toJson()).toList(); + } data['siteId'] = this.siteId; data['siteName'] = this.siteName; data['requesterExtensionNumber'] = this.requesterExtensionNumber; @@ -452,15 +463,17 @@ class TrafRequestDataModel { class TrafContacts { int? id; int? trafId; + String? userId; String? name; String? telephone; String? notes; - TrafContacts({this.id, this.trafId, this.name, this.telephone, this.notes}); + TrafContacts({this.id, this.trafId, this.userId, this.name, this.telephone, this.notes}); TrafContacts.fromJson(Map json) { id = json['id']; trafId = json['trafId']; + userId = json['userId']; name = json['name']; telephone = json['telephone']; notes = json['notes']; @@ -470,6 +483,7 @@ class TrafContacts { final Map data = new Map(); data['id'] = this.id; data['trafId'] = this.trafId; + data['userId'] = this.userId; data['name'] = this.name; data['telephone'] = this.telephone; data['notes'] = this.notes; diff --git a/lib/modules/traf_module/update_traf_request_page.dart b/lib/modules/traf_module/update_traf_request_page.dart index 77fab5a1..e16e5726 100644 --- a/lib/modules/traf_module/update_traf_request_page.dart +++ b/lib/modules/traf_module/update_traf_request_page.dart @@ -87,7 +87,7 @@ class _UpdateTrafRequestPageState extends State { initialValue: classificationType, onSelect: (value) { classificationType = value; - trafRequest?.cla = value?.value; + // trafRequest?.cla = value?.value; // setState(() {}); }, ), diff --git a/lib/modules/traf_module/users_auto_complete_field.dart b/lib/modules/traf_module/users_auto_complete_field.dart new file mode 100644 index 00000000..12060844 --- /dev/null +++ b/lib/modules/traf_module/users_auto_complete_field.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/oracle_code_provider.dart'; +import 'package:test_sa/controllers/providers/api/parts_provider.dart'; +import 'package:test_sa/controllers/providers/api/search_user_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; +import 'package:test_sa/models/new_models/users_based_on_search_model.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../../../extensions/text_extensions.dart'; +import '../../../models/service_request/spare_parts.dart'; +import '../../../new_views/app_style/app_text_style.dart'; + +class SearchUserAutoCompleteField extends StatefulWidget { + final String initialValue; + final num? assetId; + final bool clearAfterPick, byName; + final Function(UsersBasedOnSearchModel) onPick; + + const SearchUserAutoCompleteField({Key? key, required this.byName, required this.initialValue, this.assetId, required this.onPick, this.clearAfterPick = true}) : super(key: key); + + @override + _UsersAutoCompleteFieldState createState() => _UsersAutoCompleteFieldState(); +} + +class _UsersAutoCompleteFieldState extends State { + late UserSearchProvider _TechnologyUsersProvider; + + late TextEditingController _controller; + + bool loading = false; + + @override + void initState() { + _controller = TextEditingController(text: widget.initialValue); + super.initState(); + _TechnologyUsersProvider = Provider.of(context, listen: false); + } + + @override + void didUpdateWidget(covariant SearchUserAutoCompleteField oldWidget) { + if (widget.initialValue != oldWidget.initialValue) { + _controller = TextEditingController(text: widget.initialValue); + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10)); + return Container( + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Autocomplete( + optionsBuilder: (TextEditingValue textEditingValue) async { + if (textEditingValue.text.isEmpty) { + if (loading) { + setState(() { + loading = false; + }); + } + return const Iterable.empty(); + } + if (!loading) { + setState(() { + loading = true; + }); + } + List workOrders = (await _TechnologyUsersProvider.getUsersBasedOnSearch(textEditingValue.text)); + setState(() { + loading = false; + }); + return workOrders; + }, + displayStringForOption: (UsersBasedOnSearchModel option) => widget.byName ? option.userName ?? "" : option.employeeId ?? "", + fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { + return TextField( + controller: _controller, + focusNode: fieldFocusNode, + style: AppTextStyles.bodyText.copyWith(color: AppColor.black10), + textAlign: TextAlign.start, + decoration: InputDecoration( + border: border, + disabledBorder: border, + focusedBorder: border, + enabledBorder: border, + errorBorder: border, + contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth), + constraints: const BoxConstraints(), + suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8), + filled: true, + fillColor: AppColor.fieldBgColor(context), + errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), + floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20), + labelText: "Users going to use technology", + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)), + suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null, + ), + textInputAction: TextInputAction.search, + onChanged: (text) { + fieldTextEditingController.text = text; + }, + onSubmitted: (String value) { + onFieldSubmitted(); + }, + ); + }, + onSelected: (UsersBasedOnSearchModel selection) { + if (widget.clearAfterPick) { + _controller.clear(); + } else { + _controller.text = widget.byName ? (selection.userName ?? "") : (selection.employeeId ?? ""); + } + widget.onPick(selection); + }, + ), + ); + } +} diff --git a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart index ff090f7b..f644e951 100644 --- a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart +++ b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart @@ -103,7 +103,7 @@ class CreateRequestModel { list.add(CreateRequestModel(context.translation.transferAsset, "add_icon", CreateDeviceTransferRequest.id)); //TODO uncommit this to enable task. list.add(CreateRequestModel(context.translation.task, "add_icon", CreateTaskView.id)); - list.add(CreateRequestModel("Traf".addTranslation, "add_icon", CreateTRAFRequestPage.id)); + list.add(CreateRequestModel("TRAF".addTranslation, "add_icon", CreateTRAFRequestPage.id)); } return list; } diff --git a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart index 5a5231b8..cbfbbf68 100644 --- a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart +++ b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart @@ -75,6 +75,10 @@ class _AllRequestsFilterPageState extends State { if (context.settingProvider.isUserFlowMedical) { types['Recall and Alert'] = 7; } + + if (!isEngineer) { + types['TRAF'] = 9; + } final statuses = { "All WO": 0, context.translation.open: 1, diff --git a/lib/new_views/pages/land_page/my_request/my_requests_page.dart b/lib/new_views/pages/land_page/my_request/my_requests_page.dart index 23f1c89a..46ef9af8 100644 --- a/lib/new_views/pages/land_page/my_request/my_requests_page.dart +++ b/lib/new_views/pages/land_page/my_request/my_requests_page.dart @@ -50,6 +50,9 @@ class _MyRequestsPageState extends State { if (context.settingProvider.isUserFlowMedical) { requestsList.add(Request(7, 'Recall and Alert')); } + if (context.userProvider.user!.type == UsersTypes.normal_user) { + requestsList.add(Request(9, 'TRAF')); + } _provider = Provider.of(context, listen: false); _provider!.reset(); From 599da0155427a78bcac75011a34374307e4145c6 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 16 Oct 2025 19:50:20 +0300 Subject: [PATCH 5/9] traf request item list view added. --- .../providers/api/all_requests_provider.dart | 2 +- .../widgets/request_category_list.dart | 3 + lib/models/new_models/dashboard_detail.dart | 15 +- .../traf_module/create_traf_request_page.dart | 3 +- .../traf_module/traf_request_item_view.dart | 130 ++++++++++++++++++ .../requests/request_paginated_listview.dart | 4 + .../widgets/request_item_view_list.dart | 3 + 7 files changed, 155 insertions(+), 5 deletions(-) diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 722dafbc..048e39f6 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -166,7 +166,7 @@ class AllRequestsProvider extends ChangeNotifier { } final type = typeTransaction == null ? search?.typeTransaction == null || (search?.typeTransaction?.isEmpty ?? false) - ? [1, 2, 3, 4, 5, 6, 7] + ? getStatues(context) : search!.typeTransaction : [typeTransaction]; List status = (search?.statuses == null || (search?.statuses?.isEmpty ?? false)) ? (((search?.isArchived ?? false) ? [3] : [1, 2, 4])) : search!.statuses!; diff --git a/lib/dashboard_latest/widgets/request_category_list.dart b/lib/dashboard_latest/widgets/request_category_list.dart index 5c6fe481..f2df78fb 100644 --- a/lib/dashboard_latest/widgets/request_category_list.dart +++ b/lib/dashboard_latest/widgets/request_category_list.dart @@ -3,6 +3,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/task_request_item_view.dart'; +import 'package:test_sa/modules/traf_module/traf_request_item_view.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/pages/land_page/requests/device_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/gas_refill_item_view.dart'; @@ -48,6 +49,8 @@ class RequestCategoryList extends StatelessWidget { return RecurrentWoItemView(requestData: request); case 6: return TaskRequestItemView(requestData: request); + case 9: + return TrafRequestItemView(requestData: request); default: return Container( height: 100, diff --git a/lib/models/new_models/dashboard_detail.dart b/lib/models/new_models/dashboard_detail.dart index 3773dc64..de0617be 100644 --- a/lib/models/new_models/dashboard_detail.dart +++ b/lib/models/new_models/dashboard_detail.dart @@ -57,10 +57,21 @@ class Data { int? transactionNo; String? nameOfType; - Data({this.id, this.typeTransaction, this.nameOfType,this.transactionDate, this.statusName, this.priorityName, this.isHighPriority, this.assetName, this.assetNumber, this.requestTypeName, this.requestNo,this.transactionNo}); + Data( + {this.id, + this.typeTransaction, + this.nameOfType, + this.transactionDate, + this.statusName, + this.priorityName, + this.isHighPriority, + this.assetName, + this.assetNumber, + this.requestTypeName, + this.requestNo, + this.transactionNo}); Data.fromJson(Map json) { - id = json['id']; typeTransaction = json['typeTransaction']; transactionDate = json['transactionDate']; diff --git a/lib/modules/traf_module/create_traf_request_page.dart b/lib/modules/traf_module/create_traf_request_page.dart index 8cac2b05..e2d066a9 100644 --- a/lib/modules/traf_module/create_traf_request_page.dart +++ b/lib/modules/traf_module/create_traf_request_page.dart @@ -433,12 +433,11 @@ class _CreateTRAFRequestPageState extends State { trafRequest?.employeeId = context.userProvider.user?.userID; trafRequest?.siteId = context.userProvider.user?.clientId; trafRequest?.trafContacts = []; - trafRequest?.trafContacts = userBasedOnSearch.map((item) => TrafContacts(id: 0, trafId: 0, name: item.userName)).toList(); + trafRequest?.trafContacts = userBasedOnSearch.map((item) => TrafContacts(id: 0, trafId: 0, name: item.userName, userId: item.userId)).toList(); Utils.showLoading(context); await Provider.of(context, listen: false).addTraf(trafRequest!.toJson()); Utils.hideLoading(context); Navigator.pop(context); - Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: 27))); } } diff --git a/lib/modules/traf_module/traf_request_item_view.dart b/lib/modules/traf_module/traf_request_item_view.dart index e69de29b..39bdd0bb 100644 --- a/lib/modules/traf_module/traf_request_item_view.dart +++ b/lib/modules/traf_module/traf_request_item_view.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.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/models/all_requests_and_count_model.dart'; +import 'package:test_sa/models/new_models/dashboard_detail.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/widgets/requests/request_status.dart'; + +import 'traf_request_detail_page.dart'; + +class TrafRequestItemView extends StatelessWidget { + final Data? requestData; + final RequestsDetails? requestDetails; + final bool showShadow; + + const TrafRequestItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key); + + @override + Widget build(BuildContext context) { + if (requestData != null) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // StatusLabel( + // label: requestData!.priorityName!, + // textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.priorityName!), + // backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.priorityName!), + // ), + // 8.width, + StatusLabel( + label: requestData!.statusName!, + textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!), + backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!), + ), + 1.width.expanded, + Text( + requestData!.transactionDate?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), + ), + ], + ), + 8.height, + (requestData?.typeTransaction ?? "TRAF Request").heading5(context), + infoWidget(label: context.translation.requestType, value: requestData?.requestTypeName, context: context), + infoWidget(label: "TRAF No", value: requestData?.requestNo, context: context), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.viewDetails, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + ), + 4.width, + Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).toShadowContainer(context, withShadow: showShadow).onPress(() async { + Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: requestDetails!.id!))); + // Navigator.of(context).push(MaterialPageRoute( + // builder: (_) => TaskRequestDetailsView( + // taskId: requestData!.id!, + // requestDetails: RequestsDetails(nameOfType: requestData?.nameOfType, status: requestData?.statusName, priority: requestData?.priorityName, date: requestData?.transactionDate), + // ))); + }); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // StatusLabel( + // label: requestDetails!.priority!, + // textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.priority!), + // backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.priority!), + // ), + // 8.width, + StatusLabel( + label: requestDetails!.status!, + textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!), + backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!), + ), + 1.width.expanded, + Text( + requestDetails!.date?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), + ), + ], + ), + 8.height, + (requestDetails?.nameOfType ?? "TRAF Request").heading5(context), + 8.height, + infoWidget(label: context.translation.requestType, value: requestDetails!.requestType, context: context), + infoWidget(label: "TRAF No", value: requestDetails!.requestNo, context: context), + infoWidget(label: context.translation.site, value: requestDetails!.site, context: context), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.viewDetails, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + ), + 4.width, + Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).toShadowContainer(context, withShadow: showShadow).onPress(() async { + Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: requestDetails!.id!))); + }); + } + + Widget infoWidget({required String label, String? value, required BuildContext context}) { + if (value != null && value.isNotEmpty) { + return '$label: $value'.bodyText(context); + } + return const SizedBox(); + } +} diff --git a/lib/new_views/pages/land_page/requests/request_paginated_listview.dart b/lib/new_views/pages/land_page/requests/request_paginated_listview.dart index ace4047f..d3064427 100644 --- a/lib/new_views/pages/land_page/requests/request_paginated_listview.dart +++ b/lib/new_views/pages/land_page/requests/request_paginated_listview.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/task_request_item_view.dart'; +import 'package:test_sa/modules/traf_module/traf_request_item_view.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/pages/land_page/requests/device_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/gas_refill_item_view.dart'; @@ -51,6 +52,7 @@ class RequestPaginatedListview extends StatelessWidget { bool isPPMs = request.transactionNo == 4; bool isRecurrentTask = request.transactionNo == 5; bool isTask = request.transactionNo == 6; + bool isTRAF = request.transactionNo == 9; if (isServiceRequest) { return ServiceRequestItemView(requestData: request, refreshData: false); @@ -64,6 +66,8 @@ class RequestPaginatedListview extends StatelessWidget { return RecurrentWoItemView(requestData: request); } else if (isTask) { return TaskRequestItemView(requestData: request); + } else if (isTRAF) { + return TrafRequestItemView(requestData: request); } else { return Container( height: 100, diff --git a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart index a3548947..e29703d4 100644 --- a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart +++ b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart @@ -5,6 +5,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/task_request_item_view.dart'; +import 'package:test_sa/modules/traf_module/traf_request_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/device_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/gas_refill_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/ppm_item_view.dart'; @@ -42,6 +43,8 @@ class RequestItemViewList extends StatelessWidget { return TaskRequestItemView(requestDetails: list[index]); case 7: return TaskRequestItemView(requestDetails: list[index]); + case 9: + return TrafRequestItemView(requestDetails: list[index]); default: Container( height: 100, From 7c367ba614010babc7ec4955f43aef3859e63be7 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 16 Oct 2025 19:55:39 +0300 Subject: [PATCH 6/9] Apk provided to QA. --- lib/controllers/api_routes/urls.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 7fc41288..89b58897 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -4,12 +4,12 @@ class URLs { static const String appReleaseBuildNumber = "26"; // static const host1 = "https://atomsm.hmg.com"; // production url - static const host1 = "https://atomsmdev.hmg.com"; // local DEV url - // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url + // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url + static const host1 = "https://atomsmuat.hmg.com"; // local UAT url // static String _baseUrl = "$_host/mobile"; - // static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis - static final String _baseUrl = "$_host/mobile"; // host local UAT + static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis + // static final String _baseUrl = "$_host/mobile"; // host local UAT // static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM static String _host = host1; From 8c45d89c3e734dea2fceef10775f35aa509156b3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 19 Oct 2025 10:48:04 +0300 Subject: [PATCH 7/9] improvements --- .../traf_module/traf_request_detail_page.dart | 52 +++++++++++-------- .../traf_module/traf_request_model.dart | 9 +++- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/lib/modules/traf_module/traf_request_detail_page.dart b/lib/modules/traf_module/traf_request_detail_page.dart index 5682b444..7283bf98 100644 --- a/lib/modules/traf_module/traf_request_detail_page.dart +++ b/lib/modules/traf_module/traf_request_detail_page.dart @@ -59,10 +59,8 @@ class _TrafRequestDetailPageState extends State { requesterInformation(trafProvider.trafRequestDataModel!), 12.height, requestInformation(trafProvider.trafRequestDataModel!), - if (trafProvider.trafRequestDataModel!.requestTypeId == 733) ...[ - 12.height, - assetInformation(trafProvider.trafRequestDataModel!), - ] + 12.height, + assetInformation(trafProvider.trafRequestDataModel!), ], ).expanded, // // if (isEngineer) @@ -91,12 +89,12 @@ class _TrafRequestDetailPageState extends State { style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, - '${context.translation.employeeId}: ${data.employeeId ?? '-'}'.bodyText(context), - '${context.translation.name}: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer - '${context.translation.email}: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer - 'Position: ${data.employeeId ?? '-'}'.bodyText(context), // todo ask shaheer + '${context.translation.employeeId}: ${data.employeeIdForDisplay ?? '-'}'.bodyText(context), + '${context.translation.name}: ${data.employeeName ?? '-'}'.bodyText(context), // todo ask shaheer + '${context.translation.email}: ${data.employeeEmail ?? '-'}'.bodyText(context), // todo ask shaheer + 'Position: ${data.positionName ?? '-'}'.bodyText(context), // todo ask shaheer '${context.translation.site}: ${data.siteName ?? '-'}'.bodyText(context), - '${context.translation.department}: ${data.departments ?? '-'}'.bodyText(context), + '${context.translation.department}: ${data.departments?.map((item) => item.departmentName).toList() ?? '-'}'.bodyText(context), 'Requester Extension: ${data.requesterExtensionName ?? '-'}'.bodyText(context), '${context.translation.extensionNo}: ${data.requesterExtensionNumber ?? '-'}'.bodyText(context), ], @@ -109,23 +107,26 @@ class _TrafRequestDetailPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "TRAF Request Information", + "Request Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, 'TRAF No: ${data.reqCode ?? '-'}'.bodyText(context), 'Request type: ${data.requestTypeName ?? '-'}'.bodyText(context), 4.height, - 'What is the current practice?:\n${data.currentPractise ?? '-'}'.bodyText(context), + 'How would the requested technology solve the current situation and/or serve the purpose?: ${data.purposeAnswer ?? '-'}'.bodyText(context), + 4.height, + 'What is the current practice?: ${data.currentPractise ?? '-'}'.bodyText(context), 4.height, 'Census Q1: ${data.censusQ1 ?? '-'}'.bodyText(context), 'Census Q2: ${data.censusQ2 ?? '-'}'.bodyText(context), 'Census Q3: ${data.censusQ3 ?? '-'}'.bodyText(context), 'Census Q4: ${data.censusQ4 ?? '-'}'.bodyText(context), 4.height, - 'List down names & contact information of users going to use the technology & specify if they are part-time or full time?:\n${data.trafContacts ?? '-'}'.bodyText(context), + 'List down names & contact information of users going to use the technology & specify if they are part-time or full time?:\n${data.trafContacts?.map((item) => item.name).toList() ?? '-'}' + .bodyText(context), 4.height, - 'Is the requesting department going to use the technology solely or shared with other departments?:\n${data.usingSolelyOrSharedId ?? '-'}'.bodyText(context), + 'Is the requesting department going to use the technology solely or shared with other departments?:\n${data.usingSolelyOrSharedName ?? '-'}'.bodyText(context), 4.height, 'Would other services be effected by acquiring the new equipment?:\n${data.effectedServices ?? '-'}'.bodyText(context), 4.height, @@ -144,16 +145,21 @@ class _TrafRequestDetailPageState extends State { style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, - 'Last price & PO: ${data.poNumber ?? '-'}'.bodyText(context), - 'The quantity of the same asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Existing asset under SLA: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Age of the asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Total Maintenance Cost (TMC): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Net Book Value (NBV): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Mean Time Between Failure (MTBF): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Down Time (DT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Up Time (UT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer - 'Purchased Price: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + '${context.translation.assetName}: ${data.assetName ?? '-'}'.bodyText(context), + '${context.translation.model}: ${data.modelName ?? '-'}'.bodyText(context), + '${context.translation.manufacture}: ${data.manufacturerName ?? '-'}'.bodyText(context), + if (data.requestTypeId == 733) ...[ + 'Last price & PO: ${data.poNumber ?? '-'}'.bodyText(context), + 'The quantity of the same asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Existing asset under SLA: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Age of the asset: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Total Maintenance Cost (TMC): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Net Book Value (NBV): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Mean Time Between Failure (MTBF): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Down Time (DT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Up Time (UT): ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + 'Purchased Price: ${data.qty ?? '-'}'.bodyText(context), // todo check with shaheer + ], ], ).toShadowContainer(context, borderRadius: 20, padding: 12); } diff --git a/lib/modules/traf_module/traf_request_model.dart b/lib/modules/traf_module/traf_request_model.dart index 0d1eedf1..b5de3280 100644 --- a/lib/modules/traf_module/traf_request_model.dart +++ b/lib/modules/traf_module/traf_request_model.dart @@ -46,6 +46,7 @@ class TrafRequestDataModel { int? reqNo; String? reqCode; String? employeeId; + String? employeeIdForDisplay; String? employeeName; String? employeeEmail; int? positionId; @@ -140,6 +141,7 @@ class TrafRequestDataModel { {this.reqNo, this.reqCode, this.employeeId, + this.employeeIdForDisplay, this.employeeName, this.employeeEmail, this.positionId, @@ -234,6 +236,7 @@ class TrafRequestDataModel { reqNo = json['reqNo']; reqCode = json['reqCode']; employeeId = json['employeeId']; + employeeIdForDisplay = json['employeeIdForDisplay']; employeeName = json['employeeName']; employeeEmail = json['employeeEmail']; positionId = json['positionId']; @@ -355,6 +358,7 @@ class TrafRequestDataModel { data['reqNo'] = this.reqNo; data['reqCode'] = this.reqCode; data['employeeId'] = this.employeeId; + data['employeeIdForDisplay'] = this.employeeIdForDisplay; data['employeeName'] = this.employeeName; data['employeeEmail'] = this.employeeEmail; data['positionId'] = this.positionId; @@ -526,13 +530,15 @@ class Departments { int? id; int? trafId; int? departmentId; + String? departmentName; - Departments({this.id, this.trafId, this.departmentId}); + Departments({this.id, this.trafId, this.departmentId, this.departmentName}); Departments.fromJson(Map json) { id = json['id']; trafId = json['trafId']; departmentId = json['departmentId']; + departmentName = json['departmentName']; } Map toJson() { @@ -540,6 +546,7 @@ class Departments { data['id'] = this.id; data['trafId'] = this.trafId; data['departmentId'] = this.departmentId; + data['departmentName'] = this.departmentName; return data; } } From 40c7e75fa47cb7a9931301225601e038fd34ee9c Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 20 Oct 2025 16:30:10 +0300 Subject: [PATCH 8/9] assessor role added for TRAF. --- .../providers/api/all_requests_provider.dart | 13 +++++++++---- lib/controllers/providers/api/user_provider.dart | 7 +++++++ lib/models/enums/user_types.dart | 2 ++ lib/models/user.dart | 12 ++++++++---- .../land_page/create_request-type_bottomsheet.dart | 14 ++++++++------ lib/new_views/pages/land_page/land_page.dart | 3 +-- .../my_request/all_requests_filter_page.dart | 6 +++++- .../land_page/my_request/my_requests_page.dart | 7 +++++++ 8 files changed, 47 insertions(+), 17 deletions(-) diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 048e39f6..470f803d 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -134,19 +134,24 @@ class AllRequestsProvider extends ChangeNotifier { List getStatues(BuildContext context) { List list = [1, 2, 3, 4]; - if (context.userProvider.user!.type != UsersTypes.normal_user) { + if (context.userProvider.isAssessor) { + list = [9]; + return list; + } + + if (!context.userProvider.isNurse) { list.add(5); } list.add(6); // task module - if (context.settingProvider.isUserFlowMedical && context.userProvider.user!.type != UsersTypes.normal_user) { + if (context.settingProvider.isUserFlowMedical && !context.userProvider.isNurse) { list.add(7); // task mod } - if (context.userProvider.user!.type != UsersTypes.normal_user) { + if (!context.userProvider.isNurse) { list.add(8); // } - if (context.userProvider.user!.type == UsersTypes.normal_user) { + if (context.userProvider.isNurse) { list.add(9); // } diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index 6e6fc577..f8c93d63 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -8,6 +8,7 @@ import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/new_models/general_response_model.dart'; import 'package:test_sa/models/new_models/update_password.dart'; import 'package:test_sa/models/new_models/verify_otp_model.dart'; @@ -39,6 +40,12 @@ class UserProvider extends ChangeNotifier { File? profileImage; + bool get isEngineer => user!.type == UsersTypes.engineer; + + bool get isNurse => user!.type == UsersTypes.normal_user; + + bool get isAssessor => user!.type == UsersTypes.assessor || user!.type == UsersTypes.assessorTl; + VerifyOtpModel _verifyOtpModel = VerifyOtpModel(); SwipeTransaction _swipeTransactionModel = SwipeTransaction(); List _swipeHistory = []; diff --git a/lib/models/enums/user_types.dart b/lib/models/enums/user_types.dart index e84e2493..63f1d9d7 100644 --- a/lib/models/enums/user_types.dart +++ b/lib/models/enums/user_types.dart @@ -2,4 +2,6 @@ enum UsersTypes { engineer, // 0 normal_user, // 1 nurse, // 1 + assessor, + assessorTl } diff --git a/lib/models/user.dart b/lib/models/user.dart index a1ed40b0..3ffc5b29 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -88,12 +88,13 @@ class User { Future> toLoginJson() async { String notificationType = (Platform.isAndroid && !(await FirebaseNotificationManger.isGoogleServicesAvailable())) ? "HMC" : "FCM"; - if(FirebaseNotificationManger.token==null){ + if (FirebaseNotificationManger.token == null) { //calling this agin to check for token as sometimes token is null fresh install.. await FirebaseNotificationManger.getToken(); } return {"username": userName, "password": password, "fireBaseToken": FirebaseNotificationManger?.token ?? "", "notificationType": notificationType}; } + UsersTypes? get type { switch (userRoles?.first.value) { case "R-6": @@ -102,11 +103,16 @@ class User { return UsersTypes.normal_user; case "R-33": // Head Nurse Role return UsersTypes.normal_user; + case "R-32": // Head Nurse Role + return UsersTypes.assessor; + case "R-19": // Head Nurse Role + return UsersTypes.assessorTl; default: return null; } } + Map toUpdateProfileJson() { Map jsonObject = {}; // if (departmentId != null) jsonObject["department"] = departmentId; @@ -309,9 +315,7 @@ class AssetGroup { } @override - bool operator ==(Object other) => - identical(this, other) || - other is AssetGroup && runtimeType == other.runtimeType && id == other.id; + bool operator ==(Object other) => identical(this, other) || other is AssetGroup && runtimeType == other.runtimeType && id == other.id; @override int get hashCode => id.hashCode; diff --git a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart index f644e951..cca09e6e 100644 --- a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart +++ b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart @@ -5,6 +5,7 @@ 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/models/enums/user_types.dart'; import 'package:test_sa/modules/cm_module/views/nurse/create_new_request_view.dart'; import 'package:test_sa/modules/tm_module/tasks_wo/create_task_view.dart'; import 'package:test_sa/modules/traf_module/create_traf_request_page.dart'; @@ -13,13 +14,11 @@ import 'package:test_sa/new_views/pages/gas_refill_request_form.dart'; import 'package:test_sa/views/pages/device_transfer/create__device_transfer_request.dart'; class CreateRequestTypeBottomSheet extends StatelessWidget { - final bool isEngineer; - - const CreateRequestTypeBottomSheet({super.key, required this.isEngineer}); + const CreateRequestTypeBottomSheet({super.key}); @override Widget build(BuildContext context) { - List requestList = CreateRequestModel.requestsList(context, isEngineer); + List requestList = CreateRequestModel.requestsList(context); return SafeArea( top: false, @@ -89,9 +88,12 @@ class CreateRequestModel { CreateRequestModel(this.title, this.icon, this.routeName); - static List requestsList(BuildContext context, bool isEngineer) { + static List requestsList(BuildContext context) { List list = []; - if (isEngineer) { + + if (context.userProvider.isAssessor) { + list.add(CreateRequestModel("TRAF".addTranslation, "add_icon", CreateTRAFRequestPage.id)); + } else if (context.userProvider.isEngineer) { if (Provider.of(context, listen: false).engineerCanCreateCM) { list.add(CreateRequestModel(context.translation.correctiveMaintenance, "add_icon", CreateNewRequest.id)); } diff --git a/lib/new_views/pages/land_page/land_page.dart b/lib/new_views/pages/land_page/land_page.dart index 0aebe82e..b28b6eb2 100644 --- a/lib/new_views/pages/land_page/land_page.dart +++ b/lib/new_views/pages/land_page/land_page.dart @@ -161,13 +161,12 @@ class _LandPageState extends State { : AppBottomNavigationBar( selectedIndex: currentPageIndex, onPressed: (index) { - bool isEngineer = _userProvider!.user!.type == UsersTypes.engineer; if (index == 2) { showModalBottomSheet( context: context, useSafeArea: true, backgroundColor: Colors.white, - builder: (context) => CreateRequestTypeBottomSheet(isEngineer: isEngineer), + builder: (context) => CreateRequestTypeBottomSheet(), ); } else if (index == 4) { showModalBottomSheet( diff --git a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart index cbfbbf68..c1c4729f 100644 --- a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart +++ b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart @@ -60,7 +60,7 @@ class _AllRequestsFilterPageState extends State { ); search!.searchBySelectedValue = search?.requestNumber; } - final types = { + var types = { context.translation.correctiveMaintenance: 1, context.translation.gasRefill: 2, context.translation.transferAsset: 3, @@ -79,6 +79,10 @@ class _AllRequestsFilterPageState extends State { if (!isEngineer) { types['TRAF'] = 9; } + if (context.userProvider.isAssessor) { + types = {"TRAF": 9}; + } + final statuses = { "All WO": 0, context.translation.open: 1, diff --git a/lib/new_views/pages/land_page/my_request/my_requests_page.dart b/lib/new_views/pages/land_page/my_request/my_requests_page.dart index 46ef9af8..8ac38ab6 100644 --- a/lib/new_views/pages/land_page/my_request/my_requests_page.dart +++ b/lib/new_views/pages/land_page/my_request/my_requests_page.dart @@ -54,6 +54,13 @@ class _MyRequestsPageState extends State { requestsList.add(Request(9, 'TRAF')); } + if (context.userProvider.isAssessor) { + requestsList = [ + Request(null, context.translation.allWorkOrder), + Request(9, 'TRAF'), + ]; + } + _provider = Provider.of(context, listen: false); _provider!.reset(); WidgetsBinding.instance.addPostFrameCallback((_) { From b71207538d5bc39feb2364aaeea87f94d344f0af Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 21 Oct 2025 12:49:51 +0300 Subject: [PATCH 9/9] assessor dashboard api improvement. --- lib/dashboard_latest/dashboard_provider.dart | 6 +++--- lib/modules/traf_module/traf_request_item_view.dart | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index 61298f75..c09cb621 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -106,14 +106,14 @@ class DashBoardProvider extends ChangeNotifier { isAllCountLoading = true; notifyListeners(); String url = ''; - if (usersType == UsersTypes.engineer) { + if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) { url = URLs.engineerDashboardCountUrl; } else { url = URLs.nurseDashboardCountUrl; } Response response; try { - response = await ApiManager.instance.post(url,body: {}); + response = await ApiManager.instance.post(url, body: {}); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { dashboardCount = DashboardCount.fromJson(json.decode(response.body)); @@ -241,7 +241,7 @@ class DashBoardProvider extends ChangeNotifier { Response response; String url = ''; - if (usersType == UsersTypes.engineer) { + if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) { //need to check pagination for not assigned task @waseem. //these checks are to call different apis for dashboard for engineer... diff --git a/lib/modules/traf_module/traf_request_item_view.dart b/lib/modules/traf_module/traf_request_item_view.dart index 39bdd0bb..1bf03eb5 100644 --- a/lib/modules/traf_module/traf_request_item_view.dart +++ b/lib/modules/traf_module/traf_request_item_view.dart @@ -64,12 +64,7 @@ class TrafRequestItemView extends StatelessWidget { ), ], ).toShadowContainer(context, withShadow: showShadow).onPress(() async { - Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: requestDetails!.id!))); - // Navigator.of(context).push(MaterialPageRoute( - // builder: (_) => TaskRequestDetailsView( - // taskId: requestData!.id!, - // requestDetails: RequestsDetails(nameOfType: requestData?.nameOfType, status: requestData?.statusName, priority: requestData?.priorityName, date: requestData?.transactionDate), - // ))); + Navigator.push(context, MaterialPageRoute(builder: (context) => TrafRequestDetailPage(trafId: requestData!.id!))); }); } return Column(