From 3f90630db98879cda9e92b94d9d953318d66a8fc Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 27 Feb 2025 09:23:32 +0300 Subject: [PATCH 01/36] gas refill and asset transfer ui completed waiting for api --- lib/controllers/api_routes/urls.dart | 8 +- .../providers/api/gas_refill_provider.dart | 21 + lib/main.dart | 2 + lib/models/device/asset_transfer.dart | 149 ++-- lib/models/new_models/gas_refill_model.dart | 188 ++-- .../plan_preventive_visit_model.dart | 4 +- .../device_transfer_details.dart | 2 + .../update_device_transfer.dart | 837 +++++++++++++++--- .../user/gas_refill/gas_refill_details.dart | 6 +- .../user/gas_refill/gas_refill_form.dart | 424 +++++++++ .../user/ppm/update_ppm/ppm_pm_kits_form.dart | 3 + .../user/ppm/update_ppm/wo_info_form.dart | 1 - .../parts/auto_complete_parts_field.dart | 1 + 13 files changed, 1409 insertions(+), 237 deletions(-) create mode 100644 lib/views/pages/user/gas_refill/gas_refill_form.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index aaba34ee..a31b4426 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -3,12 +3,12 @@ class URLs { static const String appReleaseBuildNumber = "14"; // 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"; // new V3 apis static String _host = host1; diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index a5d59016..bab1b5d2 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -9,6 +10,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/new_models/gas_refill_model.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/user.dart'; import '../../../new_views/common_widgets/app_lazy_loading.dart'; @@ -43,6 +45,16 @@ class GasRefillProvider extends ChangeNotifier { // done _loading = true // failed _loading = false bool isLoading = false; + List _gasRefillAttachments = []; + + List get gasRefillAttachments => _gasRefillAttachments; + + set gasRefillAttachments(List value) { + _gasRefillAttachments = value; + notifyListeners(); + } + + Future getGasRefillObjectById(num id) async { try { @@ -58,6 +70,15 @@ class GasRefillProvider extends ChangeNotifier { } } + // void updateRecurrentWoTimer({TimerModel? timer}) { + // recurrentWoData?.recurrentWoTimerModel = timer; + // if (timer?.startAt != null && timer?.endAt != null) { + // recurrentWoData?.timerModelList = recurrentWoData?.timerModelList ?? []; + // recurrentWoData?.timerModelList!.add(timer!); + // } + // 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 diff --git a/lib/main.dart b/lib/main.dart index b16998bd..7c9425f6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -71,6 +71,7 @@ import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; +import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; @@ -293,6 +294,7 @@ class MyApp extends StatelessWidget { ServiceRequestsPage.id: (_) => const ServiceRequestsPage(), //ReportIssuesPage.id: (_) => ReportIssuesPage(), RequestGasRefill.id: (_) => const RequestGasRefill(), + GasRefillForm.id: (_) => const GasRefillForm(), CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), CreateNewRequest.id: (_) => const CreateNewRequest(), // SingleHospitalPicker.id: (_) => SingleHospitalPicker(), diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index 40ae2302..c14efd73 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -8,75 +8,77 @@ import 'package:test_sa/models/timer_model.dart'; import 'asset_transfer_attachment.dart'; class AssetTransfer { - AssetTransfer( - {this.id, - this.transferNo, - this.transferCode, - this.assetId, - this.destSiteId, - this.destBuildingId, - this.destFloorId, - this.destDepartmentId, - this.destRoomId, - this.senderSiteId, - this.senderBuildingId, - this.senderFloorId, - this.senderDepartmentId, - this.senderRoom, - this.senderAssignedEmployeeId, - this.senderMachineStatusId, - this.senderComment, - this.comment, - this.receiverEndUserId, - this.receiverEndUserName, - this.senderStartDate, - this.senderEndDate, - this.senderWorkingHours, - this.senderTravelingHours, - this.senderEngSignature, - this.senderAttachments, - this.receiverAssignedEmployeeId, - this.receiverMachineStatusId, - this.receiverComment, - this.receiverStartDate, - this.receiverEndDate, - this.receiverWorkingHours, - this.receiverTravelingHours, - this.receiverEngSignature, - this.receiverAttachments, - this.assetNumber, - this.assetName, - this.manufacturerName, - this.modelName, - this.assetSerialNo, - this.destDepartmentName, - this.destBuildingName, - this.applied, - this.extensionNo, - this.name, - this.employeeId, - this.createdDate, - this.createdOn, - this.destFloorName, - this.destSiteName, - this.manufacturerId, - this.modelId, - this.modifiedOn, - this.receiverAssignedEmployeeName, - this.receiverEngSignatureUrl, - this.receiverMachineStatusName, - this.senderAssignedEmployeeName, - this.senderBuildingName, - this.senderDepartmentName, - this.senderEngSignatureUrl, - this.senderFloorName, - this.senderMachineStatusName, - this.senderSiteName, - this.supplierId, - this.supplierName, - this.senderVisitTimers, - this.receiverVisitTimers, - this.tbsTimer}); + AssetTransfer({ + this.id, + this.transferNo, + this.transferCode, + this.assetId, + this.destSiteId, + this.destBuildingId, + this.destFloorId, + this.destDepartmentId, + this.destRoomId, + this.senderSiteId, + this.senderBuildingId, + this.senderFloorId, + this.senderDepartmentId, + this.senderRoom, + this.senderAssignedEmployeeId, + this.senderMachineStatusId, + this.senderComment, + this.comment, + this.receiverEndUserId, + this.receiverEndUserName, + this.senderStartDate, + this.senderEndDate, + this.senderWorkingHours, + this.senderTravelingHours, + this.senderEngSignature, + this.senderAttachments, + this.receiverAssignedEmployeeId, + this.receiverMachineStatusId, + this.receiverComment, + this.receiverStartDate, + this.receiverEndDate, + this.receiverWorkingHours, + this.receiverTravelingHours, + this.receiverEngSignature, + this.receiverAttachments, + this.assetNumber, + this.assetName, + this.manufacturerName, + this.modelName, + this.assetSerialNo, + this.destDepartmentName, + this.destBuildingName, + this.applied, + this.extensionNo, + this.name, + this.employeeId, + this.createdDate, + this.createdOn, + this.destFloorName, + this.destSiteName, + this.manufacturerId, + this.modelId, + this.modifiedOn, + this.receiverAssignedEmployeeName, + this.receiverEngSignatureUrl, + this.receiverMachineStatusName, + this.senderAssignedEmployeeName, + this.senderBuildingName, + this.senderDepartmentName, + this.senderEngSignatureUrl, + this.senderFloorName, + this.senderMachineStatusName, + this.senderSiteName, + this.supplierId, + this.supplierName, + this.senderVisitTimers, + this.receiverVisitTimers, + this.tbsTimer, + this.timerModelList, + }); AssetTransfer.fromJson(dynamic json) { id = json['id']; @@ -250,6 +252,7 @@ class AssetTransfer { String? modifiedOn; List? senderVisitTimers; List? receiverVisitTimers; + List? timerModelList = []; TimerModel? tbsTimer = TimerModel(); AssetTransfer copyWith( @@ -375,10 +378,10 @@ class AssetTransfer { receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName, receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl, applied: applied ?? this.applied, - extensionNo: extensionNo??this.extensionNo, - employeeId: employeeId??this.employeeId, - name: name??this.name, - createdDate: createdDate??this.createdDate, + extensionNo: extensionNo ?? this.extensionNo, + employeeId: employeeId ?? this.employeeId, + name: name ?? this.name, + createdDate: createdDate ?? this.createdDate, createdOn: createdOn ?? this.createdOn, modifiedOn: modifiedOn ?? this.modifiedOn, assetSerialNo: assetSerialNo ?? this.assetSerialNo, diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 938d94e4..140e68a9 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -38,7 +38,12 @@ class GasRefillModel { this.gazRefillDetails, this.localEngineerSignature, this.localNurseSignature, - this.timer}); + this.timer, + this.timerModelList, + this.gasRefillTimer, + this.gasRefillAttachments, + + }); GasRefillModel.fromJson(dynamic json) { id = json['id']; @@ -55,6 +60,21 @@ class GasRefillModel { employeeId = json['employeeId']; name = json['name']; createdDate = json['createdDate']; + //TODO need to use this when added from backend... + if (json['gasRefillTimer'] != null) { + gasRefillTimer = []; + json['gasRefillTimer'].forEach((v) { + gasRefillTimer?.add(GasRefillTimer.fromJson(v)); + }); + workingHours = json['gasRefillTimer'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDateTime']).difference(DateTime.parse(item['startDateTime'])).inSeconds) ?? 0; + } + if (json['gasRefillAttachments'] != null) { + gasRefillAttachments = []; + json['gasRefillAttachments'].forEach((v) { + gasRefillAttachments!.add(GasRefillAttachments.fromJson(v)); + }); + } + try { final DateTime? sd = DateTime.tryParse(startDate ?? ""); final DateTime? st = DateTime.tryParse(startTime ?? ""); @@ -98,7 +118,7 @@ class GasRefillModel { String? endTime; // Now nullable String? engSignature; // Now nullable String? nurseSignature; // Now nullable - num? workingHours; + double? workingHours; dynamic extensionNo; String? employeeId; String? name; @@ -113,56 +133,13 @@ class GasRefillModel { List? gazRefillDetails; // Now nullable Uint8List? localNurseSignature; // Now nullable Uint8List? localEngineerSignature; // Now nullable - TimerModel? timer; // Now nullable + TimerModel? timer; + //TODO need to check when api provided.. + List? timerModelList = []; + List? gasRefillTimer = []; + List? gasRefillAttachments; + - GasRefillModel copyWith({ - num? id, // Parameters are now nullable - String? gazRefillNo, - String? expectedDate, - String? expectedTime, - String? startDate, - String? startTime, - String? endDate, - String? endTime, - String? engSignature, - String? nurseSignature, - num? workingHours, - num? extensionNo, - num? employeeId, - String? name, - String? createdDate, - Site? site, - Building? building, - Floor? floor, - Department? department, - AssignedEmployee? assignedEmployee, - Lookup? status, - String? comment, - List? gazRefillDetails, - TimerModel? timer, - }) => - GasRefillModel( - id: id ?? this.id, - gazRefillNo: gazRefillNo ?? this.gazRefillNo, - expectedDate: expectedDate ?? this.expectedDate, - expectedTime: expectedTime ?? this.expectedTime, - startDate: startDate ?? this.startDate, - startTime: startTime ?? this.startTime, - endDate: endDate ?? this.endDate, - endTime: endTime ?? this.endTime, - engSignature: engSignature ?? this.engSignature, - nurseSignature: nurseSignature ?? this.nurseSignature, - workingHours: workingHours ?? this.workingHours, - site: site ?? this.site, - building: building ?? this.building, - floor: floor ?? this.floor, - department: department ?? this.department, - assignedEmployee: assignedEmployee ?? this.assignedEmployee, - status: status ?? this.status, - comment: comment ?? this.comment, - gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails, - timer: timer ?? this.timer, - ); Map toJson() { final map = {}; @@ -182,6 +159,14 @@ class GasRefillModel { map['name'] = name; map['createdDate'] = createdDate; map['comment'] = comment; + //TODO need to check parameters here ... + if (gasRefillTimer != null) { + map['gasRefillTimer'] = gasRefillTimer?.map((v) => v.toJson()).toList(); + } + if (gasRefillAttachments != null) { + map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); + } + if (site != null) { map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety } @@ -203,6 +188,8 @@ class GasRefillModel { if (gazRefillDetails != null) { map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null } + + return map; } @@ -248,6 +235,58 @@ class GasRefillModel { name = model.name; createdDate = model.createdDate; } + + GasRefillModel copyWith({ + num? id, // Parameters are now nullable + String? gazRefillNo, + String? expectedDate, + String? expectedTime, + String? startDate, + String? startTime, + String? endDate, + String? endTime, + String? engSignature, + String? nurseSignature, + double? workingHours, + num? extensionNo, + num? employeeId, + String? name, + String? createdDate, + Site? site, + Building? building, + Floor? floor, + Department? department, + AssignedEmployee? assignedEmployee, + Lookup? status, + String? comment, + List? gazRefillDetails, + List? gasRefillTimer, + TimerModel? timer, + + }) => + GasRefillModel( + id: id ?? this.id, + gazRefillNo: gazRefillNo ?? this.gazRefillNo, + expectedDate: expectedDate ?? this.expectedDate, + expectedTime: expectedTime ?? this.expectedTime, + startDate: startDate ?? this.startDate, + startTime: startTime ?? this.startTime, + endDate: endDate ?? this.endDate, + endTime: endTime ?? this.endTime, + engSignature: engSignature ?? this.engSignature, + nurseSignature: nurseSignature ?? this.nurseSignature, + workingHours: workingHours ?? this.workingHours, + site: site ?? this.site, + building: building ?? this.building, + floor: floor ?? this.floor, + department: department ?? this.department, + assignedEmployee: assignedEmployee ?? this.assignedEmployee, + status: status ?? this.status, + comment: comment ?? this.comment, + gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails, + timer: timer ?? this.timer, + gasRefillTimer : gasRefillTimer ?? this.gasRefillTimer, + ); } class GasRefillDetails { @@ -330,4 +369,51 @@ class GasRefillDetails { } return true; } + +} + +class GasRefillTimer { + int? id; + String? startTime; + String? endTime; + dynamic workingHours; + + GasRefillTimer({this.id, this.startTime, this.endTime, this.workingHours}); + + GasRefillTimer.fromJson(Map json) { + id = json['id']; + startTime = json['startDateTime']; + endTime = json['endDateTime']; + workingHours = json['workingHour']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['startDateTime'] = startTime; + data['endDateTime'] = endTime; + data['workingHour'] = workingHours; + return data; + } +} + +class GasRefillAttachments { + int? id; + String? attachmentName; + + GasRefillAttachments({this.id, this.attachmentName}); + + GasRefillAttachments.fromJson(Map json) { + id = json['id']; + attachmentName = json['attachmentName']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['attachmentName'] = attachmentName; + return data; + } } + + diff --git a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart index 82c9e43d..f138598e 100644 --- a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart +++ b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart @@ -949,14 +949,14 @@ class PreventiveVisitKits { PreventiveVisitKits.fromJson(Map json) { id = json['id']; + partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null; } Map toJson() { - final Map data = Map(); + final Map data = {}; data['id'] = id; if (partCatalogItem != null) { - // data['partCatalogItem'] = partCatalogItem!.toJson(); data['partCatalogItemId'] = partCatalogItem?.id; } return data; diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index 1815d04c..87f41133 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -237,4 +237,6 @@ class _DeviceTransferDetailsState extends State { } } + + } diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 8a3ffcf9..aff1a2e3 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -1,3 +1,335 @@ +// import 'dart:convert'; +// import 'dart:io'; +// +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/material.dart'; +// import 'package:fluttertoast/fluttertoast.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/asset_transfer_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/string_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/device/asset_transfer.dart'; +// import 'package:test_sa/models/device/asset_transfer_attachment.dart'; +// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; +// import 'package:test_sa/views/app_style/sizing.dart'; +// import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +// import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +// +// import '../../../extensions/text_extensions.dart'; +// import '../../../models/lookup.dart'; +// import '../../../models/ppm/ppm.dart'; +// import '../../../new_views/app_style/app_color.dart'; +// import '../../../new_views/common_widgets/app_text_form_field.dart'; +// import '../../../new_views/common_widgets/default_app_bar.dart'; +// import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +// import '../../widgets/e_signature/e_signature.dart'; +// import '../../widgets/timer/app_timer.dart'; +// +// class UpdateDeviceTransfer extends StatefulWidget { +// final AssetTransfer model; +// final bool isSender; +// +// const UpdateDeviceTransfer({Key? key, required this.model, required this.isSender}) : super(key: key); +// +// @override +// State createState() => _UpdateDeviceTransferState(); +// } +// +// class _UpdateDeviceTransferState extends State { +// final bool _isLoading = false; +// bool _validate = false; +// late UserProvider _userProvider; +// late SettingProvider _settingProvider; +// Uint8List? _signature; +// late AssetTransferProvider _deviceTransferProvider; +// final TextEditingController _requestedQuantityController = TextEditingController(); +// final AssetTransfer _formModel = AssetTransfer(); +// final GlobalKey _formKey = GlobalKey(); +// final GlobalKey _scaffoldKey = GlobalKey(); +// +// List _files = []; +// +// _update() async { +// if (widget.isSender) { +// _formModel.senderVisitTimers?.add( +// VisitTimers( +// id: 0, +// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), +// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), +// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), +// ), +// ); +// } else { +// _formModel.receiverVisitTimers?.add( +// VisitTimers( +// id: 0, +// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), +// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), +// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), +// ), +// ); +// } +// +// if (_formModel.tbsTimer?.startAt == null) { +// await Fluttertoast.showToast(msg: "Working Hours Required"); +// return false; +// } +// if (_formModel.tbsTimer?.endAt == null || isTimerRunning) { +// await Fluttertoast.showToast(msg: "Please Stop The Timer"); +// return false; +// } +// _validate = true; +// if (!(_formKey.currentState!.validate())) { +// setState(() {}); +// return false; +// } +// _formKey.currentState!.save(); +// +// if (widget.isSender) { +// _formModel.senderAttachments = []; +// } else { +// _formModel.receiverAttachments = []; +// } +// +// try { +// for (var file in _files) { +// String attachmentName = file.path; +// if (attachmentName.contains("/")) { +// attachmentName = file.path.split("/").last; +// attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; +// } +// +// if (widget.isSender) { +// _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); +// } else { +// _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); +// } +// } +// } catch (error) { +// print(error); +// } +// await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender); +// } +// +// @override +// void initState() { +// _formModel.fromDetails(widget.model); +// +// if (widget.isSender) { +// _files = widget.model.senderAttachments?.map((e) => File(e.attachmentName!)).toList() ?? []; +// } else { +// _files = widget.model.receiverAttachments?.map((e) => File(e.attachmentName!)).toList() ?? []; +// } +// +// super.initState(); +// } +// +// @override +// void dispose() { +// _requestedQuantityController.dispose(); +// super.dispose(); +// } +// +// bool isTimerRunning = false; +// +// @override +// Widget build(BuildContext context) { +// _userProvider = Provider.of(context); +// _settingProvider = Provider.of(context); +// _deviceTransferProvider = Provider.of(context, listen: false); +// +// double totalWorkingHours = widget.isSender +// ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0) +// : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0); +// +// bool isTimerEnable = widget.isSender +// ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) +// : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); +// +// return Scaffold( +// appBar: DefaultAppBar(title: context.translation.updateRequest), +// key: _scaffoldKey, +// body: SafeArea( +// child: LoadingManager( +// isLoading: _isLoading, +// isFailedLoading: false, +// stateCode: 200, +// onRefresh: () async {}, +// child: Form( +// key: _formKey, +// child: Column( +// children: [ +// SingleChildScrollView( +// padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: [ +// _buildCard(), +// 8.height, +// AppTextFormField( +// initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", +// labelText: context.translation.travelingHours, +// onChange: (text) { +// widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; +// }, +// onSaved: (value) { +// widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; +// //_formModel?.workingHours = double.tryParse(value); +// // _formModel.travelingHours = value; +// }, +// textInputType: TextInputType.number, +// //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", +// ), +// 8.height, +// if (totalWorkingHours > 0.0) ...[ +// Container( +// height: 50.toScreenHeight, +// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), +// alignment: Alignment.centerLeft, +// decoration: BoxDecoration( +// color: context.isDark ? AppColor.neutral40 : AppColor.background(context), +// borderRadius: BorderRadius.circular(10), +// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Text( +// "Total Working Time", +// style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), +// ), +// Text( +// " ${formatDuration(totalWorkingHours.round())}", +// style: Theme.of(context).textTheme.bodyLarge, +// ), +// ], +// ), +// ), +// 8.height, +// ], +// AppTimer( +// label: context.translation.workingHours, +// timer: _formModel.tbsTimer, +// enabled: isTimerEnable, +// // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), +// timerProgress: (isRunning) { +// isTimerRunning = isRunning; +// }, +// onChange: (timer) async { +// _formModel.tbsTimer = timer; +// return true; +// }, +// ), +// 8.height, +// Consumer(builder: (context, snapshot, _) { +// return SingleItemDropDownMenu( +// context: context, +// title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, +// initialValue: +// snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null), +// onSelect: (value) { +// if (value?.value == 4) { +// "Status cannot be change to ${value?.name}.".addTranslation.showToast; +// setState(() {}); +// return; +// } +// if (widget.isSender) { +// _formModel.senderMachineStatusName = value?.name; +// _formModel.senderMachineStatusId = value?.id; +// } else { +// _formModel.receiverMachineStatusName = value?.name; +// _formModel.receiverMachineStatusId = value?.id; +// } +// setState(() {}); +// }, +// ); +// }), +// 8.height, +// MultiFilesPicker(label: context.translation.attachImage, files: _files), +// 8.height, +// AppTextFormField( +// initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", +// labelText: context.translation.comments, +// textInputType: TextInputType.multiline, +// alignLabelWithHint: true, +// onSaved: (value) { +// widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; +// }, +// ), +// 8.height, +// ESignature( +// title: "Signature", +// oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, +// newSignature: _signature, +// onSaved: (signature) { +// _signature = signature; +// if (signature == null || signature.isEmpty) return; +// widget.isSender +// ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" +// : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; +// }, +// ), +// ], +// ), +// ).expanded, +// Padding( +// padding: const EdgeInsets.all(16.0), +// child: AppFilledButton( +// label: context.translation.update, +// onPressed: _update, +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ); +// } +// +// _buildCard() { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// context.translation.transferDetails.heading5(context), +// 8.height, +// '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), +// '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), +// ], +// ).toShadowContainer(context); +// } +// +// String formatDuration(int seconds) { +// int hours = seconds ~/ 3600; +// int minutes = (seconds % 3600) ~/ 60; +// int remainingSeconds = seconds % 60; +// +// String formattedDuration = ''; +// if (hours > 0) { +// formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; +// } +// if (minutes > 0) { +// formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; +// } +// if (remainingSeconds > 0) { +// formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; +// } +// if (formattedDuration.isEmpty) { +// formattedDuration = 'Less than a second'; +// } +// +// return formattedDuration.trim(); +// } +// } + +//.....new design.. + import 'dart:convert'; import 'dart:io'; @@ -14,11 +346,18 @@ import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/device/asset_transfer_attachment.dart'; +import 'package:test_sa/models/new_models/work_order_detail_model.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; +import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; import '../../../extensions/text_extensions.dart'; import '../../../models/lookup.dart'; @@ -167,114 +506,132 @@ class _UpdateDeviceTransferState extends State { SingleChildScrollView( padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _buildCard(), - 8.height, - AppTextFormField( - initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", - labelText: context.translation.travelingHours, - onChange: (text) { - widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; - }, - onSaved: (value) { - widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; - //_formModel?.workingHours = double.tryParse(value); - // _formModel.travelingHours = value; - }, - textInputType: TextInputType.number, - //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", - ), - 8.height, - if (totalWorkingHours > 0.0) ...[ - Container( - height: 50.toScreenHeight, - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // _buildCard(), + // 8.height, + // AppTextFormField( + // initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", + // labelText: context.translation.travelingHours, + // onChange: (text) { + // widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; + // }, + // onSaved: (value) { + // widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; + // //_formModel?.workingHours = double.tryParse(value); + // // _formModel.travelingHours = value; + // }, + // textInputType: TextInputType.number, + // //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + // ), + // 8.height, + // if (totalWorkingHours > 0.0) ...[ + // Container( + // height: 50.toScreenHeight, + // padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + // alignment: Alignment.centerLeft, + // decoration: BoxDecoration( + // color: context.isDark ? AppColor.neutral40 : AppColor.background(context), + // borderRadius: BorderRadius.circular(10), + // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + // ), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // "Total Working Time", + // style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + // ), + // Text( + // " ${formatDuration(totalWorkingHours.round())}", + // style: Theme.of(context).textTheme.bodyLarge, + // ), + // ], + // ), + // ), + // 8.height, + // ], + + _timerWidget(context, totalWorkingHours, isTimerEnable), + 8.height, + AppTextFormField( + initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + backgroundColor: AppColor.neutral100, + showShadow: false, + alignLabelWithHint: true, + onSaved: (value) { + widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; + }, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Total Working Time", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - ), - Text( - " ${formatDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyLarge, - ), - ], + // AppTimer( + // label: context.translation.workingHours, + // timer: _formModel.tbsTimer, + // enabled: isTimerEnable, + // // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), + // timerProgress: (isRunning) { + // isTimerRunning = isRunning; + // }, + // onChange: (timer) async { + // _formModel.tbsTimer = timer; + // return true; + // }, + // ), + // 8.height, + // Consumer(builder: (context, snapshot, _) { + // return SingleItemDropDownMenu( + // context: context, + // title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, + // initialValue:snapshot.items.isNotEmpty? + // snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null):null, + // onSelect: (value) { + // if (value?.value == 4) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // if (widget.isSender) { + // _formModel.senderMachineStatusName = value?.name; + // _formModel.senderMachineStatusId = value?.id; + // } else { + // _formModel.receiverMachineStatusName = value?.name; + // _formModel.receiverMachineStatusId = value?.id; + // } + // setState(() {}); + // }, + // ); + // }), + 8.height, + MultiFilesPicker( + label: context.translation.attachFiles, + files: _files, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), - ), - 8.height, - ], - AppTimer( - label: context.translation.workingHours, - timer: _formModel.tbsTimer, - enabled: isTimerEnable, - // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), - timerProgress: (isRunning) { - isTimerRunning = isRunning; - }, - onChange: (timer) async { - _formModel.tbsTimer = timer; - return true; - }, - ), - 8.height, - Consumer(builder: (context, snapshot, _) { - return SingleItemDropDownMenu( - context: context, - title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, - initialValue: - snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null), - onSelect: (value) { - if (value?.value == 4) { - "Status cannot be change to ${value?.name}.".addTranslation.showToast; - setState(() {}); - return; - } - if (widget.isSender) { - _formModel.senderMachineStatusName = value?.name; - _formModel.senderMachineStatusId = value?.id; - } else { - _formModel.receiverMachineStatusName = value?.name; - _formModel.receiverMachineStatusId = value?.id; - } - setState(() {}); - }, - ); - }), - 8.height, - MultiFilesPicker(label: context.translation.attachImage, files: _files), - 8.height, - AppTextFormField( - initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", - labelText: context.translation.comments, - textInputType: TextInputType.multiline, - alignLabelWithHint: true, - onSaved: (value) { - widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; - }, - ), - 8.height, - ESignature( - title: "Signature", - oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, - newSignature: _signature, - onSaved: (signature) { - _signature = signature; - if (signature == null || signature.isEmpty) return; - widget.isSender - ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" - : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), + 8.height, + + // 8.height, + // ESignature( + // title: "Signature", + // oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, + // newSignature: _signature, + // onSaved: (signature) { + // _signature = signature; + // if (signature == null || signature.isEmpty) return; + // widget.isSender + // ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" + // : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // }, + // ), + ], + ).toShadowContainer(context), + 16.height, + const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)), ], ), ).expanded, @@ -293,6 +650,15 @@ class _UpdateDeviceTransferState extends State { ); } + void updateTimer({TimerModel? timer}) { + _formModel.tbsTimer = timer; + if (timer?.startAt != null && timer?.endAt != null) { + _formModel.timerModelList = _formModel.timerModelList ?? []; + _formModel.timerModelList!.add(timer!); + } + // notifyListeners(); + } + _buildCard() { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -305,6 +671,44 @@ class _UpdateDeviceTransferState extends State { ).toShadowContainer(context); } + Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTimer( + label: context.translation.workingHours, + timer: _formModel.tbsTimer, + width: double.infinity, + enabled: isTimerEnable, + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + ), + timerProgress: (isRunning) {}, + onChange: (timer) async { + updateTimer(timer: timer); + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120), + 8.width, + Text( + ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), + style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), + ), + ], + ), + ], + ], + ); + } + String formatDuration(int seconds) { int hours = seconds ~/ 3600; int minutes = (seconds % 3600) ~/ 60; @@ -327,3 +731,226 @@ class _UpdateDeviceTransferState extends State { return formattedDuration.trim(); } } + +class AssistantEmployeeCard extends StatefulWidget { + const AssistantEmployeeCard({super.key}); + + @override + State createState() => _AssistantEmployeeCardState(); +} + +class _AssistantEmployeeCardState extends State { + bool status = false; + final TextEditingController _workingHoursController = TextEditingController(text: ''); + bool isCurrentUserIsAssistantEmp = false; + bool isExpanded = false; + + @override + void initState() { + // TODO: implement initState + WidgetsBinding.instance.addPostFrameCallback((_) { + getInitialData(); + }); + super.initState(); + } + + Future getInitialData() async { + final user = Provider.of(context, listen: false).user!; + ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); + + // if (isCurrentUserIsAssistantEmp) { + // // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; + // } + } + + @override + void dispose() { + // TODO: implement dispose + _workingHoursController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, requestDetailProvider, child) { + return Column( + children: [ + SizedBox( + height: 56.toScreenHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10), + Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), + ], + ), + ).onPress(() { + setState(() { + isExpanded = !isExpanded; + }); + }), + isExpanded + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ServiceReportAssistantEmployeeMenu( + title: context.translation.select, + backgroundColor: AppColor.neutral100, + // assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!, + // initialValue: (requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.isNotEmpty ?? false) + // ? requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.first + // : null, + + initialValue: null, + assetId: 23, + //TODO add check... + // enable: !isCurrentUserIsAssistantEmp, + onSelect: (employee) { + if (employee == null) { + requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = []; + } else { + requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [employee.copyWith(id: 0)]; + requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; + }); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null && + selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; + }); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null + ? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString() + : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; + }, + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; + }, + ), + 16.height, + ], + ) + : const SizedBox(), + ], + ); + }); + } + +// //TODO move this to some common place....@waseem +// double calculateWorkingHours(DateTime? startTime, DateTime? endTime) { +// if (startTime != null && endTime != null) { +// Duration difference = endTime.difference(startTime); +// int hours = difference.inHours; +// int minutes = difference.inMinutes % 60; +// return hours.toDouble(); +// } else { +// return -1; +// } +// } +// +// assignWorkingHours({required RequestDetailProvider requestDetailProvider}) { +// double hours = calculateWorkingHours( +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate); +// if (hours != -1) { +// _workingHoursController.text = hours.toString(); +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours = hours; +// } +// } +} diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index b341c310..237618e3 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -7,6 +7,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/widget_extensions.dart'; +import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; @@ -143,7 +144,7 @@ class _GasRefillDetailsPageState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => RequestGasRefill(gasRefillModel: gasRefillModel), + builder: (context) => GasRefillForm(gasRefillModel: gasRefillModel), ), ).then((value) { if (value != null) { @@ -239,3 +240,6 @@ class _GasRefillDetailsPageState extends State { } } + + + diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart new file mode 100644 index 00000000..a9077510 --- /dev/null +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -0,0 +1,424 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; +import 'package:test_sa/controllers/providers/api/gas_refill_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/controllers/validator/validator.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/widget_extensions.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/timer_model.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/providers/loading_list_notifier.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + +import '../../../../controllers/providers/api/hospitals_provider.dart'; +import '../../../../extensions/text_extensions.dart'; +import '../../../../models/new_models/gas_refill_model.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../providers/gas_request_providers/gas_status_provider.dart'; +import '../../../widgets/e_signature/e_signature.dart'; +import '../../../widgets/timer/app_timer.dart'; + +class GasRefillForm extends StatefulWidget { + static const String id = "/gas-refill-form"; + final GasRefillModel? gasRefillModel; + + const GasRefillForm({this.gasRefillModel, Key? key}) : super(key: key); + + @override + State createState() => _GasRefillFormState(); +} + +class _GasRefillFormState extends State { + final bool _isLoading = false; + bool _validate = false; + Uint8List? _engineerSignature; + Uint8List? _nurseSignature; + double totalWorkingHours = 0.0; + + late UserProvider _userProvider; + late SettingProvider _settingProvider; + GasRefillProvider? _gasRefillProvider; + GasRefillDetails _currentDetails = GasRefillDetails(); + final TextEditingController _deliveredQuantityController = TextEditingController(); + final TextEditingController _commentController = TextEditingController(); + final TextEditingController _workingHoursController = TextEditingController(); + + final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _DetailsKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + bool _firstTime = true; + + Lookup? _deliveredQuantity; + + static List deliveredQuantity = [ + Lookup(name: "1", id: 1, value: 1), + Lookup(name: "2", id: 2, value: 2), + Lookup(name: "3", id: 3, value: 3), + Lookup(name: "4", id: 4, value: 4), + Lookup(name: "5", id: 5, value: 5) + ]; + + @override + void initState() { + super.initState(); + _gasRefillProvider ??= Provider.of(context, listen: false); + + if (widget.gasRefillModel != null) { + _formModel.fromGasRefillModel(widget.gasRefillModel!); + + // totalWorkingHours = + // _formModel?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; + + _commentController.text = _formModel.comment ?? ""; + try { + _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty); + _currentDetails.deliverdQty = _deliveredQuantity!.value; + } catch (ex) {} + } + if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) { + _gasRefillProvider?.gasRefillAttachments = []; + _gasRefillProvider?.gasRefillAttachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList()); + } + } + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(() {}); + } + + _onSubmit(BuildContext context) async { + if (_formModel.status == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.status}"); + return false; + } + if (_formModel.timer?.startAt == null) { + await Fluttertoast.showToast(msg: "Working Hours Required"); + return false; + } + if (_formModel.timer?.endAt == null) { + await Fluttertoast.showToast(msg: "Please Stop The Timer"); + return false; + } + if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { + if (!(await _addNewModel(context))) return; + } + + //TODO need to check when added in backend.... + _formModel.gasRefillTimer = _formModel.gasRefillTimer ?? []; + _formModel.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + _formModel.gasRefillTimer?.add( + GasRefillTimer( + id: 0, + startTime: timer.startAt!.toIso8601String(), // Handle potential null + endTime: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + + _formModel.gasRefillAttachments = []; + for (var item in _gasRefillProvider!.gasRefillAttachments) { + _formModel.gasRefillAttachments + ?.add(GasRefillAttachments(id: 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + } + + //..till here... + + setState(() {}); + _formKey.currentState!.save(); + _formModel.comment = _commentController.text; + int? status = widget.gasRefillModel == null + ? 0 /*await _gasRefillProvider.createModel( + user: _userProvider.user, + model: _formModel, + )*/ + : await _gasRefillProvider!.updateModel( + user: _userProvider.user!, + host: _settingProvider.host!, + oldModel: widget.gasRefillModel!, + newModel: _formModel, + ); + //_isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast( + msg: context.translation.successfulRequestMessage, + ); + Navigator.of(context).pop(_formModel); + setState(() {}); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + } + + bool _addNewModel(BuildContext context) { + _validate = true; + if (_currentDetails.deliverdQty == null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}"); + setState(() {}); + return false; + } + // if (!_formKey.currentState!.validate()) { + // setState(() {}); + // return false; + // } + _formKey.currentState!.save(); + _currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; + _currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; + _currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; + _currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; + if (!(_currentDetails.validate(context))) { + setState(() {}); + return false; + } + _formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; + _validate = false; + // Scrollable.ensureVisible(_DetailsKey.currentContext); + _deliveredQuantityController.clear(); + _workingHoursController.clear(); + //_commentController.clear(); + _currentDetails = GasRefillDetails(); + setState(() {}); + return true; + } + + @override + void dispose() { + _deliveredQuantityController.dispose(); + _commentController.dispose(); + _workingHoursController.dispose(); + super.dispose(); + } + + void updateTimer({TimerModel? timer}) { + _formModel.timer = timer; + if (timer?.startAt != null && timer?.endAt != null) { + _formModel.timerModelList = _formModel.timerModelList ?? []; + _formModel.timerModelList!.add(timer!); + } + // notifyListeners(); + } + + @override + Widget build(BuildContext context) { + _userProvider = Provider.of(context); + _settingProvider = Provider.of(context); + if (_firstTime) { + String? clientName; + if (widget.gasRefillModel != null) { + //_formModel.status = widget.gasRefillModel?.status ?? Lookup(value: 0); + _gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? ""); + _formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? "")); + clientName = _formModel.site?.custName; + } else { + _formModel.timer = null; + clientName = _userProvider.user?.clientName; + } + + HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { + _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null); + _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null); + _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null); + _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null); + _firstTime = false; + setState(() {}); + }); + } + return Scaffold( + appBar: DefaultAppBar(title: context.translation.gasRefill), + key: _scaffoldKey, + body: Form( + key: _formKey, + child: SafeArea( + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // context.translation.gasRefill.heading5(context), + // 8.height, + // '${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), + // '${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), + // '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), + // '${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + // '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), + // ], + // ).toShadowContainer(context), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.quantity, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: _deliveredQuantity, + staticData: deliveredQuantity, + onSelect: (value) { + _deliveredQuantity = value; + _currentDetails.deliverdQty = value!.value; + }, + ), + 8.height, + _timerWidget(context, _formModel.workingHours ?? 0), + 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: context.translation.requestStatus, + // initialValue: _formModel.status, + // onSelect: (value) { + // if (value?.value == 0) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // if (value != null) { + // _formModel.status = value; + // } + // }, + // ), + // 8.height, + + // 8.height, + // AppTextFormField( + // initialValue: _formModel.gazRefillDetails?[0].deliverdQty?.toString() ?? "", + // labelText: context.translation.deliveredQuantity, + // onSaved: (value) { + // _currentDetails.deliverdQty = double.tryParse(value); + // }, + // textInputType: TextInputType.number, + // controller: _deliveredQuantityController, + // validator: (value) => value == null || value.isEmpty + // ? context.translation.requiredField + // : Validator.isNumeric(value) + // ? null + // : context.translation.onlyNumbers, + // ), + 8.height, + + /// TBD + AppTextFormField( + labelText: context.translation.technicalComment, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + controller: _commentController, + onSaved: (value) {}, + ), + 16.height, + MultiFilesPicker( + label: context.translation.attachFiles, + files: _gasRefillProvider!.gasRefillAttachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + 8.height, + // ESignature( + // title: "Engineer Signature", + // oldSignature: widget.gasRefillModel?.engSignature, + // newSignature: _engineerSignature, + // onSaved: (signature) { + // _engineerSignature = signature; + // if (signature == null || signature.isEmpty) return; + // _formModel.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // //base64Encode(signature); + // }, + // ), + // 8.height, + // ESignature( + // title: "Nurse Signature", + // oldSignature: widget.gasRefillModel?.nurseSignature, + // newSignature: _nurseSignature, + // onSaved: (signature) { + // _nurseSignature = signature; + // if (signature == null || signature.isEmpty) return; + // _formModel.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // //base64Encode(signature); + // }, + // ), + ], + ).toShadowContainer(context), + ).expanded, + AppFilledButton( + label: widget.gasRefillModel == null ? context.translation.submit : context.translation.update, + onPressed: () async { + _onSubmit.call(context); + }, + ).paddingAll(16), + ], + )), + ), + ), + ); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTimer( + label: context.translation.workingHours, + timer: _formModel.timer, + //TODO need to fix this.. + // enabled: _formModel.endDate == null, + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + ), + timerProgress: (isRunning) {}, + onChange: (timer) async { + updateTimer(timer: timer); + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120), + 8.width, + Text( + ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), + style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), + ), + ], + ), + ], + ], + ); + } +} diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart index fc3ffc94..87854a46 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; @@ -93,6 +95,7 @@ class _PpmPMKitsFormState extends State { onPick: (part) { model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); setState(() {}); + print('part number i got is ${model.partCatalogItem?.partNumber}'); }, ), 8.height, diff --git a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart index e4c4760b..b81dc60e 100644 --- a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart @@ -56,7 +56,6 @@ class _WoInfoFormState extends State { double totalWorkingHours = widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; - totalWorkingHours = totalWorkingHours; return Consumer(builder: (context, ppmProvider, child) { return ListView( diff --git a/lib/views/widgets/parts/auto_complete_parts_field.dart b/lib/views/widgets/parts/auto_complete_parts_field.dart index 1ce09558..bf9703cf 100644 --- a/lib/views/widgets/parts/auto_complete_parts_field.dart +++ b/lib/views/widgets/parts/auto_complete_parts_field.dart @@ -32,6 +32,7 @@ class _AutoCompletePartsFieldState extends State { @override void initState() { + print('initial value i got is ${widget.initialValue}'); _controller = TextEditingController(text: widget.initialValue); super.initState(); } From f06426091b993b60af653b61be3102447f2f7b6b Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 27 Feb 2025 11:11:28 +0300 Subject: [PATCH 02/36] room null value issue fixed in recurrent task --- .../recurrent_wo/components/task_info_widget.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index ad99c375..ee5f5ef5 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -50,11 +50,11 @@ class RecurrentTaskInfoWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.department, value: model!.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.floor, value: model!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.room, value: model!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, _timerWidget(context, model!.totalWorkingHours!) ], @@ -106,7 +106,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { } } -Widget buildingInfoWidget({required String label, required String value, required BuildContext context}) { +Widget buildingInfoWidget({required String label, required String ?value, required BuildContext context}) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -118,7 +118,7 @@ Widget buildingInfoWidget({required String label, required String value, require ), 3.height, Text( - value, + value??'', style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), ) ], From 152a0795c6f9822bf645029aada3f4352f6d2105 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Tue, 4 Mar 2025 11:35:39 +0300 Subject: [PATCH 03/36] add and update gas refill ui and api integrated --- lib/controllers/api_routes/urls.dart | 6 +- .../providers/api/gas_refill_provider.dart | 45 +-- lib/models/new_models/gas_refill_model.dart | 327 ++++++++++-------- .../pages/new_gas_refill_request_page.dart | 322 ++++++++++------- .../user/gas_refill/gas_refill_details.dart | 80 ++--- .../user/gas_refill/gas_refill_form.dart | 197 +++++------ .../user/gas_refill/request_gas_refill.dart | 24 +- .../widgets/gas_refill/gas_refill_item.dart | 2 +- 8 files changed, 533 insertions(+), 470 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index a31b4426..365d8966 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -167,12 +167,14 @@ class URLs { static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // get - static get requestGasRefill => "$_baseUrl/GazRefill/AddGazRefill"; // get + static get requestGasRefill => "$_baseUrl/GasRefill/AddGasRefillFromMobile"; // get static get updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // get - static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get + // static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get older endpoint.. + static get getGasRefillById => "$_baseUrl/GasRefill/GetGasRefillById"; // get static get getGazRefillComments => "$_baseUrl/GazRefill/GetHistoryComments"; // get static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add + static get updateGasRefillByEngineer => "$_baseUrl/GasRefill/UpdateGasRefillByEngineer"; // update //device transfer static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index bab1b5d2..d71e45dc 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -28,6 +28,7 @@ class GasRefillProvider extends ChangeNotifier { building = null; floor = null; department = null; + gasRefillAttachments.clear(); } // state code of current request to defied error message @@ -58,10 +59,11 @@ class GasRefillProvider extends ChangeNotifier { Future getGasRefillObjectById(num id) async { try { - Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gazRefillId=$id"); + Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id"); if (response.statusCode >= 200 && response.statusCode < 300) { - return GasRefillModel.fromJson(json.decode(response.body)["data"]); + + return GasRefillModel.fromJson(json.decode(response.body)["data"]); } else { return null; } @@ -70,14 +72,6 @@ class GasRefillProvider extends ChangeNotifier { } } - // void updateRecurrentWoTimer({TimerModel? timer}) { - // recurrentWoData?.recurrentWoTimerModel = timer; - // if (timer?.startAt != null && timer?.endAt != null) { - // recurrentWoData?.timerModelList = recurrentWoData?.timerModelList ?? []; - // recurrentWoData?.timerModelList!.add(timer!); - // } - // notifyListeners(); - // } /// return -2 if request in progress /// return -1 if error happen when sending request @@ -126,20 +120,14 @@ class GasRefillProvider extends ChangeNotifier { } } - Future createModel({ + Future addGasRefillRequest({ required BuildContext context, - required User user, required GasRefillModel model, }) async { late Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - final Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - }; - body.addAll(model.toJson()); - response = await ApiManager.instance.post(URLs.requestGasRefill, body: body); + response = await ApiManager.instance.post(URLs.requestGasRefill, body: model.toJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { if (items != null) { @@ -158,6 +146,23 @@ class GasRefillProvider extends ChangeNotifier { } } + Future updateGasRefill({required int status, required GasRefillModel model}) async { + isLoading = true; + Response response; + try { + response = await ApiManager.instance.post(URLs.updateGasRefillByEngineer, body: model.toUpdateEngineerPayload(status: status)); + stateCode = response.statusCode; + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } + Future updateModel({ required String host, required User user, @@ -166,7 +171,7 @@ class GasRefillProvider extends ChangeNotifier { }) async { Map body = { "id": newModel.id, - "gazRefillNo": newModel.gazRefillNo ?? "", + "gasRefillNo": newModel.gasRefillNo ?? "", "status": newModel.status?.toJson(), //"expectedDate": newModel.expectedDate?.toIso8601String(), "expectedTime": newModel.expectedDate, @@ -185,7 +190,7 @@ class GasRefillProvider extends ChangeNotifier { "comment": newModel.comment, }; - body["gazRefillDetails"] = newModel.gazRefillDetails! + body["gasRefillDetails"] = newModel.gasRefillDetails! .map((model) => { "gasType": model.gasType?.toJson(), "cylinderSize": model.cylinderSize?.toJson(), diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 140e68a9..0750dd33 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -12,42 +12,77 @@ import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/timer_model.dart'; class GasRefillModel { - GasRefillModel( - {this.id, - this.gazRefillNo, - this.expectedDate, - this.expectedTime, - this.startDate, - this.startTime, - this.endDate, - this.endTime, - this.engSignature, - this.nurseSignature, - this.workingHours, - this.extensionNo, - this.employeeId, - this.name, - this.createdDate, - this.site, - this.building, - this.floor, - this.department, - this.assignedEmployee, - this.status, - this.comment, - this.gazRefillDetails, - this.localEngineerSignature, - this.localNurseSignature, - this.timer, - this.timerModelList, - this.gasRefillTimer, - this.gasRefillAttachments, + GasRefillModel({ + this.id, + this.gasRefillNo, + this.expectedDate, + this.expectedTime, + this.startDate, + this.startTime, + this.endDate, + this.endTime, + this.engSignature, + this.nurseSignature, + this.workingHours, + this.extensionNo, + this.employeeId, + this.name, + this.createdDate, + this.site, + this.building, + this.floor, + this.department, + this.assignedEmployee, + this.status, + this.comment, + this.techComment, + this.gasRefillDetails, + this.localEngineerSignature, + this.localNurseSignature, + this.timer, + this.timerModelList, + this.gasRefillTimers, + this.gasRefillAttachments, + this.statusValue, + }); - }); + num? id; // Now nullable + String? gasRefillNo; // Now nullable + String? expectedDate; // Now nullable + String? expectedTime; // Now nullable + String? startDate; // Now nullable + String? startTime; // Now nullable + String? endDate; // Now nullable + String? endTime; // Now nullable + String? engSignature; // Now nullable + String? nurseSignature; // Now nullable + double? workingHours; + dynamic extensionNo; + String? employeeId; + String? name; + String? createdDate; + Site? site; // Now nullable + Building? building; // Now nullable + Floor? floor; // Now nullable + Department? department; // Now nullable + AssignedEmployee? assignedEmployee; // Now nullable + Lookup? status; // Now nullable + String? comment; // Now nullable + String? techComment; // Now nullable + List? gasRefillDetails; // Now nullable + Uint8List? localNurseSignature; // Now nullable + Uint8List? localEngineerSignature; // Now nullable + TimerModel? timer; + + //TODO need to check when api provided.. + List? timerModelList = []; + List? gasRefillTimers = []; + List? gasRefillAttachments; + int? statusValue; GasRefillModel.fromJson(dynamic json) { id = json['id']; - gazRefillNo = json['gazRefillNo']; + gasRefillNo = json['gasRefillNo']; expectedDate = json['expectedDate']; expectedTime = json['expectedTime']; startDate = json['startDate']; @@ -55,18 +90,19 @@ class GasRefillModel { endDate = json['endDate']; endTime = json['endTime']; comment = json['comment']; + techComment = json['techComment']; workingHours = json['workingHours']; extensionNo = json['extensionNo']; employeeId = json['employeeId']; name = json['name']; createdDate = json['createdDate']; - //TODO need to use this when added from backend... - if (json['gasRefillTimer'] != null) { - gasRefillTimer = []; - json['gasRefillTimer'].forEach((v) { - gasRefillTimer?.add(GasRefillTimer.fromJson(v)); + if (json['gasRefillTimers'] != null) { + gasRefillTimers = []; + json['gasRefillTimers'].forEach((v) { + gasRefillTimers?.add(GasRefillTimer.fromJson(v)); }); - workingHours = json['gasRefillTimer'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDateTime']).difference(DateTime.parse(item['startDateTime'])).inSeconds) ?? 0; + workingHours = json['gasRefillTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDate']).difference(DateTime.parse(item['startDate'])).inSeconds) ?? 0; + } if (json['gasRefillAttachments'] != null) { gasRefillAttachments = []; @@ -75,23 +111,23 @@ class GasRefillModel { }); } - try { - final DateTime? sd = DateTime.tryParse(startDate ?? ""); - final DateTime? st = DateTime.tryParse(startTime ?? ""); - final DateTime? ed = DateTime.tryParse(endDate ?? ""); - final DateTime? et = DateTime.tryParse(endTime ?? ""); - timer = TimerModel( - startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd' - endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed' - ); - if (timer!.endAt != null && timer!.startAt != null) { - // Use '!' since timer could be null after initialization - timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; - workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); - } - } catch (e) { - print(e); - } + // try { + // final DateTime? sd = DateTime.tryParse(startDate ?? ""); + // final DateTime? st = DateTime.tryParse(startTime ?? ""); + // final DateTime? ed = DateTime.tryParse(endDate ?? ""); + // final DateTime? et = DateTime.tryParse(endTime ?? ""); + // timer = TimerModel( + // startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd' + // endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed' + // ); + // if (timer!.endAt != null && timer!.startAt != null) { + // // Use '!' since timer could be null after initialization + // timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; + // workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); + // } + // } catch (e) { + // print(e); + // } engSignature = json['engSignature']; nurseSignature = json['nurseSignature']; site = json['site'] != null ? Site.fromJson(json['site']) : null; @@ -100,96 +136,93 @@ class GasRefillModel { department = json['department'] != null ? Department.fromJson(json['department']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; status = json['status'] != null ? Lookup.fromJson(json['status']) : null; - if (json['gazRefillDetails'] != null) { - gazRefillDetails = []; - json['gazRefillDetails'].forEach((v) { - gazRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gazRefillDetails is initialized here + if (json['gasRefillDetails'] != null) { + gasRefillDetails = []; + json['gasRefillDetails'].forEach((v) { + gasRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gasRefillDetails is initialized here }); } } - num? id; // Now nullable - String? gazRefillNo; // Now nullable - String? expectedDate; // Now nullable - String? expectedTime; // Now nullable - String? startDate; // Now nullable - String? startTime; // Now nullable - String? endDate; // Now nullable - String? endTime; // Now nullable - String? engSignature; // Now nullable - String? nurseSignature; // Now nullable - double? workingHours; - dynamic extensionNo; - String? employeeId; - String? name; - String? createdDate; - Site? site; // Now nullable - Building? building; // Now nullable - Floor? floor; // Now nullable - Department? department; // Now nullable - AssignedEmployee? assignedEmployee; // Now nullable - Lookup? status; // Now nullable - String? comment; // Now nullable - List? gazRefillDetails; // Now nullable - Uint8List? localNurseSignature; // Now nullable - Uint8List? localEngineerSignature; // Now nullable - TimerModel? timer; - //TODO need to check when api provided.. - List? timerModelList = []; - List? gasRefillTimer = []; - List? gasRefillAttachments; - - - Map toJson() { final map = {}; map['id'] = id ?? 0; - map['gazRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; - map['expectedDate'] = expectedDate; - map['expectedTime'] = expectedTime; - map['startDate'] = startDate; - map['startTime'] = startTime; - map['endDate'] = endDate; - map['endTime'] = endTime; - map['engSignature'] = engSignature; - map['nurseSignature'] = nurseSignature; - map['workingHours'] = workingHours; - map['extensionNo'] = extensionNo; - map['employeeId'] = employeeId; - map['name'] = name; - map['createdDate'] = createdDate; - map['comment'] = comment; - //TODO need to check parameters here ... - if (gasRefillTimer != null) { - map['gasRefillTimer'] = gasRefillTimer?.map((v) => v.toJson()).toList(); - } - if (gasRefillAttachments != null) { - map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); - } - + map['gasTypeId'] = gasRefillDetails?[0].gasType?.id; + map['cylinderTypeId'] = gasRefillDetails?[0].cylinderType?.id; + map['cylinderSizeId'] = gasRefillDetails?[0].cylinderSize?.id; + map['requestedQty'] = gasRefillDetails?[0].requestedQty; if (site != null) { - map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety + map['siteId'] = site?.id; // Use '?.' for null safety } if (building != null) { - map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety + map['buildingId'] = building?.id; // Use '?.' for null safety } if (floor != null) { - map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety + map['floorId'] = floor?.id; // Use '?.' for null safety } if (department != null) { - map['department'] = department?.toJson(); // Use '?.' for null safety + map['departmentId'] = department?.id; // Use '?.' for null safety } - if (assignedEmployee != null) { - map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety + map['comment'] = comment; + + if (gasRefillAttachments != null) { + map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); } - if (status != null) { - map['status'] = status?.toJson(); // Use '?.' for null safety + + //older code..... + // map['gasRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; + // map['expectedTime'] = expectedTime; + // + // map['startDate'] = startDate; + // map['startTime'] = startTime; + // map['endDate'] = endDate; + // map['endTime'] = endTime; + // map['engSignature'] = engSignature; + // map['nurseSignature'] = nurseSignature; + // map['workingHours'] = workingHours; + // map['extensionNo'] = extensionNo; + // map['employeeId'] = employeeId; + // map['name'] = name; + // map['createdDate'] = createdDate; + // map['comment'] = comment; + // if (site != null) { + // map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety + // } + // if (building != null) { + // map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety + // } + // if (floor != null) { + // map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety + // } + // if (department != null) { + // map['department'] = department?.toJson(); // Use '?.' for null safety + // } + // if (assignedEmployee != null) { + // map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety + // } + // if (status != null) { + // map['status'] = status?.toJson(); // Use '?.' for null safety + // } + // if (gasRefillDetails != null) { + // map['gasRefillDetails'] = gasRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gasRefillDetails could be null + // } + + return map; + } + + Map toUpdateEngineerPayload({required int status}) { + final map = {}; + map['id'] = id ?? 0; + map['deliveredQty'] = gasRefillDetails?[0].deliverdQty; + map['statusValue'] = status; + map['techComment'] = techComment; + if (gasRefillTimers != null) { + map['gasRefillTimers'] = gasRefillTimers?.map((v) => v.toJson()).toList(); } - if (gazRefillDetails != null) { - map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null + if (gasRefillAttachments != null) { + map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); } - return map; } @@ -214,9 +247,9 @@ class GasRefillModel { id = model.id; //userId = model.userId; site = model.site; - gazRefillNo = model.gazRefillNo; + gasRefillNo = model.gasRefillNo; status = Lookup.fromStatus(model.status); - gazRefillDetails = model.gazRefillDetails; + gasRefillDetails = model.gasRefillDetails; building = model.building; floor = model.floor; department = model.department; @@ -233,12 +266,13 @@ class GasRefillModel { extensionNo = model.extensionNo; employeeId = model.employeeId; name = model.name; + techComment = model.techComment; createdDate = model.createdDate; } GasRefillModel copyWith({ num? id, // Parameters are now nullable - String? gazRefillNo, + String? gasRefillNo, String? expectedDate, String? expectedTime, String? startDate, @@ -259,14 +293,13 @@ class GasRefillModel { AssignedEmployee? assignedEmployee, Lookup? status, String? comment, - List? gazRefillDetails, + List? gasRefillDetails, List? gasRefillTimer, TimerModel? timer, - }) => GasRefillModel( id: id ?? this.id, - gazRefillNo: gazRefillNo ?? this.gazRefillNo, + gasRefillNo: gasRefillNo ?? this.gasRefillNo, expectedDate: expectedDate ?? this.expectedDate, expectedTime: expectedTime ?? this.expectedTime, startDate: startDate ?? this.startDate, @@ -283,9 +316,9 @@ class GasRefillModel { assignedEmployee: assignedEmployee ?? this.assignedEmployee, status: status ?? this.status, comment: comment ?? this.comment, - gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails, + gasRefillDetails: gasRefillDetails ?? this.gasRefillDetails, timer: timer ?? this.timer, - gasRefillTimer : gasRefillTimer ?? this.gasRefillTimer, + gasRefillTimers: gasRefillTimer ?? this.gasRefillTimers, ); } @@ -369,51 +402,51 @@ class GasRefillDetails { } return true; } - } class GasRefillTimer { int? id; - String? startTime; - String? endTime; + String? startDate; + String? endDate; dynamic workingHours; - GasRefillTimer({this.id, this.startTime, this.endTime, this.workingHours}); + GasRefillTimer({this.id, this.startDate, this.endDate, this.workingHours}); GasRefillTimer.fromJson(Map json) { id = json['id']; - startTime = json['startDateTime']; - endTime = json['endDateTime']; - workingHours = json['workingHour']; + startDate = json['startDate']; + endDate = json['endDate']; + workingHours = json['workingHours']; } Map toJson() { final Map data = {}; data['id'] = id; - data['startDateTime'] = startTime; - data['endDateTime'] = endTime; - data['workingHour'] = workingHours; + data['startDate'] = startDate; + data['endDate'] = endDate; + data['workingHours'] = workingHours; return data; } } class GasRefillAttachments { int? id; + num? gasRefillId; String? attachmentName; - GasRefillAttachments({this.id, this.attachmentName}); + GasRefillAttachments({this.id, this.attachmentName, this.gasRefillId}); GasRefillAttachments.fromJson(Map json) { id = json['id']; + gasRefillId = json['gasRefillId']; attachmentName = json['attachmentName']; } Map toJson() { final Map data = {}; data['id'] = id; + data['gasRefillId'] = gasRefillId; data['attachmentName'] = attachmentName; return data; } } - - diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index b5f5d0fb..d778d5ce 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -1,7 +1,9 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.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'; @@ -21,9 +23,11 @@ import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.d 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/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import '../../controllers/providers/api/gas_refill_provider.dart'; -import '../../controllers/validator/validator.dart'; import '../common_widgets/default_app_bar.dart'; class NewGasRefillRequestPage extends StatefulWidget { @@ -39,6 +43,8 @@ class _NewGasRefillRequestPageState extends State { late GasRefillDetails _currentDetails; late GasRefillModel _gasModel; Lookup? _requestedQuantity; + final TextEditingController _commentController = TextEditingController(); + GasRefillProvider? _gasRefillProvider; static List gasQuantity = [ Lookup(name: "1", id: 1, value: 1), @@ -51,8 +57,11 @@ class _NewGasRefillRequestPageState extends State { @override void initState() { super.initState(); + _gasRefillProvider ??= Provider.of(context, listen: false); + _gasModel =GasRefillModel(); _currentDetails = GasRefillDetails(); - _gasModel = GasRefillModel(gazRefillDetails: []); + _gasModel = GasRefillModel(gasRefillDetails: []); + _gasRefillProvider!.gasRefillAttachments.clear(); } @override @@ -66,35 +75,28 @@ class _NewGasRefillRequestPageState extends State { appBar: DefaultAppBar(title: context.translation.newGasRefillRequest), body: Column( children: [ + 12.height, SingleChildScrollView( child: Column( children: [ - 16.height, SingleItemDropDownMenu( context: context, title: context.translation.gasType, initialValue: _currentDetails.gasType, + backgroundColor: AppColor.neutral100, + showShadow: false, showAsBottomSheet: true, onSelect: (value) { _currentDetails.gasType = value; }, ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.quantity, - initialValue: _requestedQuantity, - staticData: gasQuantity, - onSelect: (value) { - _requestedQuantity = value; - _currentDetails.requestedQty = value?.value; - }, - ), - 8.height, SingleItemDropDownMenu( context: context, title: context.translation.cylinderType, initialValue: _currentDetails.cylinderType, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { _currentDetails.cylinderType = value; }, @@ -105,136 +107,153 @@ class _NewGasRefillRequestPageState extends State { title: context.translation.cylinderSize, initialValue: _currentDetails.cylinderSize, showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { _currentDetails.cylinderSize = value; }, ), 8.height, - SingleItemDropDownMenu( + SingleItemDropDownMenu( context: context, - title: context.translation.site, - initialValue: _gasModel.site, + title: context.translation.quantity, showAsBottomSheet: true, + initialValue: _requestedQuantity, + staticData: gasQuantity, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { - setState(() { - _gasModel.site = value; - _gasModel.building = null; - _gasModel.floor = null; - _gasModel.department = null; - }); + _requestedQuantity = value; + _currentDetails.requestedQty = value?.value; }, ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.building, - initialValue: _gasModel.building, - enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, - staticData: _gasModel.site?.buildings ?? [], - showAsBottomSheet: true, - onSelect: (value) { - setState(() { - _gasModel.building = value; - _gasModel.floor = null; - _gasModel.department = null; - }); - }, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.site, + initialValue: _gasModel.site, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.site = value; + _gasModel.building = null; + _gasModel.floor = null; + _gasModel.department = null; + }); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.building, + initialValue: _gasModel.building, + enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, + staticData: _gasModel.site?.buildings ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.building = value; + _gasModel.floor = null; + _gasModel.department = null; + }); + }, + ).expanded, + ], ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.floor, - initialValue: _gasModel.floor, - enabled: _gasModel.building?.floors?.isNotEmpty ?? false, - staticData: _gasModel.building?.floors ?? [], - showAsBottomSheet: true, - onSelect: (value) { - setState(() { - _gasModel.floor = value; - _gasModel.department = null; - }); - }, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.floor, + initialValue: _gasModel.floor, + enabled: _gasModel.building?.floors?.isNotEmpty ?? false, + staticData: _gasModel.building?.floors ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.floor = value; + _gasModel.department = null; + }); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.department, + initialValue: _gasModel.department, + enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, + staticData: _gasModel.floor?.departments ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + _gasModel.department = value; + }, + ).expanded, + ], ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.department, - initialValue: _gasModel.department, - enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, - staticData: _gasModel.floor?.departments ?? [], - showAsBottomSheet: true, - onSelect: (value) { - _gasModel.department = value; + AppTextFormField( + labelText: context.translation.callComments, + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120), + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + controller: _commentController, + onChange: (value){ + _gasModel.comment = value; }, + onSaved: (value) {}, ), 8.height, - if (_gasModel.gazRefillDetails?.isEmpty ?? true) - AppFilledButton( - label: context.translation.add, - maxWidth: true, - textColor: Colors.white, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, - onPressed: _add, - ), - ListView.builder( - shrinkWrap: true, - itemCount: _gasModel.gazRefillDetails?.length, - padding: const EdgeInsets.only(top: 12, bottom: 24), - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (_gasModel.gazRefillDetails![index].gasType?.name ?? "").heading5(context), - 8.height, - ("${context.translation.quantity}: ${_gasModel.gazRefillDetails![index].requestedQty}").bodyText(context), - ("${context.translation.cylinderSize}: ${_gasModel.gazRefillDetails![index].cylinderSize?.name}").bodyText(context), - ("${context.translation.cylinderType}: ${_gasModel.gazRefillDetails![index].cylinderType?.name}").bodyText(context), - ], - ), - Container( - height: 48.toScreenWidth, - width: 48.toScreenWidth, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30), - ), - padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), - child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50), - ).onPress(() { - _delete(index); - }), - ], - ), - const Divider().defaultStyle(context), - ("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context), - ("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context), - ("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context), - ("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context), - ], - ).toShadowContainer(context); - }, + MultiFilesPicker( + label: context.translation.attachFiles, + files: _gasRefillProvider!.gasRefillAttachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), ], - ), + ).toShadowContainer(context, padding: 10).paddingOnly(start: 16, end: 16, top: 16), ).expanded, 16.height, - AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit), + FooterActionButton.footerContainer(child: AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit)), ], - ).paddingOnly(start: 16, end: 16, bottom: 24), + ), + ); + } + + Future _submit() async { + if (_currentDetails.gasType==null) { + Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); + return; + } + _gasModel.gasRefillDetails=[]; + _gasModel.gasRefillDetails?.add(_currentDetails); + _gasModel.gasRefillAttachments = []; + for (var item in _gasRefillProvider!.gasRefillAttachments) { + _gasModel.gasRefillAttachments?.add(GasRefillAttachments( + id: 0, gasRefillId: _gasModel.id ?? 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + } + await _gasRefillProvider?.addGasRefillRequest( + context: context, + model: _gasModel, ); } void _add() async { if (_currentDetails.validate(context) && _gasModel.validate(context)) { - _gasModel.gazRefillDetails!.add(_currentDetails); + _gasModel.gasRefillDetails!.add(_currentDetails); _currentDetails = GasRefillDetails(); _requestedQuantity = null; setState(() {}); @@ -242,19 +261,62 @@ class _NewGasRefillRequestPageState extends State { } void _delete(index) { - _gasModel.gazRefillDetails!.remove(_gasModel.gazRefillDetails![index]); + _gasModel.gasRefillDetails!.remove(_gasModel.gasRefillDetails![index]); setState(() {}); } - - Future _submit() async { - if (_gasModel.gazRefillDetails?.isEmpty ?? true) { - Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); - return; - } - await Provider.of(context, listen: false).createModel( - context: context, - user: Provider.of(context, listen: false).user!, - model: _gasModel, - ); - } +//older code.... +// if (_gasModel.gasRefillDetails?.isEmpty ?? true) +// AppFilledButton( +// label: context.translation.add, +// maxWidth: true, +// textColor: Colors.white, +// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, +// onPressed: _add, +// ), +// ListView.builder( +// shrinkWrap: true, +// itemCount: _gasModel.gasRefillDetails?.length, +// padding: const EdgeInsets.only(top: 12, bottom: 24), +// physics: const NeverScrollableScrollPhysics(), +// itemBuilder: (context, index) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// (_gasModel.gasRefillDetails![index].gasType?.name ?? "").heading5(context), +// 8.height, +// ("${context.translation.quantity}: ${_gasModel.gasRefillDetails![index].requestedQty}").bodyText(context), +// ("${context.translation.cylinderSize}: ${_gasModel.gasRefillDetails![index].cylinderSize?.name}").bodyText(context), +// ("${context.translation.cylinderType}: ${_gasModel.gasRefillDetails![index].cylinderType?.name}").bodyText(context), +// ], +// ), +// Container( +// height: 48.toScreenWidth, +// width: 48.toScreenWidth, +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(100), +// border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30), +// ), +// padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), +// child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50), +// ).onPress(() { +// _delete(index); +// }), +// ], +// ), +// const Divider().defaultStyle(context), +// ("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context), +// ("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context), +// ("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context), +// ("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context), +// ], +// ).toShadowContainer(context); +// }, +// ), } diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index 237618e3..c35e71f6 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -7,6 +7,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/widget_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; @@ -31,7 +32,7 @@ class GasRefillDetailsPage extends StatefulWidget { } class _GasRefillDetailsPageState extends State { - GasRefillModel _model = GasRefillModel(gazRefillDetails: []); + GasRefillModel _model = GasRefillModel(gasRefillDetails: []); late UserProvider _userProvider; late GasRefillProvider gasRefillProvider; final bool _isLoading = false; @@ -69,6 +70,14 @@ class _GasRefillDetailsPageState extends State { padding: const EdgeInsets.all(16), child: informationCard(_model), ).expanded, + if (_userProvider.user!.type == UsersTypes.engineer && (_model.status!.id! != 5833))//TODO need to check this value for complete status. + AppFilledButton( + onPressed: () async { + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => GasRefillForm(gasRefillModel: _model))); + // getVisitData(); + }, + label: context.translation.updateRequest, + ).paddingAll(16) ], ); } @@ -110,21 +119,21 @@ class _GasRefillDetailsPageState extends State { context.translation.gasRefillRequest.heading5(context), 8.height, - '${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails![0].gasType?.name}'.bodyText(context), - '${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails![0].cylinderType?.name}'.bodyText(context), - '${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails![0].cylinderSize?.name}'.bodyText(context), + '${context.translation.gasRequest}: ${gasRefillModel.gasRefillDetails![0].gasType?.name}'.bodyText(context), + '${context.translation.cylinderType}: ${gasRefillModel.gasRefillDetails![0].cylinderType?.name}'.bodyText(context), + '${context.translation.cylinderSize}: ${gasRefillModel.gasRefillDetails![0].cylinderSize?.name}'.bodyText(context), '${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.requestNo}: ${gasRefillModel.gazRefillNo}'.bodyText(context), + '${context.translation.requestNo}: ${gasRefillModel.gasRefillNo}'.bodyText(context), //TODO need to confirm where to display this new data... - infoText(label:context.translation.gasRequest ,value:gasRefillModel.extensionNo ), - infoText(label:context.translation.employeeId ,value:gasRefillModel.employeeId ), - infoText(label:context.translation.name ,value:gasRefillModel.name ), - infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), + infoText(label: context.translation.gasRequest, value: gasRefillModel.extensionNo), + infoText(label: context.translation.employeeId, value: gasRefillModel.employeeId), + infoText(label: context.translation.name, value: gasRefillModel.name), + infoText(label: context.translation.createdDate, value: gasRefillModel.createdDate?.toInitialVisitCardFormat), const Divider().defaultStyle(context), - '${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), - '${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), + '${context.translation.requestedQuantity}: ${gasRefillModel.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + '${context.translation.deliveredQuantity}: ${gasRefillModel.gasRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), 8.height, if (gasRefillModel.comment?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), @@ -133,34 +142,11 @@ class _GasRefillDetailsPageState extends State { ] ], ).expanded, - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) - "edit".toSvgAsset(height: 48, width: 48).onPress( - () async { - _model.fromGasRefillModel(gasRefillModel); - // setState(() {}); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => GasRefillForm(gasRefillModel: gasRefillModel), - ), - ).then((value) { - if (value != null) { - _model = value; - setState(() {}); - } - }); - }, - ), - if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, - Text( - (widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "", - textAlign: TextAlign.end, - style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), - ), - ], + if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, + Text( + (widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), ), ], ).paddingOnly(top: 16, start: 16, end: 16), @@ -230,16 +216,14 @@ class _GasRefillDetailsPageState extends State { ).toShadowContainer(context, padding: 0); } - Widget infoText({String ?label,String ?value,}){ - if(value==null||value.isEmpty){ - return const SizedBox(); - } - else { + Widget infoText({ + String? label, + String? value, + }) { + if (value == null || value.isEmpty) { + return const SizedBox(); + } else { return '$label: $value'.bodyText(context); } - } } - - - diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart index a9077510..a03281e2 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_form.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -6,6 +7,7 @@ import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; @@ -18,8 +20,10 @@ import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/timer_model.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_lazy_loading.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; @@ -58,7 +62,7 @@ class _GasRefillFormState extends State { final TextEditingController _commentController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController(); - final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); + final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []); final GlobalKey _formKey = GlobalKey(); final GlobalKey _DetailsKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); @@ -85,9 +89,9 @@ class _GasRefillFormState extends State { // totalWorkingHours = // _formModel?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; - _commentController.text = _formModel.comment ?? ""; + _commentController.text = _formModel.techComment ?? ""; try { - _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty); + _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); _currentDetails.deliverdQty = _deliveredQuantity!.value; } catch (ex) {} } @@ -102,11 +106,8 @@ class _GasRefillFormState extends State { if (mounted) super.setState(() {}); } - _onSubmit(BuildContext context) async { - if (_formModel.status == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.status}"); - return false; - } + _onSubmit(BuildContext context,int status) async { + if (_formModel.timer?.startAt == null) { await Fluttertoast.showToast(msg: "Working Hours Required"); return false; @@ -115,92 +116,50 @@ class _GasRefillFormState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { - if (!(await _addNewModel(context))) return; + if(_currentDetails.deliverdQty==null){ + await Fluttertoast.showToast(msg: "Delivered Quantity is Required"); + return false; } + _formModel.gasRefillDetails=[]; + _formModel.gasRefillDetails?.add(_currentDetails); + + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + _formModel.gasRefillTimers = _formModel.gasRefillTimers ?? []; - //TODO need to check when added in backend.... - _formModel.gasRefillTimer = _formModel.gasRefillTimer ?? []; _formModel.timerModelList?.forEach((timer) { int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; - _formModel.gasRefillTimer?.add( + _formModel.gasRefillTimers?.add( GasRefillTimer( id: 0, - startTime: timer.startAt!.toIso8601String(), // Handle potential null - endTime: timer.endAt?.toIso8601String(), // Handle potential null + startDate: timer.startAt!.toIso8601String(), // Handle potential null + endDate: timer.endAt?.toIso8601String(), // Handle potential null workingHours: ((durationInSecond) / 60 / 60), ), ); }); - _formModel.gasRefillAttachments = []; for (var item in _gasRefillProvider!.gasRefillAttachments) { _formModel.gasRefillAttachments - ?.add(GasRefillAttachments(id: 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + ?.add(GasRefillAttachments(id: 0,gasRefillId: _formModel.id??0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); } + await _gasRefillProvider + ?.updateGasRefill( + status: status, + model: _formModel + ) + .whenComplete(() { + if (status == 1) { + AllRequestsProvider allRequestsProvider = Provider.of(context,listen: false); + // when click complete then this request remove from the list and status changes to closed.. + _gasRefillProvider?.reset(); + allRequestsProvider.getAllRequests(context, typeTransaction: 2); + } + Navigator.pop(context); + Navigator.pop(context); + }); - //..till here... - - setState(() {}); - _formKey.currentState!.save(); - _formModel.comment = _commentController.text; - int? status = widget.gasRefillModel == null - ? 0 /*await _gasRefillProvider.createModel( - user: _userProvider.user, - model: _formModel, - )*/ - : await _gasRefillProvider!.updateModel( - user: _userProvider.user!, - host: _settingProvider.host!, - oldModel: widget.gasRefillModel!, - newModel: _formModel, - ); - //_isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: context.translation.successfulRequestMessage, - ); - Navigator.of(context).pop(_formModel); - setState(() {}); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } } - bool _addNewModel(BuildContext context) { - _validate = true; - if (_currentDetails.deliverdQty == null) { - Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}"); - setState(() {}); - return false; - } - // if (!_formKey.currentState!.validate()) { - // setState(() {}); - // return false; - // } - _formKey.currentState!.save(); - _currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; - _currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; - _currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; - _currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; - if (!(_currentDetails.validate(context))) { - setState(() {}); - return false; - } - _formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; - _validate = false; - // Scrollable.ensureVisible(_DetailsKey.currentContext); - _deliveredQuantityController.clear(); - _workingHoursController.clear(); - //_commentController.clear(); - _currentDetails = GasRefillDetails(); - setState(() {}); - return true; - } @override void dispose() { @@ -235,14 +194,14 @@ class _GasRefillFormState extends State { clientName = _userProvider.user?.clientName; } - HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { - _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null); - _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null); - _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null); - _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null); - _firstTime = false; - setState(() {}); - }); + // HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { + // _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null); + // _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null); + // _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null); + // _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null); + // _firstTime = false; + // setState(() {}); + // }); } return Scaffold( appBar: DefaultAppBar(title: context.translation.gasRefill), @@ -268,10 +227,10 @@ class _GasRefillFormState extends State { // children: [ // context.translation.gasRefill.heading5(context), // 8.height, - // '${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), - // '${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), - // '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), - // '${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + // '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context), + // '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context), + // '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context), + // '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), // '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), // ], // ).toShadowContainer(context), @@ -289,6 +248,21 @@ class _GasRefillFormState extends State { }, ), 8.height, + // AppTextFormField( + // initialValue: _formModel.gasRefillDetails?[0].deliverdQty?.toString() ?? "", + // labelText: context.translation.deliveredQuantity, + // onSaved: (value) { + // _currentDetails.deliverdQty = double.tryParse(value); + // }, + // textInputType: TextInputType.number, + // controller: _deliveredQuantityController, + // validator: (value) => value == null || value.isEmpty + // ? context.translation.requiredField + // : Validator.isNumeric(value) + // ? null + // : context.translation.onlyNumbers, + // ), + // 8.height, _timerWidget(context, _formModel.workingHours ?? 0), 8.height, // SingleItemDropDownMenu( @@ -309,21 +283,7 @@ class _GasRefillFormState extends State { // 8.height, // 8.height, - // AppTextFormField( - // initialValue: _formModel.gazRefillDetails?[0].deliverdQty?.toString() ?? "", - // labelText: context.translation.deliveredQuantity, - // onSaved: (value) { - // _currentDetails.deliverdQty = double.tryParse(value); - // }, - // textInputType: TextInputType.number, - // controller: _deliveredQuantityController, - // validator: (value) => value == null || value.isEmpty - // ? context.translation.requiredField - // : Validator.isNumeric(value) - // ? null - // : context.translation.onlyNumbers, - // ), - 8.height, + /// TBD AppTextFormField( @@ -333,6 +293,9 @@ class _GasRefillFormState extends State { backgroundColor: AppColor.neutral100, showShadow: false, controller: _commentController, + onChange: (value){ + _formModel.techComment = value; + }, onSaved: (value) {}, ), 16.height, @@ -370,12 +333,26 @@ class _GasRefillFormState extends State { ], ).toShadowContainer(context), ).expanded, - AppFilledButton( - label: widget.gasRefillModel == null ? context.translation.submit : context.translation.update, - onPressed: () async { - _onSubmit.call(context); - }, - ).paddingAll(16), + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _onSubmit(context, 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _onSubmit(context, 1), + ).expanded, + ], + ), + ), + ], )), ), diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index 462e30c7..a802ef50 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -53,7 +53,7 @@ class _RequestGasRefillState extends State { final TextEditingController _commentController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController(); - final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); + final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []); final GlobalKey _formKey = GlobalKey(); final GlobalKey _DetailsKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); @@ -77,7 +77,7 @@ class _RequestGasRefillState extends State { _formModel.fromGasRefillModel(widget.gasRefillModel!); _commentController.text = _formModel.comment ?? ""; try { - _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty); + _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); _currentDetails.deliverdQty = _deliveredQuantity!.value; } catch (ex) {} } @@ -101,7 +101,7 @@ class _RequestGasRefillState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { + if (_formModel.gasRefillDetails?.isNotEmpty ?? false) { if (!(await _addNewModel(context))) return; } @@ -147,15 +147,15 @@ class _RequestGasRefillState extends State { // return false; // } _formKey.currentState!.save(); - _currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; - _currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; - _currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; - _currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; + _currentDetails.gasType = _formModel.gasRefillDetails![0].gasType; + _currentDetails.cylinderSize = _formModel.gasRefillDetails![0].cylinderSize; + _currentDetails.cylinderType = _formModel.gasRefillDetails![0].cylinderType; + _currentDetails.requestedQty = _formModel.gasRefillDetails![0].requestedQty; if (!( _currentDetails.validate(context))) { setState(() {}); return false; } - _formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; + _formModel.gasRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; _validate = false; // Scrollable.ensureVisible(_DetailsKey.currentContext); _deliveredQuantityController.clear(); @@ -225,10 +225,10 @@ class _RequestGasRefillState extends State { children: [ context.translation.gasRefill.heading5(context), 8.height, - '${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), - '${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), - '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), - '${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context), + '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context), + '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context), + '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), ], ).toShadowContainer(context), diff --git a/lib/views/widgets/gas_refill/gas_refill_item.dart b/lib/views/widgets/gas_refill/gas_refill_item.dart index 4cf4af7d..e8551865 100644 --- a/lib/views/widgets/gas_refill/gas_refill_item.dart +++ b/lib/views/widgets/gas_refill/gas_refill_item.dart @@ -41,7 +41,7 @@ class GasRefillItem extends StatelessWidget { ), 8.height, context.translation.gasRefillRequest.heading5(context), - '${context.translation.gasType}: ${item.gazRefillDetails![0].gasType!.name}'.bodyText(context), + '${context.translation.gasType}: ${item.gasRefillDetails![0].gasType!.name}'.bodyText(context), '${context.translation.site}: ${item.site!.name}'.bodyText(context), 8.height, Row( From 289d06ff6894019e9da962cb99bb35fe60ea89be Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 6 Mar 2025 12:16:21 +0300 Subject: [PATCH 04/36] Asset transfer nurse side ui completed --- lib/main.dart | 4 +- .../app_floating_action_button.dart | 4 +- .../create_request-type_bottomsheet.dart | 4 +- .../create__asset_transfer_request.dart | 322 ++++++++++++++++++ .../request_device_transfer.dart | 211 ------------ lib/views/pages/user/land_page.dart | 2 +- lib/views/widgets/equipment/asset_picker.dart | 18 +- 7 files changed, 342 insertions(+), 223 deletions(-) create mode 100644 lib/views/pages/device_transfer/create__asset_transfer_request.dart delete mode 100644 lib/views/pages/device_transfer/request_device_transfer.dart diff --git a/lib/main.dart b/lib/main.dart index 7c9425f6..59c05001 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -68,7 +68,7 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart'; -import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; @@ -305,7 +305,7 @@ class MyApp extends StatelessWidget { // PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), PpmPage.id: (_) => const PpmPage(), TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), - RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), + CreateAssetTransferRequest.id: (_) => const CreateAssetTransferRequest(), TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), // todo remove this class after work diff --git a/lib/new_views/common_widgets/app_floating_action_button.dart b/lib/new_views/common_widgets/app_floating_action_button.dart index 29f9892b..bdf4499f 100644 --- a/lib/new_views/common_widgets/app_floating_action_button.dart +++ b/lib/new_views/common_widgets/app_floating_action_button.dart @@ -9,7 +9,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; -import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart'; import '../app_style/app_color.dart'; @@ -40,7 +40,7 @@ class _AppFloatingActionButtonState extends State { final elements = [ if (user.type == UsersTypes.normal_user) fabItem(context.translation.gasRefillRequest, "gas_refill_request", NewGasRefillRequestPage.routeName), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), - if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", RequestDeviceTransfer.id), + if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", CreateAssetTransferRequest.id), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id), ]; 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 87206116..21745e18 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,7 +5,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; -import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; class CreateRequestTypeBottomSheet extends StatelessWidget { const CreateRequestTypeBottomSheet({super.key}); @@ -49,7 +49,7 @@ class CreateRequestTypeBottomSheet extends StatelessWidget { icon: 'add_icon', label: context.translation.deviceTransfer, onTap: () async { - Navigator.pushReplacementNamed(context, RequestDeviceTransfer.id); + Navigator.pushReplacementNamed(context, CreateAssetTransferRequest.id); }, ), ], diff --git a/lib/views/pages/device_transfer/create__asset_transfer_request.dart b/lib/views/pages/device_transfer/create__asset_transfer_request.dart new file mode 100644 index 00000000..d65537ff --- /dev/null +++ b/lib/views/pages/device_transfer/create__asset_transfer_request.dart @@ -0,0 +1,322 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_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/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/models/device/asset_transfer.dart'; +import 'package:test_sa/models/employee.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/department.dart'; +import 'package:test_sa/models/new_models/floor.dart'; +import 'package:test_sa/models/new_models/room_model.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import 'package:test_sa/views/widgets/status/employee/nurse_menu.dart'; + +import '../../../models/new_models/building.dart'; +import '../../../models/new_models/site.dart'; +import '../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../providers/gas_request_providers/site_provider.dart'; +import '../../../providers/loading_list_notifier.dart'; +import '../../widgets/equipment/pick_asset.dart'; + +class CreateAssetTransferRequest extends StatefulWidget { + static const String id = "/request-device-transfer"; + + const CreateAssetTransferRequest({Key? key}) : super(key: key); + + @override + State createState() => _CreateAssetTransferRequestState(); +} + +class _CreateAssetTransferRequestState extends State { + UserProvider? _userProvider; + SettingProvider? _settingProvider; + late AssetTransferProvider _deviceTransferProvider; + final TextEditingController _requestedQuantityController = TextEditingController(); + final AssetTransfer _transferModel = AssetTransfer(); + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController(); + final Asset _assetDestination = Asset(); + Asset? _pickedAsset; + Employee? receiverEndUser; + Employee? _selectedNurse; + final List _deviceImages = []; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(() {}); + } +//TODO need to clean the extra logic and code when finilize api from backend.. + void _onSubmit() async { + _transferModel.assetId = _pickedAsset?.id; + _transferModel.destSiteId = _assetDestination.site?.id; + _transferModel.destBuildingId = _assetDestination.building?.id; + _transferModel.destFloorId = _assetDestination.floor?.id; + _transferModel.destDepartmentId = _assetDestination.department?.id; + _transferModel.destRoomId = _assetDestination.room?.id; + _transferModel.receiverEndUserId = _selectedNurse?.id; + + if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) { + return; + } + _formKey.currentState!.save(); + // List attachement = []; + // for (var item in _deviceImages) { + // attachement.add(WorkOrderAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}")); + // } + + await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset!); + } + + List requestType = [ + Lookup(name: 'Internal', value: 1), + Lookup(name: 'External', value: 2), + ]; + + @override + void initState() { + // TODO: need to check parameter with backend. + // _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList()); + super.initState(); + } + + Lookup selectedRequestType = Lookup(name: 'Internal', value: 1); + + @override + void dispose() { + _requestedQuantityController.dispose(); + _deviceTransferProvider.reset(); + _receiverNameController.dispose(); + _commentsController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _userProvider = Provider.of(context, listen: false); + _settingProvider = Provider.of(context, listen: false); + _deviceTransferProvider = Provider.of(context, listen: false); + return Scaffold( + key: _scaffoldKey, + appBar: DefaultAppBar(title: context.translation.newTransferRequest), + body: Form( + key: _formKey, + child: SafeArea( + child: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 16.height, + // PickAsset( + // device: _pickedAsset, + // onPickAsset: (asset) { + // _pickedAsset = asset; + // setState(() {}); + // }, + // ), + AssetPicker( + device: _pickedAsset, + showLoading: false, + borderColor: AppColor.black20, + backgroundColor: AppColor.white936, + onPick: (asset) async { + _pickedAsset = asset; + setState(() {}); + // pendingAssetServiceRequest = null; + // _serviceRequest.device = asset; + // await checkAssetForPendingServiceRequest(asset.id!.toInt()); + // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + // showPendingRequestBottomSheet(); + }), + 21.height, + context.translation.requestType.bodyText(context).custom(color: AppColor.white936), + 10.height, + Wrap( + runSpacing: 8, + spacing: 20, + children: [ + for (var element in requestType) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: AppColor.primary10, + fillColor: WidgetStateColor.resolveWith((states) { + if (states.contains(WidgetState.selected)) { + return AppColor.primary10; // Thumb color when selected + } + return Colors.grey; // Thumb color when unselected (grey) + }), + groupValue: selectedRequestType, + onChanged: (state) { + setState(() { + selectedRequestType = element; + }); + }), + ), + 8.width, + Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)), + ], + ) + ], + ), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.site, + initialValue: _assetDestination.site, + showShadow: false, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + onSelect: (value) { + _assetDestination.site = value; + _assetDestination.building = null; + _assetDestination.floor = null; + _assetDestination.department = null; + _selectedNurse = null; + Provider.of(context, listen: false).siteId = value!.id!.toInt(); + Provider.of(context, listen: false).getData(); + setState(() {}); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.building, + initialValue: _assetDestination.building, + showShadow: false, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false, + staticData: _assetDestination.site?.buildings ?? [], + onSelect: (value) { + _assetDestination.building = value; + _assetDestination.floor = null; + _assetDestination.department = null; + setState(() {}); + }, + ).expanded, + ], + ), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.floor, + showShadow: false, + initialValue: _assetDestination.floor, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.building?.floors?.isNotEmpty ?? false, + staticData: _assetDestination.building?.floors ?? [], + onSelect: (value) { + _assetDestination.floor = value; + _assetDestination.department = null; + setState(() {}); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.department, + showShadow: false, + initialValue: _assetDestination.department, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false, + staticData: _assetDestination.floor?.departments ?? [], + onSelect: (value) { + _assetDestination.department = value; + _assetDestination.room = null; + setState(() {}); + }, + ).expanded, + ], + ), + 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: context.translation.room, + // initialValue: _assetDestination.room, + // backgroundColor:AppColor.neutral100, + // enabled: _assetDestination.department?.rooms?.isNotEmpty ?? false, + // staticData: _assetDestination.department?.rooms ?? [], + // onSelect: (value) { + // _assetDestination.room = value; + // setState(() {}); + // }, + // ), + // 8.height, + // NurseMenu( + // title: context.translation.receiverName, + // initialValue: _selectedNurse, + // + // enable: _assetDestination.site != null, + // onSelect: (employee) { + // if (employee != null) { + // _selectedNurse = employee; + // setState(() {}); + // } + // }, + // ), + // 16.height, + AppTextFormField( + controller: _commentsController, + backgroundColor: AppColor.neutral100, + labelText: context.translation.callComments, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + showShadow: false, + onSaved: (text) { + _transferModel.comment = text; + }, + ), + 8.height, + 23.height, + MultiFilesPicker( + label: context.translation.attachImage, + files: _deviceImages, + buttonColor: AppColor.black10, + onlyImages: true, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + // 100.height, + ], + ).toShadowContainer(context).paddingOnly(top: 20, start: 16, end: 16), + ).expanded, + FooterActionButton.footerContainer( + child: AppFilledButton(buttonColor: AppColor.primary10, label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit + // buttonColor: AppColor.primary10, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/device_transfer/request_device_transfer.dart b/lib/views/pages/device_transfer/request_device_transfer.dart deleted file mode 100644 index ea7ccb03..00000000 --- a/lib/views/pages/device_transfer/request_device_transfer.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_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/text_extensions.dart'; -import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/device/asset.dart'; -import 'package:test_sa/models/device/asset_transfer.dart'; -import 'package:test_sa/models/employee.dart'; -import 'package:test_sa/models/new_models/department.dart'; -import 'package:test_sa/models/new_models/floor.dart'; -import 'package:test_sa/models/new_models/room_model.dart'; -import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; -import 'package:test_sa/views/widgets/status/employee/nurse_menu.dart'; - -import '../../../models/new_models/building.dart'; -import '../../../models/new_models/site.dart'; -import '../../../new_views/common_widgets/app_filled_button.dart'; -import '../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../../providers/gas_request_providers/site_provider.dart'; -import '../../../providers/loading_list_notifier.dart'; -import '../../widgets/equipment/pick_asset.dart'; - -class RequestDeviceTransfer extends StatefulWidget { - static const String id = "/request-device-transfer"; - - const RequestDeviceTransfer({Key? key}) : super(key: key); - - @override - State createState() => _RequestDeviceTransferState(); -} - -class _RequestDeviceTransferState extends State { - UserProvider? _userProvider; - SettingProvider? _settingProvider; - late AssetTransferProvider _deviceTransferProvider; - final TextEditingController _requestedQuantityController = TextEditingController(); - final AssetTransfer _transferModel = AssetTransfer(); - final GlobalKey _formKey = GlobalKey(); - final GlobalKey _scaffoldKey = GlobalKey(); - final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController(); - final Asset _assetDestination = Asset(); - Asset? _pickedAsset; - Employee? receiverEndUser; - Employee? _selectedNurse; - - @override - void setState(VoidCallback fn) { - if (mounted) super.setState(() {}); - } - - void _onSubmit() async { - _transferModel.assetId = _pickedAsset?.id; - _transferModel.destSiteId = _assetDestination.site?.id; - _transferModel.destBuildingId = _assetDestination.building?.id; - _transferModel.destFloorId = _assetDestination.floor?.id; - _transferModel.destDepartmentId = _assetDestination.department?.id; - _transferModel.destRoomId = _assetDestination.room?.id; - _transferModel.receiverEndUserId = _selectedNurse?.id; - if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) { - return; - } - _formKey.currentState!.save(); - await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset!); - } - - @override - void dispose() { - _requestedQuantityController.dispose(); - _deviceTransferProvider.reset(); - _receiverNameController.dispose(); - _commentsController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - _userProvider = Provider.of(context, listen: false); - _settingProvider = Provider.of(context, listen: false); - _deviceTransferProvider = Provider.of(context, listen: false); - // _selectedNurse ??= Employee(id: _userProvider.user.userID, name: _userProvider.user.username); - - return Scaffold( - key: _scaffoldKey, - appBar: DefaultAppBar(title: context.translation.newTransferRequest), - body: Form( - key: _formKey, - child: SafeArea( - child: Column( - children: [ - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 16.height, - PickAsset( - device: _pickedAsset, - onPickAsset: (asset) { - _pickedAsset = asset; - setState(() {}); - }, - ), - 16.height, - context.translation.receiverDetails.heading5(context), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.destinationSite, - initialValue: _assetDestination.site, - onSelect: (value) { - _assetDestination.site = value; - _assetDestination.building = null; - _assetDestination.floor = null; - _assetDestination.department = null; - _selectedNurse = null; - Provider.of(context, listen: false).siteId = value!.id!.toInt(); - Provider.of(context, listen: false).getData(); - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.building, - initialValue: _assetDestination.building, - enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false, - staticData: _assetDestination.site?.buildings ?? [], - onSelect: (value) { - _assetDestination.building = value; - _assetDestination.floor = null; - _assetDestination.department = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.floor, - initialValue: _assetDestination.floor, - enabled: _assetDestination.building?.floors?.isNotEmpty ?? false, - staticData: _assetDestination.building?.floors ?? [], - onSelect: (value) { - _assetDestination.floor = value; - _assetDestination.department = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.department, - initialValue: _assetDestination.department, - enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false, - staticData: _assetDestination.floor?.departments ?? [], - onSelect: (value) { - _assetDestination.department = value; - _assetDestination.room = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.room, - initialValue: _assetDestination.room, - enabled: _assetDestination.department?.rooms?.isNotEmpty ?? false, - staticData: _assetDestination.department?.rooms ?? [], - onSelect: (value) { - _assetDestination.room = value; - setState(() {}); - }, - ), - 8.height, - NurseMenu( - title: context.translation.receiverName, - initialValue: _selectedNurse, - enable: _assetDestination.site != null, - onSelect: (employee) { - if (employee != null) { - _selectedNurse = employee; - setState(() {}); - } - }, - ), - 16.height, - context.translation.comments.heading5(context), - 8.height, - AppTextFormField( - controller: _commentsController, - labelText: context.translation.comments, - onSaved: (text) { - _transferModel.comment = text; - }, - ), - 100.height, - ], - ), - ).expanded, - AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit) - ], - ).paddingOnly(start: 16, end: 16, bottom: 24), - ), - ), - ); - } -} diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 198ba167..da3c34ce 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -19,7 +19,7 @@ // // import '../../../models/enums/user_types.dart'; // import '../../widgets/land_page/land_page_item.dart'; -// import '../device_transfer/request_device_transfer.dart'; +// import '../device_transfer/create__asset_transfer_request.dart'; // import 'requests/requests_page.dart'; // // @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder") diff --git a/lib/views/widgets/equipment/asset_picker.dart b/lib/views/widgets/equipment/asset_picker.dart index bc3dcd17..31dc9ba1 100644 --- a/lib/views/widgets/equipment/asset_picker.dart +++ b/lib/views/widgets/equipment/asset_picker.dart @@ -15,10 +15,12 @@ class AssetPicker extends StatelessWidget { final bool editable; final bool showAssetInfo; final Color? borderColor; + Color? backgroundColor; final bool forPPM; final bool showLoading; - const AssetPicker({Key? key, this.editable = true, this.device, this.onPick,this.borderColor, this.showAssetInfo = true, this.forPPM = false, this.showLoading = false}) : super(key: key); + AssetPicker({Key? key, this.editable = true, this.device, this.onPick, this.borderColor, this.showAssetInfo = true, this.forPPM = false, this.backgroundColor, this.showLoading = false}) + : super(key: key); @override Widget build(BuildContext context) { @@ -29,7 +31,7 @@ class AssetPicker extends StatelessWidget { height: 50, alignment: Alignment.center, decoration: BoxDecoration( - color: AppColor.blueStatus(context), + color: backgroundColor ?? AppColor.blueStatus(context), borderRadius: BorderRadius.circular(10), // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), @@ -43,7 +45,10 @@ class AssetPicker extends StatelessWidget { ], ), ).onPress(() async { - Asset? device = await Navigator.of(context).push(MaterialPageRoute(builder: (context)=>AssetScanQr(title: context.translation.assetScan,))) as Asset?; + Asset? device = await Navigator.of(context).push(MaterialPageRoute( + builder: (context) => AssetScanQr( + title: context.translation.assetScan, + ))) as Asset?; if (device != null) { onPick!(device); } @@ -53,7 +58,7 @@ class AssetPicker extends StatelessWidget { height: 50, alignment: Alignment.center, decoration: BoxDecoration( - color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color:borderColor?? AppColor.blueStatus(context), width: 2), + color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color: borderColor ?? AppColor.blueStatus(context), width: 2), // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), @@ -66,7 +71,10 @@ class AssetPicker extends StatelessWidget { ], ), ).onPress(() async { - Asset? device = await Navigator.of(context).push(MaterialPageRoute(builder: (context)=>AssetScanQr(title: context.translation.assetScan,))) as Asset?; + Asset? device = await Navigator.of(context).push(MaterialPageRoute( + builder: (context) => AssetScanQr( + title: context.translation.assetScan, + ))) as Asset?; if (device != null) { onPick!(device); } From be8c83cc8f449f6c0fc3430779388b5e9bee8c17 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Tue, 18 Mar 2025 13:48:29 +0300 Subject: [PATCH 05/36] Asset tranfer api integrated ready to test --- lib/controllers/api_routes/urls.dart | 9 +- .../api/asset_transfer_provider.dart | 43 +- lib/l10n/app_ar.arb | 4 +- lib/l10n/app_en.arb | 4 +- lib/models/device/asset_transfer.dart | 118 ++++ .../common_widgets/default_app_bar.dart | 5 +- .../components/assistant_employee_card.dart | 2 +- .../create__asset_transfer_request.dart | 248 ++++---- .../update_device_transfer.dart | 589 +++++++----------- .../recurrent_work_order_view.dart | 4 - 10 files changed, 506 insertions(+), 520 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 365d8966..96569225 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -178,11 +178,16 @@ class URLs { //device transfer static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get - static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get + // static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get static get getDeviceTransfer => "$_baseUrl/AssetTransfer/GetAssetTransfers"; // get - static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get + // static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get static get getAssetTransferStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=406"; // get + //Asset transfer new Apis + static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferNewById"; // get + static get createAssetTransferRequest => "$_baseUrl/AssetTransfer/AddAssetTransferMobileNew";// post + static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateEngineerAssetTransferNew"; // get + // employee static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get diff --git a/lib/controllers/providers/api/asset_transfer_provider.dart b/lib/controllers/providers/api/asset_transfer_provider.dart index 7f722ddf..b4cad354 100644 --- a/lib/controllers/providers/api/asset_transfer_provider.dart +++ b/lib/controllers/providers/api/asset_transfer_provider.dart @@ -6,8 +6,10 @@ 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/extensions/string_extensions.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; +import 'package:test_sa/models/service_request/pending_service_request_model.dart'; import 'package:test_sa/models/user.dart'; import '../../../models/hospital.dart'; @@ -120,15 +122,27 @@ class AssetTransferProvider extends ChangeNotifier { } } + Future checkAssetPendingRequest(int assetId) async { + Response response; + try { + response = await ApiManager.instance.post(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId",body: {}); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) {} + return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]); + } catch (error) { + "Please Try Again\n$error".addTranslation.showToast; + return null; + } + } + Future createRequest({ required BuildContext context, - required AssetTransfer assetDestination, - required Asset asset, + required AssetTransfer model, }) async { Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: assetDestination.transferBody(asset: asset)); + response = await ApiManager.instance.post(URLs.createAssetTransferRequest, body: model.toCreateAssetTransferJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { if (items != null) { @@ -148,29 +162,15 @@ class AssetTransferProvider extends ChangeNotifier { } } - Future updateRequest(BuildContext context, {required AssetTransfer assetTransfer, required bool isSender}) async { + Future updateRequest(BuildContext context, {required AssetTransfer model}) async { Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.put(URLs.updateDeviceTransfer, body: assetTransfer.toJson()); - - //print(response.body); - // print("${newModel.engSignature}.png"); - // response = await post( - // Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"), - // body: body, - // ); - + response = await ApiManager.instance.post(URLs.updateDeviceTransfer, body: model.toEngineerUpdateJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { reset(); - // Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); Navigator.of(context).pop(); - // oldModel.fromDeviceTransfer( - // DeviceTransfer.fromJson( - // json.decode(utf8.decode(response.bodyBytes))[0] - // ) - // ); notifyListeners(); } else { Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}"); @@ -184,8 +184,5 @@ class AssetTransferProvider extends ChangeNotifier { } } - bool _isLocalUrl(String? url) { - if (url?.isEmpty ?? true) return false; - return url!.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); - } + } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index b8cb09a2..453ef48c 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -549,6 +549,8 @@ "attachments": "المرفقات", "supplierName": "اسم المورد", "externalEngineerName": "اسم المهندس الخارجي", - "telephone": "الهاتف" + "telephone": "الهاتف", + "transferAsset": "نقل الأصل", + "createAssetTransferRequest": "إنشاء طلب نقل أصل" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 07b5420a..05c9b774 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -552,5 +552,7 @@ "attachments": "Attachments", "supplierName": "Supplier Name", "externalEngineerName": "External Engineer Name", - "telephone": "Telephone" + "telephone": "Telephone", + "transferAsset": "Transfer Asset", + "createAssetTransferRequest": "Create Asset Transfer Request" } \ No newline at end of file diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index c14efd73..de7eab0b 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -2,6 +2,8 @@ import 'package:flutter/src/widgets/framework.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/assistant_employee.dart'; import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -11,6 +13,7 @@ class AssetTransfer { AssetTransfer({ this.id, this.transferNo, + this.transferType, this.transferCode, this.assetId, this.destSiteId, @@ -44,6 +47,7 @@ class AssetTransfer { this.receiverTravelingHours, this.receiverEngSignature, this.receiverAttachments, + this.attachments, this.assetNumber, this.assetName, this.manufacturerName, @@ -52,6 +56,7 @@ class AssetTransfer { this.destDepartmentName, this.destBuildingName, this.applied, + this.isSender, this.extensionNo, this.name, this.employeeId, @@ -76,14 +81,21 @@ class AssetTransfer { this.supplierName, this.senderVisitTimers, this.receiverVisitTimers, + this.assetTransferEngineerTimers, this.tbsTimer, this.timerModelList, + this.assistantEmployees, + this.modelAssistantEmployees, + this.assetTransferAssistantEmployeesReceiver, + this.assetTransferAssistantEmployeesSender, + this.statusValue, }); AssetTransfer.fromJson(dynamic json) { id = json['id']; transferNo = json['transferNo']; transferCode = json['transferCode']; + transferType = json["transferType"] == null ? null : Lookup.fromJson(json["transferType"]); assetId = json['assetId']; destSiteId = json['destSiteId']; destBuildingId = json['destBuildingId']; @@ -132,6 +144,19 @@ class AssetTransfer { receiverVisitTimers!.add(VisitTimers.fromJson(v)); }); } + if (json['assetTransferAssistantEmployeesSender'] != null) { + assetTransferAssistantEmployeesSender = []; + json['assetTransferAssistantEmployeesSender'].forEach((v) { + assetTransferAssistantEmployeesSender!.add(AssetTransferAssistantEmployees.fromJson(v)); + }); + } + if (json['assetTransferAssistantEmployeesReceiver'] != null) { + assetTransferAssistantEmployeesReceiver = []; + json['assetTransferAssistantEmployeesReceiver'].forEach((v) { + assetTransferAssistantEmployeesReceiver!.add(AssetTransferAssistantEmployees.fromJson(v)); + }); + } + tbsTimer = TimerModel(); // try { // receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? "")); @@ -188,6 +213,8 @@ class AssetTransfer { num? id; num? transferNo; String? transferCode; + int? statusValue; + Lookup? transferType; String? assetSerialNo; num? assetId; String? assetNumber; @@ -218,6 +245,7 @@ class AssetTransfer { String? senderTravelingHours; String? senderEngSignature; List? senderAttachments; + List? attachments; String? receiverAssignedEmployeeId; num? receiverMachineStatusId; String? receiverComment; @@ -244,6 +272,7 @@ class AssetTransfer { String? receiverMachineStatusName; String? receiverEngSignatureUrl; bool? applied; + bool? isSender; dynamic extensionNo; String? employeeId; String? name; @@ -252,13 +281,21 @@ class AssetTransfer { String? modifiedOn; List? senderVisitTimers; List? receiverVisitTimers; + List? assetTransferEngineerTimers; List? timerModelList = []; + List? assistantEmployees; + List? assetTransferAssistantEmployeesSender; + + List? assetTransferAssistantEmployeesReceiver; + + AssetTransferAssistantEmployees? modelAssistantEmployees; TimerModel? tbsTimer = TimerModel(); AssetTransfer copyWith( {num? id, num? transferNo, String? transferCode, + Lookup? transferType, num? assetId, num? destSiteId, num? destBuildingId, @@ -329,6 +366,7 @@ class AssetTransfer { id: id ?? this.id, transferNo: transferNo ?? this.transferNo, transferCode: transferCode ?? this.transferCode, + transferType: transferType ?? this.transferType, assetId: assetId ?? this.assetId, destSiteId: destSiteId ?? this.destSiteId, destBuildingId: destBuildingId ?? this.destBuildingId, @@ -475,6 +513,44 @@ class AssetTransfer { return map; } + Map toCreateAssetTransferJson() { + final map = {}; + map['id'] = id; + map['assetId'] = assetId; + map['transferTypeId'] = transferType?.id; + map['destSiteId'] = destSiteId; + map['destSiteId'] = destSiteId; + map['destBuildingId'] = destBuildingId; + map['destFloorId'] = destFloorId; + map['destDepartmentId'] = destDepartmentId; + map['destRoomId'] = destRoomId; + map['comment'] = comment; + if (attachments != null) { + map['attachment'] = attachments!.map((v) => v.toJson()).toList(); + } + return map; + } + + Map toEngineerUpdateJson() { + final map = {}; + map['id'] = id; + map['statusValue'] = statusValue; + map['isSender'] = isSender; + map['techComment'] = comment; + map['assetTransferAssistantEmployees'] = modelAssistantEmployees; + map['assetTransferEngineerTimers'] = assetTransferEngineerTimers; + if (attachments != null) { + map['attachments'] = attachments!.map((v) => v.toJson()).toList(); + } + if (assetTransferEngineerTimers != null) { + map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList(); + } + if (modelAssistantEmployees != null) { + map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()]; + } + return map; + } + Map transferBody({Asset? asset}) { final map = {}; map['id'] = 0; @@ -529,6 +605,7 @@ class AssetTransfer { if (assetTransfer == null) return; id = assetTransfer.id; transferNo = assetTransfer.transferNo; + transferType = assetTransfer.transferType; transferCode = assetTransfer.transferCode; assetId = assetTransfer.assetId; destSiteId = assetTransfer.destSiteId; @@ -594,6 +671,8 @@ class AssetTransfer { manufacturerName = assetTransfer.manufacturerName; senderVisitTimers = assetTransfer.senderVisitTimers; receiverVisitTimers = assetTransfer.receiverVisitTimers; + assetTransferAssistantEmployeesReceiver = assetTransfer.assetTransferAssistantEmployeesReceiver; + assetTransferAssistantEmployeesSender = assetTransfer.assetTransferAssistantEmployeesSender; } Future validate(BuildContext context) async { @@ -616,3 +695,42 @@ class AssetTransfer { return true; } } + +class AssetTransferAssistantEmployees { + DateTime? startDate; + DateTime? endDate; + double? workingHours; + String? techComment; + String? employeeId; + String? employeeNumber; + String? employeeName; + String? email; + String? mobileNo; + dynamic extension; + + AssetTransferAssistantEmployees( + {this.startDate, this.endDate, this.workingHours, this.techComment, this.employeeId, this.employeeName, this.employeeNumber, this.email, this.extension, this.mobileNo}); + + AssetTransferAssistantEmployees.fromJson(Map json) { + startDate = json['startDate'] != null ? DateTime.parse(json['startDate']) : null; + endDate = json['endDate'] != null ? DateTime.parse(json['endDate']) : null; + workingHours = json['workingHours']; + techComment = json['techComment']; + employeeId = json['employeeId']; + employeeNumber = json['employeeNumber']; + employeeName = json['employeeName']; + email = json['email']; + mobileNo = json['mobileNo']; + extension = json['extension']; + } + + Map toJson() { + final Map data = {}; + data['startDate'] = startDate?.toIso8601String(); + data['endDate'] = endDate?.toIso8601String(); + data['workingHours'] = workingHours; + data['techComment'] = techComment; + data['employeeId'] = employeeId; + return data; + } +} diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index 6cc8bd5a..ff409dd0 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -12,8 +12,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { final List? actions; final Function? onBackPress; final bool showHomeActionButton; + final TextStyle? titleStyle; - const DefaultAppBar({this.title, this.onBackPress, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); + const DefaultAppBar({this.title, this.onBackPress, this.actions, this.showHomeActionButton = false,this.titleStyle, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -49,7 +50,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { 10.width, Text( title ?? "", - style: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + style: titleStyle??AppTextStyles.heading4.copyWith(fontWeight: FontWeight.w500, color:AppColor.white936 ), ).expanded, ], ), diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart index 0e1764e7..3e92e92e 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -122,7 +122,7 @@ class _AssistantEmployeeCardState extends State { requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); ServiceRequestUtils.calculateAndAssignWorkingHours( startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, workingHoursController: _workingHoursController, updateModel: (hours){ requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; diff --git a/lib/views/pages/device_transfer/create__asset_transfer_request.dart b/lib/views/pages/device_transfer/create__asset_transfer_request.dart index d65537ff..d9587739 100644 --- a/lib/views/pages/device_transfer/create__asset_transfer_request.dart +++ b/lib/views/pages/device_transfer/create__asset_transfer_request.dart @@ -1,29 +1,26 @@ +import 'dart:convert'; import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_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/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; -import 'package:test_sa/models/employee.dart'; -import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/device/asset_transfer_attachment.dart'; import 'package:test_sa/models/new_models/department.dart'; import 'package:test_sa/models/new_models/floor.dart'; -import 'package:test_sa/models/new_models/room_model.dart'; +import 'package:test_sa/models/service_request/pending_service_request_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/providers/ppm_service_provider.dart'; import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart'; +import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart'; import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; -import 'package:test_sa/views/widgets/status/employee/nurse_menu.dart'; - import '../../../models/new_models/building.dart'; import '../../../models/new_models/site.dart'; import '../../../new_views/common_widgets/app_filled_button.dart'; @@ -31,7 +28,6 @@ import '../../../new_views/common_widgets/default_app_bar.dart'; import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; import '../../../providers/gas_request_providers/site_provider.dart'; import '../../../providers/loading_list_notifier.dart'; -import '../../widgets/equipment/pick_asset.dart'; class CreateAssetTransferRequest extends StatefulWidget { static const String id = "/request-device-transfer"; @@ -43,25 +39,28 @@ class CreateAssetTransferRequest extends StatefulWidget { } class _CreateAssetTransferRequestState extends State { - UserProvider? _userProvider; - SettingProvider? _settingProvider; late AssetTransferProvider _deviceTransferProvider; final TextEditingController _requestedQuantityController = TextEditingController(); - final AssetTransfer _transferModel = AssetTransfer(); + final AssetTransfer _transferModel = AssetTransfer(id: 0); final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController(); final Asset _assetDestination = Asset(); Asset? _pickedAsset; - Employee? receiverEndUser; - Employee? _selectedNurse; final List _deviceImages = []; + PendingAssetServiceRequest? pendingAssetServiceRequest; @override void setState(VoidCallback fn) { if (mounted) super.setState(() {}); } -//TODO need to clean the extra logic and code when finilize api from backend.. + + bool checkPendingRequest = false; + + void showPendingRequests() { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!))); + } + void _onSubmit() async { _transferModel.assetId = _pickedAsset?.id; _transferModel.destSiteId = _assetDestination.site?.id; @@ -69,33 +68,32 @@ class _CreateAssetTransferRequestState extends State _transferModel.destFloorId = _assetDestination.floor?.id; _transferModel.destDepartmentId = _assetDestination.department?.id; _transferModel.destRoomId = _assetDestination.room?.id; - _transferModel.receiverEndUserId = _selectedNurse?.id; if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) { return; } _formKey.currentState!.save(); - // List attachement = []; - // for (var item in _deviceImages) { - // attachement.add(WorkOrderAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}")); - // } + List attachement = []; + for (var item in _deviceImages) { + attachement.add(AssetTransferAttachment(id: 0, attachmentName: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}")); + } + _transferModel.attachments = attachement; - await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset!); - } - List requestType = [ - Lookup(name: 'Internal', value: 1), - Lookup(name: 'External', value: 2), - ]; + await _deviceTransferProvider.createRequest( + context: context, + model: _transferModel, + ); + } @override void initState() { - // TODO: need to check parameter with backend. - // _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList()); + WidgetsBinding.instance.addPostFrameCallback((_) async { + Provider.of(context, listen: false).getDate(); + }); super.initState(); } - Lookup selectedRequestType = Lookup(name: 'Internal', value: 1); @override void dispose() { @@ -108,12 +106,13 @@ class _CreateAssetTransferRequestState extends State @override Widget build(BuildContext context) { - _userProvider = Provider.of(context, listen: false); - _settingProvider = Provider.of(context, listen: false); _deviceTransferProvider = Provider.of(context, listen: false); return Scaffold( key: _scaffoldKey, - appBar: DefaultAppBar(title: context.translation.newTransferRequest), + appBar: DefaultAppBar( + title: context.translation.createAssetTransferRequest, + titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), body: Form( key: _formKey, child: SafeArea( @@ -123,14 +122,6 @@ class _CreateAssetTransferRequestState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // 16.height, - // PickAsset( - // device: _pickedAsset, - // onPickAsset: (asset) { - // _pickedAsset = asset; - // setState(() {}); - // }, - // ), AssetPicker( device: _pickedAsset, showLoading: false, @@ -138,50 +129,30 @@ class _CreateAssetTransferRequestState extends State backgroundColor: AppColor.white936, onPick: (asset) async { _pickedAsset = asset; + await checkAssetForPendingServiceRequest(asset.id!.toInt()); + if (_pickedAsset != null && pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + showPendingRequestBottomSheet(); + } setState(() {}); - // pendingAssetServiceRequest = null; - // _serviceRequest.device = asset; - // await checkAssetForPendingServiceRequest(asset.id!.toInt()); - // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { - // showPendingRequestBottomSheet(); }), + if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ + 8.height, + Row( + children: [ + const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), + 8.width, + Text( + "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), + ).expanded, + ], + ).onPress(() { + showPendingRequests(); + }), + ], 21.height, - context.translation.requestType.bodyText(context).custom(color: AppColor.white936), - 10.height, - Wrap( - runSpacing: 8, - spacing: 20, - children: [ - for (var element in requestType) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 24, - height: 24, - child: Radio( - value: element, - activeColor: AppColor.primary10, - fillColor: WidgetStateColor.resolveWith((states) { - if (states.contains(WidgetState.selected)) { - return AppColor.primary10; // Thumb color when selected - } - return Colors.grey; // Thumb color when unselected (grey) - }), - groupValue: selectedRequestType, - onChanged: (state) { - setState(() { - selectedRequestType = element; - }); - }), - ), - 8.width, - Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)), - ], - ) - ], - ), - 8.height, + requestTypeWidget(context), + 12.height, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -197,9 +168,6 @@ class _CreateAssetTransferRequestState extends State _assetDestination.building = null; _assetDestination.floor = null; _assetDestination.department = null; - _selectedNurse = null; - Provider.of(context, listen: false).siteId = value!.id!.toInt(); - Provider.of(context, listen: false).getData(); setState(() {}); }, ).expanded, @@ -257,32 +225,6 @@ class _CreateAssetTransferRequestState extends State ], ), 8.height, - // SingleItemDropDownMenu( - // context: context, - // title: context.translation.room, - // initialValue: _assetDestination.room, - // backgroundColor:AppColor.neutral100, - // enabled: _assetDestination.department?.rooms?.isNotEmpty ?? false, - // staticData: _assetDestination.department?.rooms ?? [], - // onSelect: (value) { - // _assetDestination.room = value; - // setState(() {}); - // }, - // ), - // 8.height, - // NurseMenu( - // title: context.translation.receiverName, - // initialValue: _selectedNurse, - // - // enable: _assetDestination.site != null, - // onSelect: (employee) { - // if (employee != null) { - // _selectedNurse = employee; - // setState(() {}); - // } - // }, - // ), - // 16.height, AppTextFormField( controller: _commentsController, backgroundColor: AppColor.neutral100, @@ -309,9 +251,7 @@ class _CreateAssetTransferRequestState extends State ).toShadowContainer(context).paddingOnly(top: 20, start: 16, end: 16), ).expanded, FooterActionButton.footerContainer( - child: AppFilledButton(buttonColor: AppColor.primary10, label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit - // buttonColor: AppColor.primary10, - ), + child: AppFilledButton(buttonColor: AppColor.primary10, label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit), ), ], ), @@ -319,4 +259,84 @@ class _CreateAssetTransferRequestState extends State ), ); } + + Future checkAssetForPendingServiceRequest(int assetId) async { + checkPendingRequest = true; + setState(() {}); + + pendingAssetServiceRequest = await _deviceTransferProvider.checkAssetPendingRequest(assetId); + await Future.delayed(const Duration(milliseconds: 250)); + + checkPendingRequest = false; + setState(() {}); + } + + void showPendingRequestBottomSheet() async { + bool view = (await showModalBottomSheet( + context: context, + isDismissible: false, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _pickedAsset!), + )) as bool; + if (view) { + showPendingRequests(); + } + } + + Widget requestTypeWidget(BuildContext context) { + return Consumer(builder: (cxt, snapshot, _) { + try { + _transferModel.transferType ??= snapshot.items.first; + } catch (ex) { + print("snapshot.items:${snapshot.items.length}"); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + context.translation.requestType.bodyText(context).custom(color: AppColor.white936), + 8.height, + Wrap( + runSpacing: 8, + spacing: 8, + children: [ + for (var element in snapshot.items) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: AppColor.primary10, + fillColor: WidgetStateColor.resolveWith((states) { + if (states.contains(WidgetState.selected)) { + return AppColor.primary10; // Thumb color when selected + } + return Colors.grey; // Thumb color when unselected (grey) + }), + groupValue: _transferModel.transferType, + onChanged: (state) { + _transferModel.transferType = element; + setState(() {}); + // }); + }), + ), + 8.width, + Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)), + ], + ) + ], + ).toShimmer(isShow: snapshot.loading), + ], + ); + }); + } } diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index aff1a2e3..5ab3a914 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -1,3 +1,5 @@ + +//older code. // import 'dart:convert'; // import 'dart:io'; // @@ -332,41 +334,32 @@ import 'dart:convert'; import 'dart:io'; - -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_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/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/device/asset_transfer_attachment.dart'; -import 'package:test_sa/models/new_models/work_order_detail_model.dart'; +import 'package:test_sa/models/new_models/assigned_employee.dart'; +import 'package:test_sa/models/new_models/assistant_employee.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; -import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; -import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; -import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; - import '../../../extensions/text_extensions.dart'; -import '../../../models/lookup.dart'; import '../../../models/ppm/ppm.dart'; import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../widgets/e_signature/e_signature.dart'; import '../../widgets/timer/app_timer.dart'; class UpdateDeviceTransfer extends StatefulWidget { @@ -381,10 +374,7 @@ class UpdateDeviceTransfer extends StatefulWidget { class _UpdateDeviceTransferState extends State { final bool _isLoading = false; - bool _validate = false; - late UserProvider _userProvider; - late SettingProvider _settingProvider; - Uint8List? _signature; + late AssetTransferProvider _deviceTransferProvider; final TextEditingController _requestedQuantityController = TextEditingController(); final AssetTransfer _formModel = AssetTransfer(); @@ -393,27 +383,7 @@ class _UpdateDeviceTransferState extends State { List _files = []; - _update() async { - if (widget.isSender) { - _formModel.senderVisitTimers?.add( - VisitTimers( - id: 0, - startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), - endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), - workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), - ), - ); - } else { - _formModel.receiverVisitTimers?.add( - VisitTimers( - id: 0, - startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), - endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), - workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), - ), - ); - } - + _update({required int status}) async { if (_formModel.tbsTimer?.startAt == null) { await Fluttertoast.showToast(msg: "Working Hours Required"); return false; @@ -422,19 +392,38 @@ class _UpdateDeviceTransferState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - _validate = true; if (!(_formKey.currentState!.validate())) { setState(() {}); return false; } _formKey.currentState!.save(); + _formModel.statusValue = status; + _formModel.isSender = widget.isSender; + if (widget.isSender) { _formModel.senderAttachments = []; + _formModel.senderVisitTimers?.add( + VisitTimers( + id: 0, + startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), + endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), + workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), + ), + ); + _formModel.assetTransferEngineerTimers = _formModel.senderVisitTimers; } else { _formModel.receiverAttachments = []; + _formModel.receiverVisitTimers?.add( + VisitTimers( + id: 0, + startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), + endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), + workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), + ), + ); + _formModel.assetTransferEngineerTimers = _formModel.receiverVisitTimers; } - try { for (var file in _files) { String attachmentName = file.path; @@ -442,17 +431,19 @@ class _UpdateDeviceTransferState extends State { attachmentName = file.path.split("/").last; attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; } - if (widget.isSender) { _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); + _formModel.attachments = _formModel.senderAttachments; } else { _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); + _formModel.attachments = _formModel.receiverAttachments; } } } catch (error) { print(error); } - await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender); + + await _deviceTransferProvider.updateRequest(context, model: _formModel); } @override @@ -478,20 +469,16 @@ class _UpdateDeviceTransferState extends State { @override Widget build(BuildContext context) { - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); _deviceTransferProvider = Provider.of(context, listen: false); - double totalWorkingHours = widget.isSender ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0) : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0); - bool isTimerEnable = widget.isSender ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); return Scaffold( - appBar: DefaultAppBar(title: context.translation.updateRequest), + appBar: DefaultAppBar(title: context.translation.transferAsset), key: _scaffoldKey, body: SafeArea( child: LoadingManager( @@ -510,56 +497,12 @@ class _UpdateDeviceTransferState extends State { Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - // _buildCard(), - // 8.height, - // AppTextFormField( - // initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", - // labelText: context.translation.travelingHours, - // onChange: (text) { - // widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; - // }, - // onSaved: (value) { - // widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; - // //_formModel?.workingHours = double.tryParse(value); - // // _formModel.travelingHours = value; - // }, - // textInputType: TextInputType.number, - // //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", - // ), - // 8.height, - // if (totalWorkingHours > 0.0) ...[ - // Container( - // height: 50.toScreenHeight, - // padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - // alignment: Alignment.centerLeft, - // decoration: BoxDecoration( - // color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - // borderRadius: BorderRadius.circular(10), - // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - // ), - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Text( - // "Total Working Time", - // style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - // ), - // Text( - // " ${formatDuration(totalWorkingHours.round())}", - // style: Theme.of(context).textTheme.bodyLarge, - // ), - // ], - // ), - // ), - // 8.height, - // ], - _timerWidget(context, totalWorkingHours, isTimerEnable), 8.height, AppTextFormField( initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", - labelText: context.translation.comments, + labelText: context.translation.technicalComment, + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral20), textInputType: TextInputType.multiline, backgroundColor: AppColor.neutral100, showShadow: false, @@ -568,43 +511,6 @@ class _UpdateDeviceTransferState extends State { widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; }, ), - // AppTimer( - // label: context.translation.workingHours, - // timer: _formModel.tbsTimer, - // enabled: isTimerEnable, - // // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), - // timerProgress: (isRunning) { - // isTimerRunning = isRunning; - // }, - // onChange: (timer) async { - // _formModel.tbsTimer = timer; - // return true; - // }, - // ), - // 8.height, - // Consumer(builder: (context, snapshot, _) { - // return SingleItemDropDownMenu( - // context: context, - // title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, - // initialValue:snapshot.items.isNotEmpty? - // snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null):null, - // onSelect: (value) { - // if (value?.value == 4) { - // "Status cannot be change to ${value?.name}.".addTranslation.showToast; - // setState(() {}); - // return; - // } - // if (widget.isSender) { - // _formModel.senderMachineStatusName = value?.name; - // _formModel.senderMachineStatusId = value?.id; - // } else { - // _formModel.receiverMachineStatusName = value?.name; - // _formModel.receiverMachineStatusId = value?.id; - // } - // setState(() {}); - // }, - // ); - // }), 8.height, MultiFilesPicker( label: context.translation.attachFiles, @@ -614,32 +520,33 @@ class _UpdateDeviceTransferState extends State { buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), 8.height, - - // 8.height, - // ESignature( - // title: "Signature", - // oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, - // newSignature: _signature, - // onSaved: (signature) { - // _signature = signature; - // if (signature == null || signature.isEmpty) return; - // widget.isSender - // ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" - // : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - // }, - // ), ], ).toShadowContainer(context), 16.height, - const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)), + AssistantEmployeeCard( + isSender: widget.isSender, + formModel: _formModel, + ).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)), ], ), ).expanded, - Padding( - padding: const EdgeInsets.all(16.0), - child: AppFilledButton( - label: context.translation.update, - onPressed: _update, + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _update(status: 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _update(status: 1), + ).expanded, + ], ), ), ], @@ -659,18 +566,6 @@ class _UpdateDeviceTransferState extends State { // notifyListeners(); } - _buildCard() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - context.translation.transferDetails.heading5(context), - 8.height, - '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), - ], - ).toShadowContainer(context); - } - Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) { return Column( mainAxisSize: MainAxisSize.min, @@ -708,46 +603,27 @@ class _UpdateDeviceTransferState extends State { ], ); } - - String formatDuration(int seconds) { - int hours = seconds ~/ 3600; - int minutes = (seconds % 3600) ~/ 60; - int remainingSeconds = seconds % 60; - - String formattedDuration = ''; - if (hours > 0) { - formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; - } - if (minutes > 0) { - formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; - } - if (remainingSeconds > 0) { - formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; - } - if (formattedDuration.isEmpty) { - formattedDuration = 'Less than a second'; - } - - return formattedDuration.trim(); - } } class AssistantEmployeeCard extends StatefulWidget { - const AssistantEmployeeCard({super.key}); + bool? isSender = false; + AssetTransfer? formModel; + + AssistantEmployeeCard({super.key, this.isSender, this.formModel}); @override State createState() => _AssistantEmployeeCardState(); } class _AssistantEmployeeCardState extends State { - bool status = false; final TextEditingController _workingHoursController = TextEditingController(text: ''); bool isCurrentUserIsAssistantEmp = false; bool isExpanded = false; + List employeeList = []; + AssistantEmployees selectedEmployee = AssistantEmployees(); @override void initState() { - // TODO: implement initState WidgetsBinding.instance.addPostFrameCallback((_) { getInitialData(); }); @@ -755,202 +631,171 @@ class _AssistantEmployeeCardState extends State { } Future getInitialData() async { - final user = Provider.of(context, listen: false).user!; - ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); - - // if (isCurrentUserIsAssistantEmp) { - // // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; - // } + if (widget.isSender!) { + employeeList = widget.formModel!.assetTransferAssistantEmployeesSender ?? []; + } else { + employeeList = widget.formModel!.assetTransferAssistantEmployeesReceiver ?? []; + } + widget.formModel?.modelAssistantEmployees = employeeList.isNotEmpty ? employeeList[0] : AssetTransferAssistantEmployees(); + AssignedEmployee? assignedUser = AssignedEmployee( + id: employeeList[0].employeeId, + name: employeeList[0].employeeName, + ); + selectedEmployee = AssistantEmployees(userId: assignedUser.id, user: assignedUser); } @override void dispose() { - // TODO: implement dispose _workingHoursController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - return Consumer(builder: (context, requestDetailProvider, child) { - return Column( - children: [ - SizedBox( - height: 56.toScreenHeight, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10), - Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), - ], - ), - ).onPress(() { - setState(() { - isExpanded = !isExpanded; - }); - }), - isExpanded - ? Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ServiceReportAssistantEmployeeMenu( - title: context.translation.select, - backgroundColor: AppColor.neutral100, - // assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!, - // initialValue: (requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.isNotEmpty ?? false) - // ? requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.first - // : null, - - initialValue: null, - assetId: 23, - //TODO add check... - // enable: !isCurrentUserIsAssistantEmp, - onSelect: (employee) { - if (employee == null) { - requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = []; - } else { - requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [employee.copyWith(id: 0)]; - requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); - } - }, - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; - }); - } - }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null && - selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) { - "End Date time must be greater then start date".showToast; - return; - } - requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours; - }); + return Column( + children: [ + SizedBox( + height: 56.toScreenHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10), + Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), + ], + ), + ).onPress(() { + setState(() { + isExpanded = !isExpanded; + }); + }), + isExpanded + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ServiceReportAssistantEmployeeMenu( + title: context.translation.select, + backgroundColor: AppColor.neutral100, + assetId: widget.formModel?.assetId ?? 0, + initialValue: selectedEmployee, + onSelect: (employee) { + if (employee == null) { + widget.formModel?.assistantEmployees = []; + } else { + widget.formModel?.assistantEmployees = [employee.copyWith(id: 0)]; + widget.formModel?.modelAssistantEmployees?.employeeId = employee.user?.id; + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.formModel?.modelAssistantEmployees?.startDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + widget.formModel?.modelAssistantEmployees?.startDate = selectedDateTime; + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.formModel?.modelAssistantEmployees?.startDate, + endTime: widget.formModel?.modelAssistantEmployees?.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + widget.formModel?.modelAssistantEmployees?.workingHours = hours; + }); + setState(() {}); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.formModel?.modelAssistantEmployees?.endDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (widget.formModel?.modelAssistantEmployees?.startDate != null && selectedDateTime.isBefore(widget.formModel!.modelAssistantEmployees!.startDate!)) { + "End Date time must be greater then start date".showToast; + return; } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: _workingHoursController, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null - ? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString() - : '', - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - AppTextFormField( - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment, - labelText: context.translation.technicalComment, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - alignLabelWithHint: true, - textInputType: TextInputType.multiline, - onChange: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; - }, - onSaved: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; - }, - ), - 16.height, - ], - ) - : const SizedBox(), - ], - ); - }); + widget.formModel?.modelAssistantEmployees?.endDate = selectedDateTime; + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.formModel?.modelAssistantEmployees?.startDate, + endTime: widget.formModel?.modelAssistantEmployees?.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + widget.formModel?.modelAssistantEmployees?.workingHours = hours; + }); + setState(() {}); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: widget.formModel?.modelAssistantEmployees?.workingHours != null ? widget.formModel?.modelAssistantEmployees?.workingHours.toString() : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: widget.formModel?.modelAssistantEmployees?.techComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + widget.formModel?.modelAssistantEmployees?.techComment = value; + }, + onSaved: (value) { + widget.formModel?.modelAssistantEmployees?.techComment = value; + }, + ), + 16.height, + ], + ) + : const SizedBox(), + ], + ); } - -// //TODO move this to some common place....@waseem -// double calculateWorkingHours(DateTime? startTime, DateTime? endTime) { -// if (startTime != null && endTime != null) { -// Duration difference = endTime.difference(startTime); -// int hours = difference.inHours; -// int minutes = difference.inMinutes % 60; -// return hours.toDouble(); -// } else { -// return -1; -// } -// } -// -// assignWorkingHours({required RequestDetailProvider requestDetailProvider}) { -// double hours = calculateWorkingHours( -// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate); -// if (hours != -1) { -// _workingHoursController.text = hours.toString(); -// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours = hours; -// } -// } } diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 8b3eb979..21a2f28f 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -104,11 +104,7 @@ void _updateTask({required BuildContext context, required int status}) async { if (validate(model: allRequestsProvider.recurrentWoData!)) { allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; - DateTime? startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt; - DateTime? endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt; - // final duration = (endTime?.difference(startTime!)); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) { int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( From d8cd1362fb9b0bac9b0996af974e0c325dfecec3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 19 Mar 2025 10:47:39 +0300 Subject: [PATCH 06/36] pod file --- ios/Podfile.lock | 371 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 ios/Podfile.lock diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..ffbf5eb6 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,371 @@ +PODS: + - audio_session (0.0.1): + - Flutter + - audioplayers_darwin (0.0.1): + - Flutter + - device_calendar (0.0.1): + - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - DTTJailbreakDetection (0.4.0) + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Firebase/CoreOnly (11.2.0): + - FirebaseCore (= 11.2.0) + - Firebase/Messaging (11.2.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 11.2.0) + - firebase_core (3.6.0): + - Firebase/CoreOnly (= 11.2.0) + - Flutter + - firebase_messaging (15.1.3): + - Firebase/Messaging (= 11.2.0) + - firebase_core + - Flutter + - FirebaseCore (11.2.0): + - FirebaseCoreInternal (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Logger (~> 8.0) + - FirebaseCoreInternal (11.9.0): + - "GoogleUtilities/NSData+zlib (~> 8.0)" + - FirebaseInstallations (11.4.0): + - FirebaseCore (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - FirebaseMessaging (11.2.0): + - FirebaseCore (~> 11.0) + - FirebaseInstallations (~> 11.0) + - GoogleDataTransport (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Reachability (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) + - Flutter (1.0.0) + - flutter_keyboard_visibility (0.0.1): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_sound (9.6.0): + - Flutter + - flutter_sound_core (= 9.6.0) + - flutter_sound_core (9.6.0) + - flutter_timezone (0.0.1): + - Flutter + - fluttertoast (0.0.2): + - Flutter + - Toast + - FMDB (2.7.12): + - FMDB/standard (= 2.7.12) + - FMDB/Core (2.7.12) + - FMDB/standard (2.7.12): + - FMDB/Core + - geolocator_apple (1.2.0): + - Flutter + - GoogleDataTransport (10.1.0): + - nanopb (~> 3.30910.0) + - PromisesObjC (~> 2.4) + - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (8.0.2)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.0.2) + - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - image_cropper (0.0.4): + - Flutter + - TOCropViewController (~> 2.7.4) + - image_picker_ios (0.0.1): + - Flutter + - just_audio (0.0.1): + - Flutter + - local_auth_darwin (0.0.1): + - Flutter + - FlutterMacOS + - MTBBarcodeScanner (5.0.11) + - nanopb (3.30910.0): + - nanopb/decode (= 3.30910.0) + - nanopb/encode (= 3.30910.0) + - nanopb/decode (3.30910.0) + - nanopb/encode (3.30910.0) + - nfc_manager (0.0.1): + - Flutter + - open_file_ios (0.0.1): + - Flutter + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + - pointer_interceptor_ios (0.0.1): + - Flutter + - PromisesObjC (2.4.0) + - qr_code_scanner (0.2.0): + - Flutter + - MTBBarcodeScanner + - record_mp3_plus (1.0.0): + - Flutter + - rive_common (0.0.1): + - Flutter + - safe_device (1.0.0): + - DTTJailbreakDetection + - Flutter + - SDWebImage (5.21.0): + - SDWebImage/Core (= 5.21.0) + - SDWebImage/Core (5.21.0) + - share_plus (0.0.1): + - Flutter + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - speech_to_text (0.0.1): + - Flutter + - FlutterMacOS + - Try + - sqflite (0.0.3): + - Flutter + - FlutterMacOS + - SwiftyGif (5.4.5) + - Toast (4.1.1) + - TOCropViewController (2.7.4) + - Try (2.1.1) + - url_launcher_ios (0.0.1): + - Flutter + - wifi_iot (0.0.1): + - Flutter + +DEPENDENCIES: + - audio_session (from `.symlinks/plugins/audio_session/ios`) + - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) + - device_calendar (from `.symlinks/plugins/device_calendar/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`) + - flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - FMDB + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - just_audio (from `.symlinks/plugins/just_audio/ios`) + - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) + - nfc_manager (from `.symlinks/plugins/nfc_manager/ios`) + - open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`) + - qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`) + - record_mp3_plus (from `.symlinks/plugins/record_mp3_plus/ios`) + - rive_common (from `.symlinks/plugins/rive_common/ios`) + - safe_device (from `.symlinks/plugins/safe_device/ios`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - speech_to_text (from `.symlinks/plugins/speech_to_text/darwin`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - wifi_iot (from `.symlinks/plugins/wifi_iot/ios`) + +SPEC REPOS: + trunk: + - DKImagePickerController + - DKPhotoGallery + - DTTJailbreakDetection + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - flutter_sound_core + - FMDB + - GoogleDataTransport + - GoogleUtilities + - MTBBarcodeScanner + - nanopb + - PromisesObjC + - SDWebImage + - SwiftyGif + - Toast + - TOCropViewController + - Try + +EXTERNAL SOURCES: + audio_session: + :path: ".symlinks/plugins/audio_session/ios" + audioplayers_darwin: + :path: ".symlinks/plugins/audioplayers_darwin/ios" + device_calendar: + :path: ".symlinks/plugins/device_calendar/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_keyboard_visibility: + :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + flutter_sound: + :path: ".symlinks/plugins/flutter_sound/ios" + flutter_timezone: + :path: ".symlinks/plugins/flutter_timezone/ios" + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + just_audio: + :path: ".symlinks/plugins/just_audio/ios" + local_auth_darwin: + :path: ".symlinks/plugins/local_auth_darwin/darwin" + nfc_manager: + :path: ".symlinks/plugins/nfc_manager/ios" + open_file_ios: + :path: ".symlinks/plugins/open_file_ios/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + pointer_interceptor_ios: + :path: ".symlinks/plugins/pointer_interceptor_ios/ios" + qr_code_scanner: + :path: ".symlinks/plugins/qr_code_scanner/ios" + record_mp3_plus: + :path: ".symlinks/plugins/record_mp3_plus/ios" + rive_common: + :path: ".symlinks/plugins/rive_common/ios" + safe_device: + :path: ".symlinks/plugins/safe_device/ios" + share_plus: + :path: ".symlinks/plugins/share_plus/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + speech_to_text: + :path: ".symlinks/plugins/speech_to_text/darwin" + sqflite: + :path: ".symlinks/plugins/sqflite/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + wifi_iot: + :path: ".symlinks/plugins/wifi_iot/ios" + +SPEC CHECKSUMS: + audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207 + audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 + device_calendar: 9cb33f88a02e19652ec7b8b122ca778f751b1f7b + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + DTTJailbreakDetection: 5e356c5badc17995f65a83ed9483f787a0057b71 + file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 + Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c + firebase_core: 2bedc3136ec7c7b8561c6123ed0239387b53f2af + firebase_messaging: 15d114e1a41fc31e4fbabcd48d765a19eec94a38 + FirebaseCore: a282032ae9295c795714ded2ec9c522fc237f8da + FirebaseCoreInternal: 154779013b85b4b290fdba38414df475f42e3096 + FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 + FirebaseMessaging: c9ec7b90c399c7a6100297e9d16f8a27fc7f7152 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 + flutter_sound: dde9a913063b65a27ba8fdc2039036b99b136c79 + flutter_sound_core: 0c6eb9d5268adc70ff159b3d65fd3d98a82d3a27 + flutter_timezone: ffb07bdad3c6276af8dada0f11978d8a1f8a20bb + fluttertoast: 723e187574b149e68e63ca4d39b837586b903cfa + FMDB: 728731dd336af3936ce00f91d9d8495f5718a0e6 + geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d + image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + nfc_manager: d7da7cb781f7744b94df5fe9dbca904ac4a0939e + open_file_ios: 461db5853723763573e140de3193656f91990d9e + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + pointer_interceptor_ios: 508241697ff0947f853c061945a8b822463947c1 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e + record_mp3_plus: be7806da5b5ff9694f8069f401120853c89f3398 + rive_common: cbbac3192af00d7341f19dae2f26298e9e37d99e + safe_device: 4539eb6bdbeb4b61a763a51c4e73e6b37dea4e3d + SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + speech_to_text: 627d3fd2194770b51abb324ba45c2d39398f24a8 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 + Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e + TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 + Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + wifi_iot: b5aafd6f9b52f8a357383a1deabab45f31cd602d + +PODFILE CHECKSUM: d8654c27146ad2b7c852fbdd93ef1a3785d9310b + +COCOAPODS: 1.12.0 From 6b51805827f323aad6edc067660170bb608ba5e6 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 19 Mar 2025 10:54:43 +0300 Subject: [PATCH 07/36] improvement --- .../recurrent_wo/components/task_info_widget.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index b2082e8e..799de831 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -50,11 +50,11 @@ class RecurrentTaskInfoWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildingInfoWidget(label: context.translation.department, value: model?.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.floor, value: model?.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.room, value: model?.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, _timerWidget(context, model!.totalWorkingHours!) ], From f99ea0dacd8d99261a268cff73f9bfdae7520a3f Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 12:32:54 +0300 Subject: [PATCH 08/36] remove camel case text, confirmation dialog added, on back press. --- lib/extensions/text_extensions.dart | 15 ++-- lib/extensions/widget_extensions.dart | 46 ++++++++--- .../common_widgets/app_filled_button.dart | 4 +- .../common_widgets/default_app_bar.dart | 16 +++- .../dialoge/acknowledge_work_dialog.dart | 67 ++++++++++++++++ .../swipe_module/dialoge/confirm_dialog.dart | 14 ++-- .../maintenance_request_main.dart | 76 ++++++++++--------- 7 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index 5a81bc5c..ea5496e3 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -164,13 +164,14 @@ extension CapExtension on String { String get allInCaps => toUpperCase(); - String get cleanupWhitespace => replaceAll(RegExp(r"\s+"), " "); - - String get capitalizeFirstOfEach => trim().isNotEmpty - ? trim().toLowerCase().split(" ").map((str) { - return str.trim()?.inCaps ?? ""; - }).join(" ") - : ""; + String get cleanupWhitespace => this;//replaceAll(RegExp(r"\s+"), " "); + + String get capitalizeFirstOfEach => this; + //trim().isNotEmpty + // ? trim().toLowerCase().split(" ").map((str) { + // return str.trim()?.inCaps ?? ""; + // }).join(" ") + // : ""; } extension FilesExtension on String { diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 0586f01a..23a5a6a1 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -4,6 +4,7 @@ import 'package:shimmer/shimmer.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/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../new_views/app_style/app_color.dart'; @@ -54,6 +55,26 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); + Widget handlePopScope(BuildContext _cxt, VoidCallback onSave) { + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) { + return; + } + showDialog( + context: _cxt, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: () => onSave(), + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + }, + child: this); + } + Widget toShimmer({bool isShow = true, double radius = 20}) => isShow ? Shimmer.fromColors( baseColor: const Color(0xffe8eff0), @@ -81,18 +102,19 @@ extension WidgetExtensions on Widget { ).toShadowContainer(context) : this; - Widget toShadowContainer(BuildContext context, {bool showShadow = true,double borderRadius = 14, bool withShadow = true, Color? backgroundColor, double padding = 16, EdgeInsets? paddingObject}) => withShadow - ? Container( - padding: paddingObject ?? EdgeInsets.all(padding), - width: double.infinity, - decoration: ShapeDecoration( - color: backgroundColor ?? AppColor.background(context), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius)), - shadows: showShadow ? [boxShadowR14] : null, - ), - child: this, - ) - : this; + Widget toShadowContainer(BuildContext context, {bool showShadow = true, double borderRadius = 14, bool withShadow = true, Color? backgroundColor, double padding = 16, EdgeInsets? paddingObject}) => + withShadow + ? Container( + padding: paddingObject ?? EdgeInsets.all(padding), + width: double.infinity, + decoration: ShapeDecoration( + color: backgroundColor ?? AppColor.background(context), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(borderRadius)), + shadows: showShadow ? [boxShadowR14] : null, + ), + child: this, + ) + : this; Widget bottomSheetContainer(BuildContext context, {EdgeInsets? padding}) => Container( clipBehavior: Clip.antiAlias, diff --git a/lib/new_views/common_widgets/app_filled_button.dart b/lib/new_views/common_widgets/app_filled_button.dart index 153f7431..87376c27 100644 --- a/lib/new_views/common_widgets/app_filled_button.dart +++ b/lib/new_views/common_widgets/app_filled_button.dart @@ -15,6 +15,7 @@ class AppFilledButton extends StatelessWidget { final Color? textColor; final bool showBorder; final double radius; + final int height; final bool disableButton; const AppFilledButton( @@ -25,6 +26,7 @@ class AppFilledButton extends StatelessWidget { this.icon, this.fontSize, this.loading = false, + this.height = 56, this.showBorder = false, this.disableButton = false, this.buttonColor, @@ -36,7 +38,7 @@ class AppFilledButton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 56.toScreenHeight, + height: height.toScreenHeight, width: maxWidth ? double.infinity : null, alignment: Alignment.center, decoration: BoxDecoration( diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index 6cc8bd5a..7d28abaa 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -4,6 +4,7 @@ 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/new_views/pages/land_page/land_page.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../app_style/app_color.dart'; @@ -12,8 +13,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { final List? actions; final Function? onBackPress; final bool showHomeActionButton; + final VoidCallback? onWillPopScope; - const DefaultAppBar({this.title, this.onBackPress, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); + const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -40,6 +42,18 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { title: Row( children: [ const Icon(Icons.arrow_back_ios).onPress(() { + if (onWillPopScope != null) { + showDialog( + context: context, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: onWillPopScope!, + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + return; + } if (onBackPress != null) { onBackPress!(); } else { diff --git a/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart new file mode 100644 index 00000000..81ee9a1d --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.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/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; + +class AcknowledgeWorkDialog extends StatelessWidget { + final String? title; + final String? message; + final String? okTitle; + final VoidCallback onSave; + final VoidCallback onDiscard; + + const AcknowledgeWorkDialog( + {Key? key, this.title, this.message = "To prevent the risk of losing your changes, Please confirm Save or Discard", this.okTitle, required this.onSave, required this.onDiscard}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder(), + insetPadding: const EdgeInsets.only(left: 21, right: 21), + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Confirm", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96), + ).paddingOnly(top: 16, bottom: 8), + message != null ? message!.heading5(context).custom(color: AppColor.neutral50) : const SizedBox(), + 28.height, + Row( + children: [ + AppFilledButton( + label: "Discard", + buttonColor: Colors.white54, + textColor: AppColor.red30, + height: 40, + showBorder: true, + onPressed: () { + Navigator.of(context).pop(); + onDiscard(); + }, + ).expanded, + 16.width, + AppFilledButton( + label: "Save", + onPressed: () { + Navigator.of(context).pop(); + onSave(); + }, + height: 40, + buttonColor: AppColor.green70, + ).expanded, + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart index 3e07310f..f8cfacfb 100644 --- a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart +++ b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart @@ -6,13 +6,13 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; class ConfirmDialog extends StatelessWidget { - final String ?title; - final String ?message; - final String ?okTitle; - final VoidCallback ?onTap; - final VoidCallback ?onCloseTap; + final String? title; + final String? message; + final String? okTitle; + final VoidCallback? onTap; + final VoidCallback? onCloseTap; - const ConfirmDialog({Key ?key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); + const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); @override Widget build(BuildContext context) { @@ -45,7 +45,7 @@ class ConfirmDialog extends StatelessWidget { ) ], ), - message!=null?message!.heading5(context).custom(color: AppColor.neutral70):const SizedBox(), + message != null ? message!.heading5(context).custom(color: AppColor.neutral70) : const SizedBox(), 28.height, AppFilledButton( label: okTitle ?? "OK", diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index e60383bb..a9dded6f 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -49,7 +49,12 @@ class _MaintenanceRequestFormState extends State with Si bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; return Scaffold( backgroundColor: AppColor.neutral110, - appBar: const DefaultAppBar(title: "CM Activity"), + appBar: DefaultAppBar( + title: "CM Activity", + onWillPopScope: () { + save(requestDetailProvider); + }, + ), body: Stack( children: [ DefaultTabController( @@ -97,48 +102,49 @@ class _MaintenanceRequestFormState extends State with Si label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label buttonColor: AppColor.primary10, onPressed: () async { - //TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. - // requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; - - if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { - int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( - ActivityMaintenanceTimers( - id: 0, - startTime: timer.startAt!.toIso8601String(), // Handle potential null - endTime: timer.endAt?.toIso8601String(), // Handle potential null - workingHours: ((durationInSecond) / 60 / 60), - ), - ); - }); - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - int status = -1; - if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { - status = await requestDetailProvider.createActivityMaintenanceRequest(); - } else { - status = await requestDetailProvider.updateActivityMaintenance(); - } - if (status == 200) { - requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); - Navigator.pop(context); - Navigator.pop(context); - } else { - Navigator.pop(context); - } - } - - // Handle button press + save(requestDetailProvider); }, ), ), ], ), - ); + ).handlePopScope(context, () { + save(requestDetailProvider); + }); }); } + void save(ServiceRequestDetailProvider requestDetailProvider) async { + if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( + ActivityMaintenanceTimers( + id: 0, + startTime: timer.startAt!.toIso8601String(), // Handle potential null + endTime: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + int status = -1; + if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { + status = await requestDetailProvider.createActivityMaintenanceRequest(); + } else { + status = await requestDetailProvider.updateActivityMaintenance(); + } + if (status == 200) { + requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); + Navigator.pop(context); + Navigator.pop(context); + } else { + Navigator.pop(context); + } + } + } + bool validate({required ActivityMaintenanceHelperModel model}) { if (model.activityStatus == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); From 53028580972bdeaf08940eb19de09ae01a1dad4d Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 12:38:56 +0300 Subject: [PATCH 09/36] confirmation dialog added on ppm & recurrent --- .../recurrent_work_order_view.dart | 11 ++++++++-- .../pages/user/ppm/update_ppm/update_ppm.dart | 20 ++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 8b3eb979..19574b31 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -48,7 +48,12 @@ class _RecurrentWorkOrderViewState extends State { Widget build(BuildContext context) { return Consumer(builder: (context, requestProvider, child) { return Scaffold( - appBar: DefaultAppBar(title: context.translation.recurrentWo), + appBar: DefaultAppBar( + title: context.translation.recurrentWo, + onWillPopScope: () { + _updateTask(context: context, status: 0); + }, + ), body: allRequestsProvider!.isLoading ? const ALoading() : requestProvider.recurrentWoData != null @@ -94,7 +99,9 @@ class _RecurrentWorkOrderViewState extends State { ], ) : NoDataFound(message: context.translation.noDataFound).center, - ); + ).handlePopScope(context, () { + _updateTask(context: context, status: 0); + }); }); } } diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index dc78915c..839a6090 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -9,7 +8,6 @@ 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/widget_extensions.dart'; -import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; @@ -44,8 +42,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { late PpmProvider ppmProvider; _onSubmit({required int status}) async { - - if(ppmProvider.validate()){ + if (ppmProvider.validate()) { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = []; for (var item in ppmProvider.ppmPlanAttachments) { @@ -67,7 +64,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { }); await ppmProvider.updateVisitByEngineer(status: status).whenComplete(() { - if(status==1){ + if (status == 1) { AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); allRequestsProvider.reset(); allRequestsProvider.getAllRequests(context, typeTransaction: 4); @@ -78,8 +75,6 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { Navigator.pop(context); }); } - - } @override @@ -115,7 +110,12 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.neutral110, - appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), + appBar: DefaultAppBar( + title: context.translation.preventiveMaintenance, + onWillPopScope: () { + _onSubmit(status: 0); + }, + ), key: _scaffoldKey, body: SafeArea( child: Column( @@ -212,6 +212,8 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ], ), ), - ); + ).handlePopScope(context, () { + _onSubmit(status: 0); + }); } } From 544dffc03fc3009617d2113be219be1d0c49cc6f Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 13:01:07 +0300 Subject: [PATCH 10/36] chart updated overview screen. --- .../widgets/progress_fragment.dart | 79 +++++++++---------- pubspec.lock | 24 ++---- pubspec.yaml | 2 +- 3 files changed, 47 insertions(+), 58 deletions(-) diff --git a/lib/dashboard_latest/widgets/progress_fragment.dart b/lib/dashboard_latest/widgets/progress_fragment.dart index 994d13d7..8f60be60 100644 --- a/lib/dashboard_latest/widgets/progress_fragment.dart +++ b/lib/dashboard_latest/widgets/progress_fragment.dart @@ -151,10 +151,9 @@ // import 'package:flutter/material.dart'; +import 'package:pie_chart/pie_chart.dart'; import 'package:provider/provider.dart'; -import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; -import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; @@ -212,46 +211,44 @@ class ProgressFragment extends StatelessWidget { child: Stack( alignment: Alignment.center, children: [ - SfCircularChart( - tooltipBehavior: TooltipBehavior( - enable: true, - // elevation: 2, - color: context.isDark ? const Color(0xFF111427) : const Color(0xffF7F9FB), - textStyle: context.isDark ? null : const TextStyle(color: Colors.black87, fontSize: 12), + PieChart( + dataMap: {for (var v in chartData) v.x: v.y}, + animationDuration: const Duration(milliseconds: 800), + chartLegendSpacing: 32, + chartRadius: MediaQuery.of(context).size.width / 3.2, + colorList: chartData.map((element) => element.color).toList(), + initialAngleInDegree: 270, + chartType: ChartType.ring, + ringStrokeWidth: 32, + centerWidget: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.total, + style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + Text( + "$total", + style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + ], + ), + legendOptions: const LegendOptions( + showLegendsInRow: false, + legendPosition: LegendPosition.right, + showLegends: true, + legendTextStyle: TextStyle( + fontWeight: FontWeight.w500, ), - legend: const Legend( - //isVisible: true, - ), - series: [ - DoughnutSeries( - dataSource: chartData, - radius: "100%", - innerRadius: "60%", - pointColorMapper: (ChartData data, _) => data.color, - xValueMapper: (ChartData data, _) => data.x, - yValueMapper: (ChartData data, _) => data.y, - dataLabelMapper: (ChartData data, _) => data.x, - dataLabelSettings: DataLabelSettings( - margin: const EdgeInsets.all(8), - isVisible: true, - textStyle: TextStyle(color: context.isDark ? Colors.white : AppColor.neutral20, fontSize: 12, fontWeight: FontWeight.w500), - labelPosition: ChartDataLabelPosition.outside, - ), - ) - ]).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(0).toShadowContainer(context), - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.total, - style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), - ), - Text( - "$total", - style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), - ), - ], - ), + ), + chartValuesOptions: const ChartValuesOptions( + showChartValueBackground: false, + showChartValues: false, + showChartValuesInPercentage: false, + showChartValuesOutside: false, + decimalPlaces: 1, + ), + ).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(0).toShadowContainer(context), ], ), ), diff --git a/pubspec.lock b/pubspec.lock index 402dbb06..4546b9fd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1213,6 +1213,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + pie_chart: + dependency: "direct main" + description: + name: pie_chart + sha256: "58e6a46999ac938bfa1c3e5be414d6e149f037647197dca03ba3614324c12c82" + url: "https://pub.dev" + source: hosted + version: "5.4.0" pinput: dependency: "direct main" description: @@ -1506,22 +1514,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" - syncfusion_flutter_charts: - dependency: "direct main" - description: - name: syncfusion_flutter_charts - sha256: a755274a8786b200b7a05f7414168cd5858871db74d0f1de2e57b20a8aaeb7a4 - url: "https://pub.dev" - source: hosted - version: "26.2.14" - syncfusion_flutter_core: - dependency: transitive - description: - name: syncfusion_flutter_core - sha256: "6e67726b85812afc7105725a23620b876ab7f6b04b8410e211330ffb8c2cdbe8" - url: "https://pub.dev" - source: hosted - version: "26.2.14" synchronized: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8cc4034f..2bcf8f5b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,11 +79,11 @@ dependencies: image_cropper: ^8.0.2 flutter_timezone: ^3.0.1 device_calendar: ^4.3.3 + pie_chart: ^5.4.0 badges: ^3.1.1 # buttons_tabbar: ^1.1.2 flutter_custom_month_picker: ^0.1.3 - syncfusion_flutter_charts: ^26.2.14 local_auth: ^2.3.0 google_api_availability: ^5.0.0 huawei_push: ^6.5.0+300 From 6b93479170be31ac7f6b82ef4cc329430bbbc07f Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Tue, 25 Mar 2025 13:06:03 +0300 Subject: [PATCH 11/36] work order attachment added --- lib/controllers/api_routes/urls.dart | 2 + .../workorder/work_order_helper_models.dart | 8 ++++ .../service_request_detail_provider.dart | 28 +++++++++++ .../utilities/service_request_utils.dart | 1 - .../service_request_detail_view.dart | 46 +++++++++++++++---- .../components/internal_request.dart | 7 +++ .../service_request_detail_main_view.dart | 4 +- 7 files changed, 83 insertions(+), 13 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index aaba34ee..3481dc79 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -76,6 +76,8 @@ class URLs { static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; + static get uploadWorkOrderAttachmentsUrl=> '$_baseUrl/ServiceRequest/UploadAttachmentsWorkOrder'; + static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; diff --git a/lib/models/helper_data_models/workorder/work_order_helper_models.dart b/lib/models/helper_data_models/workorder/work_order_helper_models.dart index f851e5c3..2eae7084 100644 --- a/lib/models/helper_data_models/workorder/work_order_helper_models.dart +++ b/lib/models/helper_data_models/workorder/work_order_helper_models.dart @@ -41,6 +41,14 @@ class WorkOrderHelperModel { } return data; } + Map toUploadAttachmentJson(int? workOrderId,List? workOrderAttachments) { + final Map data = {}; + data['workOrderId'] = workOrderId; + if (workOrderAttachments != null) { + data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList(); + } + return data; + } } class WorkOrderAttachments { diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index ffaca293..fad2e78a 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:http/src/response.dart'; @@ -14,6 +15,7 @@ import 'package:test_sa/models/new_models/arrival_verification_type_model.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; class ServiceRequestDetailProvider extends ChangeNotifier { final pageItemNumber = 10; @@ -226,6 +228,32 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + //upload workorder attachment by engineer.. + Future addWorkOrderAttachment({required int woId, required List attachments}) async { + try { + List woAttachments = []; + for (var file in attachments) { + String fileName = ServiceRequestUtils.isLocalUrl(file.path) ? ("${file.path.split("/").last}|${base64Encode(File(file.path).readAsBytesSync())}") : file.path; + woAttachments.add(WorkOrderAttachments(id: 0, name: fileName)); + } + + isLoading = true; + notifyListeners(); + final response = await ApiManager.instance.post(URLs.uploadWorkOrderAttachmentsUrl, body: WorkOrderHelperModel().toUploadAttachmentJson(woId, woAttachments)); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + } + isLoading = false; + notifyListeners(); + } catch (e) { + log("getWorkOrder [error] : $e"); + isLoading = false; + notifyListeners(); + return null; + } + } + //getQrCode...... Future getQrCode({required int workOrderId}) async { try { diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index b18f5ee8..9deccbfa 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -457,7 +457,6 @@ class ConfirmArrivalNotificationModel { this.accept, }); - // Factory constructor to create an instance from a Map (e.g., JSON) factory ConfirmArrivalNotificationModel.fromJson(Map json) { return ConfirmArrivalNotificationModel( transactionType: json['transactionType'], diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index e804e248..61111bdd 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.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/controllers/api_routes/urls.dart'; @@ -19,13 +22,27 @@ import 'package:test_sa/service_request_latest/views/components/asset_detail_car import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart'; import 'package:test_sa/service_request_latest/views/components/timer_widget.dart'; import 'package:test_sa/service_request_latest/views/forms/asset_retired/asset_retired.dart'; -import 'package:test_sa/views/widgets/images/files_list.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; -class ServiceRequestDetailView extends StatelessWidget { - const ServiceRequestDetailView({Key? key}) : super(key: key); +class ServiceRequestDetailView extends StatefulWidget { + ServiceRequestDetailView({Key? key}) : super(key: key); + + @override + State createState() => _ServiceRequestDetailViewState(); +} + +class _ServiceRequestDetailViewState extends State { + List _workOrderAttachments = []; + + @override + void initState() { + ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? []; + super.initState(); + } @override Widget build(BuildContext context) { @@ -45,7 +62,7 @@ class ServiceRequestDetailView extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider), + workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), 20.height, @@ -69,7 +86,7 @@ class ServiceRequestDetailView extends StatelessWidget { }); } - Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider) { + Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider, ServiceRequestDetailProvider requestProvider) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -230,11 +247,20 @@ class ServiceRequestDetailView extends StatelessWidget { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], - if (workOrder.workOrderAttachments.isNotEmpty ?? false) ...[ - 8.height, - const Divider().defaultStyle(context), - FilesList(images: workOrder.workOrderAttachments.map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()), - ], + + 8.height, + const Divider().defaultStyle(context), + MultiFilesPicker( + label: context.translation.attachments, + files: _workOrderAttachments, + buttonColor: AppColor.primary10, + onlyImages: false, + buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), + onChange: (attachment) { + requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment); + }, + ), + if (workOrder.voiceNote?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 16.height, diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart index c611ec97..4ea023f1 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; @@ -32,11 +34,15 @@ class _InternalMaintenanceRequestState extends State final TextEditingController _travellingHoursController = TextEditingController(); Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1}); + + @override void initState() { _requestDetailProvider = Provider.of(context, listen: false); super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { + //need to confirm with backend api data... + // _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList()); _travellingHoursController.text = _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : ''; }); @@ -280,6 +286,7 @@ class _InternalMaintenanceRequestState extends State requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; }, ), + ], ), ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), diff --git a/lib/service_request_latest/views/service_request_detail_main_view.dart b/lib/service_request_latest/views/service_request_detail_main_view.dart index 13e6e432..4ea8d260 100644 --- a/lib/service_request_latest/views/service_request_detail_main_view.dart +++ b/lib/service_request_latest/views/service_request_detail_main_view.dart @@ -128,10 +128,10 @@ class _ServiceRequestDetailMainState extends State { ), ), 12.height, - const TabBarView( + TabBarView( children: [ ServiceRequestDetailView(), - HistoryLogView(), + const HistoryLogView(), ], ).expanded, ], From 99ef704913755ca1d530f1583e26b651498516fd Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 14:43:12 +0300 Subject: [PATCH 12/36] rename points done --- lib/dashboard_latest/dashboard_provider.dart | 8 ++++---- .../new_models/work_order_detail_model.dart | 8 ++++---- .../my_request/all_requests_filter_page.dart | 16 +++++++++++----- .../pages/land_page/requests/ppm_item_view.dart | 6 ++++-- .../requests/service_request_item_view.dart | 10 ++++++---- .../views/components/asset_detail_card.dart | 2 +- .../forms/asset_retired/verify_asset_detail.dart | 15 ++++++++------- lib/views/pages/user/ppm/ppm_details_page.dart | 4 ++-- .../components/task_info_widget.dart | 2 +- .../pages/user/ppm/update_ppm/wo_info_form.dart | 5 +---- 10 files changed, 42 insertions(+), 34 deletions(-) diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index d763092d..db07f571 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -367,16 +367,16 @@ class CategoryTabs { if (userType == UsersTypes.engineer) { // tabs.add(CategoryTabs(label: 'Upcoming', tag: 0, id: 0)); // tabs.add(CategoryTabs('Open', 1)); - tabs.add(CategoryTabs(label: 'UnAssigned Open', tag: 1, id: 1)); - tabs.add(CategoryTabs(label: 'Assigned Open', tag: 1, id: 2)); + tabs.add(CategoryTabs(label: 'UnAssigned', tag: 1, id: 1)); + tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2)); tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3)); tabs.add(CategoryTabs(label: 'Completed', tag: 3, id: 4)); return tabs; } - tabs.add(CategoryTabs(label: 'Open Request', tag: 1, id: 2)); + tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2)); tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3)); - tabs.add(CategoryTabs(label: 'Upcoming', tag: 3, id: 1)); + tabs.add(CategoryTabs(label: 'Pending Acknowledgement', tag: 3, id: 1)); tabs.add(CategoryTabs(label: 'Canceled', tag: 6, id: 4)); return tabs; } diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index 8117d902..d98565e3 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -281,7 +281,7 @@ class WorkOrderAssignedEmployee { required this.languageId, }); - dynamic userId; + String userId; String? userName; String? email; int? languageId; @@ -357,7 +357,7 @@ class Activities { activityStatus = json['activityStatus'] != null ? Lookup.fromJson(json['activityStatus']) : null; activityMaintenance = json['activityMaintenance'] != null ? ActivityMaintenance.fromJson(json['activityMaintenance']) : null; if (activityMaintenance != null) { - activityType = 'Maintenance Request'; + activityType = 'CM Activity'; } activitySparePart = json['activitySparePart'] != null ? ActivitySparePart.fromJson(json['activitySparePart']) : null; @@ -504,9 +504,9 @@ class WorkOrderContactPerson { String? name; String? employeeId; String? position; - dynamic extension; + String extension; String? email; - dynamic mobilePhone; + String mobilePhone; WorkOrderAssignedEmployee? contactUser; factory WorkOrderContactPerson.fromJson(Map json) { 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 0ce17697..684eb99d 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 @@ -1,9 +1,11 @@ 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/models/search_all_requests_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -43,6 +45,7 @@ class _AllRequestsFilterPageState extends State { @override Widget build(BuildContext context) { + bool isEngineer = (Provider.of(context, listen: false).user?.type) == UsersTypes.engineer; if (search == null) { search = SearchAllRequestsModel( requestNumber: SearchByRequestNumberModel(context, controller: TextEditingController()), @@ -59,14 +62,17 @@ class _AllRequestsFilterPageState extends State { context.translation.gasRefill: 2, context.translation.deviceTransfer: 3, context.translation.preventiveMaintenance: 4, - context.translation.recurrentWo: 5, }; + if (isEngineer) { + types.addAll({context.translation.recurrentWo: 5}); + } final statuses = { - context.translation.allRequests: 0, + "All WO": 0, context.translation.open: 1, context.translation.inProgress: 2, context.translation.completed: 4, context.translation.closed: 3, + "Canceled": 5, }; return Scaffold( appBar: DefaultAppBar( @@ -99,7 +105,7 @@ class _AllRequestsFilterPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - context.translation.requestStatus.heading5(context), + "WO Status".heading5(context), 8.height, RequestsTypeFilter( initialValues: search?.statuses ?? [], @@ -116,7 +122,7 @@ class _AllRequestsFilterPageState extends State { }, ), 16.height, - context.translation.typeOfRequest.heading5(context), + "Type of WO".heading5(context), 8.height, RequestsTypeFilter( initialValues: search?.typeTransaction ?? [], @@ -155,7 +161,7 @@ class _AllRequestsFilterPageState extends State { ], ), 16.height, - "Archived Requests".heading5(context), + "Archived WO".heading5(context), // 8.height, Row( children: [ diff --git a/lib/new_views/pages/land_page/requests/ppm_item_view.dart b/lib/new_views/pages/land_page/requests/ppm_item_view.dart index a4569881..ba30b5c7 100644 --- a/lib/new_views/pages/land_page/requests/ppm_item_view.dart +++ b/lib/new_views/pages/land_page/requests/ppm_item_view.dart @@ -49,10 +49,11 @@ class PpmItemView extends StatelessWidget { 8.height, (requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context), 8.height, + '${context.translation.assetName}: ${requestData!.assetName}'.bodyText(context), '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + 'PM No: ${requestData!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, @@ -99,10 +100,11 @@ class PpmItemView extends StatelessWidget { 8.height, (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), 8.height, + '${context.translation.assetName}: ${requestDetails!.assetName}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + 'PM No: ${requestDetails!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/new_views/pages/land_page/requests/service_request_item_view.dart b/lib/new_views/pages/land_page/requests/service_request_item_view.dart index e9b09bbc..928dc950 100644 --- a/lib/new_views/pages/land_page/requests/service_request_item_view.dart +++ b/lib/new_views/pages/land_page/requests/service_request_item_view.dart @@ -55,7 +55,7 @@ class ServiceRequestItemView extends StatelessWidget { '${context.translation.assetName}: ${requestData!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), // '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + 'CM Number: ${requestData!.requestNo}'.bodyText(context), if (requestData?.statusName == 'Canceled') ...[ '${context.translation.rejectionReason}: ${requestData!.rejectReason}'.bodyText(context), ], @@ -110,10 +110,12 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, (requestDetails!.nameOfType ?? context.translation.correctiveMaintenance).heading5(context), 8.height, - '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + + // '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), + 'CM Number: ${requestDetails!.requestNo}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), - '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + 8.height, Row( // mainAxisSize: MainAxisSize.min, diff --git a/lib/service_request_latest/views/components/asset_detail_card.dart b/lib/service_request_latest/views/components/asset_detail_card.dart index f86b30ad..2ba75907 100644 --- a/lib/service_request_latest/views/components/asset_detail_card.dart +++ b/lib/service_request_latest/views/components/asset_detail_card.dart @@ -47,7 +47,7 @@ class AssetDetailCard extends StatelessWidget { ]), 6.height, Text( - context.translation.assetSituation, + "Work Order Details", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), Text( diff --git a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart index c0f9942e..25c26a43 100644 --- a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart +++ b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -215,12 +214,14 @@ class _VerifyAssetDetailsState extends State with TickerProv } }, ), - 12.height, - context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), - 8.height, - requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null - ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120) - : const SizedBox(), + if (requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null) ...[ + 12.height, + context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), + 8.height, + requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null + ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120) + : const SizedBox(), + ] ], ).toShadowContainer(context).paddingAll(16), ).expanded, diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index 107cc4d7..ecd40444 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -97,7 +97,7 @@ class _PpmDetailsPageState extends State { // '${context.translation.expectDate}: ${planPreventiveVisit.expectedDate?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, '${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, const Divider().defaultStyle(context), - '${context.translation.engineerName}: ${planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText(context), //todo @baha, + '${context.translation.assignedEmployee}: ${planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText(context), //todo @baha, '${context.translation.site}: ${planPreventiveVisit.siteName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, '${context.translation.building}: ${planPreventiveVisit.buildingName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, '${context.translation.floor}: ${planPreventiveVisit.floorName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, @@ -112,7 +112,7 @@ class _PpmDetailsPageState extends State { await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); getVisitData(); }, - label: context.translation.updateRequest, + label: context.translation.updateWorkOrder, ).paddingAll(16) ]); }), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 407449bc..4e418aa3 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -40,7 +40,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { 2.height, '${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.site}: ${model!.site!.siteName!}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.assignedEmployee}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), ], ).toShadowContainer(context), diff --git a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart index a5e23ea4..b1b44b66 100644 --- a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart @@ -78,9 +78,6 @@ class _WoInfoFormState extends State { '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), //need to add in translation it's suggestion from ahmed.. 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' .bodyText2(context) .custom(color: AppColor.neutral120), @@ -248,7 +245,7 @@ class _WoInfoFormState extends State { _timerWidget(context, totalWorkingHours), 8.height, AppTextFormField( - labelText: context.translation.callComments, + labelText: context.translation.comment, backgroundColor: AppColor.neutral100, showShadow: false, initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), From bbc584800ad10f3deefebe477302347dc82b823c Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 25 Mar 2025 15:05:07 +0300 Subject: [PATCH 13/36] CM contact info added. --- .../service_request_detail_view.dart | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index 61111bdd..74512830 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -65,6 +64,8 @@ class _ServiceRequestDetailViewState extends State { workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), + 12.height, + contactInfoCard(context, requestProvider.currentWorkOrder!.data!), 20.height, ], ), @@ -334,6 +335,55 @@ class _ServiceRequestDetailViewState extends State { ).toShadowContainer(context, padding: 0); } + Widget contactInfoCard(BuildContext context, WorkOrderData workOrder) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact Info", + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${workOrder.workOrderContactPerson[index].name}', + style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + Text( + '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + 'Job: ${workOrder.workOrderContactPerson[index].position}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + 'Extension: ${workOrder.workOrderContactPerson[index].extension}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + ], + ), + separatorBuilder: (cxt, index) => const Divider().defaultStyle(context), + itemCount: workOrder.workOrderContactPerson.length), + ], + ).toShadowContainer(context, padding: 16); + } + Widget assetRetiredButton({required BuildContext context}) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth), From 5825464ed54449399e25392c941a719842d720e3 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 26 Mar 2025 11:00:49 +0300 Subject: [PATCH 14/36] ppm wo inspection back button added. --- .../pages/user/ppm/update_ppm/update_ppm.dart | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index 839a6090..51255a31 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -158,6 +158,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ), ), TabBarView( + physics: const NeverScrollableScrollPhysics(), children: [ WoInfoForm( planPreventiveVisit: _planPreventiveVisit, @@ -183,6 +184,24 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ).expanded, Row( children: [ + if (tabIndex == 1) ...[ + AppFilledButton( + buttonColor: _tabController!.index == 0 ? null:AppColor.background(context), + textColor: _tabController!.index == 0 ? null: AppColor.blueStatus(context), + showBorder: true, + disableButton: _tabController!.index == 0, + onPressed: () { + if (_tabController!.index == 0) { + return; + } + _tabController?.animateTo(_tabController!.index - 1); + setState(() {}); + return; + }, + label: context.translation.back, + ).expanded, + 8.width, + ], AppFilledButton( buttonColor: AppColor.white60, textColor: AppColor.neutral50, @@ -191,7 +210,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { }, label: context.translation.save, ).expanded, - 16.width, + 8.width, AppFilledButton( onPressed: () { if (tabIndex == 0) { From e13a7c96349e016159a89f0c03f859b06a840225 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 26 Mar 2025 11:18:43 +0300 Subject: [PATCH 15/36] rename text --- .../views/forms/spare_part/spare_part_request.dart | 2 +- lib/views/pages/user/requests/pending_requests_screen.dart | 2 +- .../widgets/bottom_sheets/pending_request_bottom_sheet.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 3df20c4c..4f93a950 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -245,7 +245,7 @@ class _SparePartRequestState extends State with TickerProvider controller: _descriptionController, showSpeechToText: true, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, - labelText: context.translation.description, + labelText: "Engineer Comment", alignLabelWithHint: true, showWithoutDecoration: true, textInputType: TextInputType.multiline, diff --git a/lib/views/pages/user/requests/pending_requests_screen.dart b/lib/views/pages/user/requests/pending_requests_screen.dart index 4ae44fa5..ee99a490 100644 --- a/lib/views/pages/user/requests/pending_requests_screen.dart +++ b/lib/views/pages/user/requests/pending_requests_screen.dart @@ -18,7 +18,7 @@ class PendingServiceRequestScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: DefaultAppBar(title: "Pending Requests (${pendingAssetServiceRequest.details!.length})"), + appBar: DefaultAppBar(title: "Pending WOs (${pendingAssetServiceRequest.details!.length})"), body: ListView.separated( itemCount: pendingAssetServiceRequest.details!.length, padding: const EdgeInsets.all(16), diff --git a/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart b/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart index f22c2d1b..84b98782 100644 --- a/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart +++ b/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart @@ -25,7 +25,7 @@ class PendingRequestBottomSheet extends StatelessWidget { "Alert!".heading4(context), 12.height, Text( - "${pendingAssetServiceRequest.details!.length} pending service requests found", + "${pendingAssetServiceRequest.details!.length} pending corrective maintenance found", style: TextStyle( fontSize: 16.toScreenWidth, fontWeight: FontWeight.w500, From 68c4df0c14de143ff1260fbee79e35357505d180 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 26 Mar 2025 16:12:02 +0300 Subject: [PATCH 16/36] validateAssetSituation check removed handled from backend --- .../service_request_bottomsheet.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart index 150b59d8..44f7a9a6 100644 --- a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart +++ b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart @@ -837,14 +837,14 @@ class ServiceRequestBottomSheet { } static bool validateAssetSituation(ServiceRequestDetailProvider requestDetailProvider) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) { - Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG); - return false; - } - } - } + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) { + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) { + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) { + // Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG); + // return false; + // } + // } + // } return true; } From a66215ef8be989775a4a39a54dd927f7368d096d Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 27 Mar 2025 14:03:30 +0300 Subject: [PATCH 17/36] bug fixes --- lib/controllers/api_routes/urls.dart | 8 +- lib/l10n/app_ar.arb | 10 +- lib/l10n/app_en.arb | 10 +- .../new_models/work_order_detail_model.dart | 25 +- .../plan_preventive_visit_model.dart | 49 +- lib/models/ppm/recurrent_wo.dart | 5 + lib/new_views/app_style/app_color.dart | 1 + .../service_request_detail_provider.dart | 15 +- .../action_button/footer_action_button.dart | 16 +- .../components/activities_list_view.dart | 55 ++- .../views/components/asset_detail_card.dart | 2 + .../service_request_bottomsheet.dart | 2 +- .../service_request_detail_view.dart | 68 ++- .../components/assistant_employee_card.dart | 6 + .../components/external_request.dart | 366 +++++++-------- .../components/internal_request.dart | 443 +++++++++--------- .../maintenance_request_main.dart | 2 +- .../forms/spare_part/spare_part_request.dart | 2 +- .../components/room_inspection_card.dart | 14 +- .../components/task_info_widget.dart | 30 +- .../recurrent_work_order_view.dart | 38 +- .../ppm_calibration_tools_form.dart | 1 + .../user/ppm/update_ppm/wo_info_form.dart | 44 +- .../asset_detail_bottom_sheet.dart | 4 +- .../widgets/images/multi_image_picker.dart | 320 ++++++++++++- 25 files changed, 1022 insertions(+), 514 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 3481dc79..900aafd6 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -3,12 +3,12 @@ class URLs { static const String appReleaseBuildNumber = "14"; // 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"; // new V3 apis static String _host = host1; diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index b8cb09a2..1becd2e9 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -549,6 +549,14 @@ "attachments": "المرفقات", "supplierName": "اسم المورد", "externalEngineerName": "اسم المهندس الخارجي", - "telephone": "الهاتف" + "telephone": "الهاتف", + "arrivedDate": "تاريخ الوصول", + "closedDate": "تاريخ الإغلاق", + "since": "منذ", + "rejectionDetails": "تفاصيل الرفض", + "part": "جزء", + "closedDate": "تاريخ الإغلاق", + "creationDate": "تاريخ الإنشاء" + } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 07b5420a..56f13e64 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -552,5 +552,13 @@ "attachments": "Attachments", "supplierName": "Supplier Name", "externalEngineerName": "External Engineer Name", - "telephone": "Telephone" + "telephone": "Telephone", + "arrivedDate": "Arrived Date", + "closedDate": "Closed Date", + "since": "Since", + "rejectionDetails": "Rejection Details", + "part": "Part", + "closedDate": "Closed Date", + "creationDate": "Creation Date" + } \ No newline at end of file diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index 8117d902..b1c134c0 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -84,6 +84,13 @@ class WorkOrderData { required this.totalWorkingHours, this.needAVisitComment, this.needAVisitDateTime, + this.iHaveArrivedDate, + this.rejectReason, + this.closedDate, + this.since, + this.cmFrame, + this.lastComment, + this.callResponse, required this.workOrderHistory, required this.activities, required this.activityAssetToBeRetireds, @@ -127,9 +134,18 @@ class WorkOrderData { Lookup? failureReasone; FaultDescription? faultDescription; Lookup? solution; + Lookup? cmFrame; + + //cmComments String? totalWorkingHours; DateTime? needAVisitDateTime; String? needAVisitComment; + String? iHaveArrivedDate; + String? closedDate; + Lookup? rejectReason; + String? lastComment; // need to replace with reject comments. + String? callResponse; // need to replace with reject comments. + int? since; List workOrderHistory; List activities; List activityAssetToBeRetireds; @@ -150,6 +166,13 @@ class WorkOrderData { floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]), department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]), room: json["room"], + lastComment: json["lastComment"], + callResponse: json["callResponse"], + iHaveArrivedDate: json["iHaveArrivedDate"], + closedDate: json["closedDate"], + cmFrame: json["cmFrame"] == null ? null : Lookup.fromJson(json["cmFrame"]), + rejectReason: json["rejectReason"] == null ? null : Lookup.fromJson(json["rejectReason"]), + since: json['since'], assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]), assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]), lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null, @@ -174,7 +197,7 @@ class WorkOrderData { failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]), faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]), solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]), - totalWorkingHours: (json["totalWorkingHours"] ??"").toString(), + totalWorkingHours: (json["totalWorkingHours"] ?? "").toString(), workOrderHistory: json["workOrderHistory"] == null ? [] : List.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))), activities: json["activities"] == null ? [] : List.from(json["activities"]!.map((x) => Activities.fromJson(x))), needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""), diff --git a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart index 82c9e43d..1dcb94f6 100644 --- a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart +++ b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/widgets.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -24,6 +25,8 @@ class PlanPreventiveVisit { String? departmentName; String? roomName; String? fromDate; + String? creationDate; + String? closedDate; String? toDate; AssignedEmployee? assignedEmployee; DateTime? acutalDateOfVisit; @@ -65,6 +68,8 @@ class PlanPreventiveVisit { this.departmentName, this.roomName, this.fromDate, + this.creationDate, + this.closedDate, this.toDate, this.assignedEmployee, this.acutalDateOfVisit, @@ -105,6 +110,8 @@ class PlanPreventiveVisit { departmentName = json['departmentName']; roomName = json['roomName']; fromDate = json['fromDate']; + creationDate = json['creationDate']; + closedDate = json['closedDate']; toDate = json['toDate']; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null; @@ -526,27 +533,27 @@ class PlanPreventiveVisit { // } // } -class Asset { - num? id; - String? assetNumber; - String? assetSerialNo; - - Asset({this.id, this.assetNumber, this.assetSerialNo}); - - Asset.fromJson(Map json) { - id = json['id']; - assetNumber = json['assetNumber']; - assetSerialNo = json['assetSerialNo']; - } - - Map toJson() { - final Map data = Map(); - data['id'] = this.id; - data['assetNumber'] = this.assetNumber; - data['assetSerialNo'] = this.assetSerialNo; - return data; - } -} +// class Asset { +// num? id; +// String? assetNumber; +// String? assetSerialNo; +// +// Asset({this.id, this.assetNumber, this.assetSerialNo}); +// +// Asset.fromJson(Map json) { +// id = json['id']; +// assetNumber = json['assetNumber']; +// assetSerialNo = json['assetSerialNo']; +// } +// +// Map toJson() { +// final Map data = Map(); +// data['id'] = this.id; +// data['assetNumber'] = this.assetNumber; +// data['assetSerialNo'] = this.assetSerialNo; +// return data; +// } +// } class AssignedEmployee { String? userId; diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index 4844ce65..c8161054 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -53,6 +53,8 @@ class RecurrentWoData { TimerModel? recurrentWoTimerModel = TimerModel(); double? totalWorkingHours = 0.0; List? timerModelList = []; + String? comment; + RecurrentWoData( {this.id, @@ -70,6 +72,7 @@ class RecurrentWoData { this.planRecurrentMedicalTaskRooms, this.planRecurrentTaskTimers, this.timerModelList, + this.comment, this.totalWorkingHours}); RecurrentWoData.fromJson(Map json) { @@ -84,6 +87,7 @@ class RecurrentWoData { floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]); department = json["department"] == null ? null : Lookup.fromJson(json["department"]); room = json["room"] == null ? null : Lookup.fromJson(json["room"]); + comment = json["comment"]; if (json['planRecurrentMedicalTaskRooms'] != null) { planRecurrentMedicalTaskRooms = []; json['planRecurrentMedicalTaskRooms'].forEach((v) { @@ -114,6 +118,7 @@ class RecurrentWoData { } data['id'] = id; data['statusValue'] = status; + data['comment'] = comment; if (planRecurrentTaskTimers != null) { data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 571e4f06..4e4421fe 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -79,6 +79,7 @@ class AppColor { static const Color orange50 = Color(0xffCC9B14); static const Color orange60 = Color(0xff886400); static const Color orange70 = Color(0xffFFC945); + static const Color orange80 = Color(0xff65531B); // static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff1FA269) : green50; static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green70.withOpacity(.5); diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index fad2e78a..fc989218 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -185,7 +185,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier { notifyListeners(); } - //create workOrder nurse ..... + bool _isReadOnlyRequest = false; + + bool get isReadOnlyRequest => _isReadOnlyRequest; + + set isReadOnlyRequest(bool value) { + _isReadOnlyRequest = value; + notifyListeners(); + } //create workOrder nurse ..... + Future createWorkOrder() async { isLoading = true; notifyListeners(); @@ -217,6 +225,11 @@ class ServiceRequestDetailProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + if (currentWorkOrder?.data?.status?.id == 3498) { + isReadOnlyRequest = true; + } else { + isReadOnlyRequest = false; + } } isLoading = false; notifyListeners(); diff --git a/lib/service_request_latest/views/components/action_button/footer_action_button.dart b/lib/service_request_latest/views/components/action_button/footer_action_button.dart index 789fe025..34446263 100644 --- a/lib/service_request_latest/views/components/action_button/footer_action_button.dart +++ b/lib/service_request_latest/views/components/action_button/footer_action_button.dart @@ -8,6 +8,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/work_order_next_step.dart'; import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart'; +import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -34,10 +35,10 @@ class FooterActionButton { {required WorkOrderNextStepEnum workOrderNextStepStatus, List activities = const [], required BuildContext context, + Lookup? status, required UserProvider userProvider, bool isEmpIsAssigned = false}) { ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - bool showMarkAsFixedButton = activities.isEmpty ? false : activities.any((object) => object.activityStatus!.value == 14 || object.activityStatus!.value == 19); if (userProvider.user?.type == UsersTypes.engineer) { if (workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe && isEmpIsAssigned) return const SizedBox(); @@ -58,6 +59,19 @@ class FooterActionButton { // TODO: Handle this case. case WorkOrderNextStepEnum.nTakeAction: // const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: ''); + //Need to add enum for these values in future instead of static values.. + + if (requestDetailProvider.isReadOnlyRequest) { + return footerContainer( + child: AppFilledButton( + label: context.translation.activities, + buttonColor: AppColor.neutral50, + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const ActivitiesListView())); + }, + ), + ); + } return footerContainer( child: AppFilledButton( label: context.translation.close, diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 81e8cc4e..6793817a 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -68,7 +68,7 @@ class _ActivitiesListViewState extends State { //backgroundColor: const Color(0xfff8f9fb), body: Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { activities = requestDetailProvider.currentWorkOrder!.data!.activities; - requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty? activities.last.id :-1)!; + requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty ? activities.last.id : -1)!; if (activities.isNotEmpty && (activities.last.activityStatus!.value == 14 || activities.last.activityStatus!.value == 19)) { disableNewActivity = true; } else { @@ -165,7 +165,7 @@ class _ActivitiesListViewState extends State { // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), backgroundColor: AppColor.primary10, ), - "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), + // "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3) Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -225,11 +225,6 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), 2.height, -//TODO description text not in api. -// Text( -// '${context.translation.date}: ${activity.currentSituation?.date}', -// style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), -// ), if (activity.activitySparePart?.comment?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 2.height, @@ -245,11 +240,26 @@ class _ActivitiesListViewState extends State { ], ], ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { -//TODO write onview detail method.. -// Navigator.push( -// context, -// MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activity, serviceRequest: ServiceRequest())), -// ); + // if(requestDetailProvider.currentWorkOrder?.data?.status?.id ==3498){ + // requestDetailProvider.sparePartHelperModel = SparePartHelperModel( + // id: activity.id, + // workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, + // comment: activity.activitySparePart?.comment, + // sparePartAttachments: activity.activitySparePart?.acitiySparePartAttachments ?? [], + // activityStatus: activity.activityStatus, + // sparePart: SparePart( + // id: activity.activitySparePart?.partCatalogItem?.id, + // partName: activity.activitySparePart?.partCatalogItem?.partName, + // partNo: activity.activitySparePart?.partCatalogItem?.partNumber, + // oracleCode: activity.activitySparePart?.partCatalogItem?.oracleCode), + // quantity: activity.activitySparePart?.quantity, + // activityStatusId: activity.activityStatus?.id, + // ); + // requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel); + // Navigator.of(context).push(MaterialPageRoute( + // builder: (_) => const SparePartRequest(), + // )); + // } }); } @@ -272,7 +282,7 @@ class _ActivitiesListViewState extends State { // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), backgroundColor: AppColor.primary10, ), - "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), + // "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3) Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -308,7 +318,7 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), 2.height, - if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ + if (activity.activityMaintenance?.assistantEmployees != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ Text( '${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}', style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), @@ -329,8 +339,21 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), ], + //need to add all info here... + // if(requestDetailProvider.currentWorkOrder?.data?.status?.id==3498)...[ + // const Divider().defaultStyle(context), + // 2.height, + // // Text( + // // activity.activityMaintenance?.technicalComment ?? "", + // // style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), + // // ), + // ] ], - ).toShadowContainer(context, padding: 12, showShadow: false); + ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { + if (requestDetailProvider.isReadOnlyRequest) { + onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); + } + }); } void onEditMaintenanceRequestPress({required BuildContext context, required ServiceRequestDetailProvider requestDetailProvider, required Activities activity}) async { @@ -391,7 +414,7 @@ class _ActivitiesListViewState extends State { } Navigator.of(context).push(MaterialPageRoute( - builder: (_) => const MaintenanceRequestForm(), + builder: (_) => MaintenanceRequestForm(), )); } } diff --git a/lib/service_request_latest/views/components/asset_detail_card.dart b/lib/service_request_latest/views/components/asset_detail_card.dart index f86b30ad..c7ef8814 100644 --- a/lib/service_request_latest/views/components/asset_detail_card.dart +++ b/lib/service_request_latest/views/components/asset_detail_card.dart @@ -34,6 +34,8 @@ class AssetDetailCard extends StatelessWidget { textColor: AppColor.white10, backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0), ), + //hide if status is closed. + if(!requestDetailProvider.isReadOnlyRequest) "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async{ requestDetailProvider.refreshTimer = false; await Navigator.push( diff --git a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart index 150b59d8..55921e6a 100644 --- a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart +++ b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart @@ -704,7 +704,7 @@ class ServiceRequestBottomSheet { ); Navigator.pushReplacement( context, - MaterialPageRoute(builder: (context) => const MaintenanceRequestForm()), + MaterialPageRoute(builder: (context) => MaintenanceRequestForm()), ); break; } diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index 61111bdd..061de6ba 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -35,12 +35,12 @@ class ServiceRequestDetailView extends StatefulWidget { } class _ServiceRequestDetailViewState extends State { - List _workOrderAttachments = []; + List _workOrderAttachments = []; @override void initState() { ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? []; + _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? []; super.initState(); } @@ -71,7 +71,7 @@ class _ServiceRequestDetailViewState extends State { ).expanded, FooterActionButton.requestDetailsFooterWidget( workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, - // workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit, + status: requestProvider.currentWorkOrder?.data?.status, isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null, activities: requestProvider.currentWorkOrder!.data?.activities ?? [], userProvider: _userProvider, @@ -117,6 +117,15 @@ class _ServiceRequestDetailViewState extends State { textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!), backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!), ), + if(workOrder.since!=null)...[ + 8.width, + StatusLabel( + radius: 4, + label:'${workOrder.since} days', + textColor: AppColor.neutral50, + backgroundColor: AppColor.orange80, + ), + ], 1.width.expanded, Column( crossAxisAlignment: CrossAxisAlignment.end, @@ -208,9 +217,18 @@ class _ServiceRequestDetailViewState extends State { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Date/Time: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', + 'Requested Date: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), + ), + Text( + '${context.translation.arrivedDate}: ${workOrder.iHaveArrivedDate != null ? workOrder.iHaveArrivedDate.toString().toServiceRequestDetailsFormat : '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), ), + Text( + '${context.translation.closedDate}: ${workOrder.closedDate != null ? workOrder.closedDate!.toString().toServiceRequestDetailsFormat : '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), + ), + const Divider().defaultStyle(context), //... call response details starts here.... @@ -232,13 +250,40 @@ class _ServiceRequestDetailViewState extends State { '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), + Text( + '${context.translation.callResponse}: ${workOrder.callResponse ?? "-"}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + '${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + 8.height, + if (workOrder.rejectReason != null) ...[ + const Divider().defaultStyle(context), + 8.height, + Text( + context.translation.rejectionDetails, + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + Text( + '${context.translation.rejectionReason}: ${workOrder.rejectReason?.name ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + 8.height, + Text( + '${context.translation.comment}: ${workOrder.lastComment ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + ], 8.height, if ((workOrder.comments ?? "").isNotEmpty) ...[ const Divider().defaultStyle(context), 8.height, Text( - "Call Comment", + context.translation.callComments, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, @@ -250,14 +295,17 @@ class _ServiceRequestDetailViewState extends State { 8.height, const Divider().defaultStyle(context), - MultiFilesPicker( + AttachmentPicker( label: context.translation.attachments, - files: _workOrderAttachments, + // files: _workOrderAttachments, + attachment: _workOrderAttachments, buttonColor: AppColor.primary10, onlyImages: false, buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), onChange: (attachment) { - requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment); + print('i am called.'); + // print('attachment value is ${attachment.last.file?.path}'); + // requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); }, ), @@ -373,7 +421,9 @@ class _ServiceRequestDetailViewState extends State { } Widget assetDetailCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) { - if (userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) { + print('id i got is ${requestDetailProvider.currentWorkOrder?.data?.status?.id}'); + if ((userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) || + requestDetailProvider.isReadOnlyRequest) { WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!; requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel( workOrderId: currentWorkOrderData.requestId, diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart index 0e1764e7..eb0746c5 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -39,6 +39,12 @@ class _AssistantEmployeeCardState extends State { Future getInitialData() async { final user = Provider.of(context, listen: false).user!; ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + print('readonly value is ${requestDetailProvider.isReadOnlyRequest}'); + if( requestDetailProvider.isReadOnlyRequest){ + isExpanded = true; + setState(() { + }); + } isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); // if (isCurrentUserIsAssistantEmp) { diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart index e3727b7f..1f828514 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart @@ -42,198 +42,198 @@ class _ExternalMaintenanceRequestState extends State ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); _workingHoursController.text = requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel!.supplierWorkingHour.toString() : ''; - } @override Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { - return Column( - children: [ - Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SingleItemDropDownMenu( - context: context, - title: context.translation.supplier, - backgroundColor: AppColor.neutral100, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier, - showAsBottomSheet: true, - onSelect: (supplier) { - if (supplier != null) { - requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier; - // _subWorkOrders.supplier = supplier; - // log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString()); - setState(() {}); - } - }, - ), - 8.height, - Row( - children: [ - SingleItemDropDownMenu( - context: context, - backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, - title: context.translation.supplierEngineer, - enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false, - staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons, - showAsBottomSheet: true, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null - ? null - : SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()), - onSelect: (suppPerson) { - print(suppPerson?.toJson()); - if (suppPerson != null) { - requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson()); - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // engineer = SuppEngineerWorkOrders( - // id: suppPerson?.supplierId, - // supplierContactId: suppPerson?.id, - // personName: suppPerson?.personName, - // contact: suppPerson?.contact, - // externalEngCode: suppPerson?.externalEngCode, - // email: suppPerson?.email, - // ); - setState(() {}); - } - }, - ).expanded, - 8.width, - Container( - height: 56.toScreenHeight, - width: 60.toScreenWidth, - decoration: BoxDecoration( - color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - child: Icon( - Icons.add, - color: context.isDark ? null : AppColor.neutral60, - ), - ).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null - ? null - : () async { - SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()), - )) as SuppEngineerWorkOrders; - requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= []; - requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson())); - requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer; - setState(() {}); - }), - ], - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime; - requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null; + return IgnorePointer( + ignoring: requestDetailProvider.isReadOnlyRequest, + child: Column( + children: [ + Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.supplier, + backgroundColor: AppColor.neutral100, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier, + showAsBottomSheet: true, + onSelect: (supplier) { + if (supplier != null) { + requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier; + // _subWorkOrders.supplier = supplier; + // log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString()); + setState(() {}); + } + }, + ), + 8.height, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, + title: context.translation.supplierEngineer, + enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false, + staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons, + showAsBottomSheet: true, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null + ? null + : SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()), + onSelect: (suppPerson) { + print(suppPerson?.toJson()); + if (suppPerson != null) { + requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson()); requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - _workingHoursController.clear(); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; - }, - ); - + // engineer = SuppEngineerWorkOrders( + // id: suppPerson?.supplierId, + // supplierContactId: suppPerson?.id, + // personName: suppPerson?.personName, + // contact: suppPerson?.contact, + // externalEngCode: suppPerson?.externalEngCode, + // email: suppPerson?.email, + // ); + setState(() {}); } - }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null && - selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { - "End Date time must be greater then start date".showToast; - return; + }, + ).expanded, + 8.width, + Container( + height: 56.toScreenHeight, + width: 60.toScreenWidth, + decoration: BoxDecoration( + color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Icon( + Icons.add, + color: context.isDark ? null : AppColor.neutral60, + ), + ).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null + ? null + : () async { + SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()), + )) as SuppEngineerWorkOrders; + requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= []; + requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson())); + requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer; + setState(() {}); + }), + ], + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime; + requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + _workingHoursController.clear(); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, + endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; + }, + ); } - requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; - }, - ); - } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: _workingHoursController, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '', - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - ], - ), - ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), - ], + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null && + selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, + endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; + }, + ); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], + ), + ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), + ], + ), ); }); } - } diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart index 4ea023f1..c94195d4 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart @@ -35,14 +35,11 @@ class _InternalMaintenanceRequestState extends State Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1}); - @override void initState() { _requestDetailProvider = Provider.of(context, listen: false); super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - //need to confirm with backend api data... - // _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList()); _travellingHoursController.text = _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : ''; }); @@ -59,8 +56,6 @@ class _InternalMaintenanceRequestState extends State @override Widget build(BuildContext context) { return Consumer(builder: (context, requestDetailProvider, child) { - - double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers ?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; @@ -70,229 +65,231 @@ class _InternalMaintenanceRequestState extends State : requestDetailProvider.activityMaintenanceHelperModel?.id == requestDetailProvider.lastVisitedRequestActivityId; return SingleChildScrollView( - child: Column( - children: [ - Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // SingleItemDropDownMenu( - // context: context, - // height: 56.toScreenHeight, - // title: context.translation.activityStatus, - // showShadow: false, - // backgroundColor: AppColor.neutral100, - // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, - // onSelect: (status) { - // print('status i got is ${status?.toJson()}'); - // requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; - // }, - // ), - // 8.height, - SingleItemDropDownMenu( - context: context, - height: 56.toScreenHeight, - title: context.translation.activityStatus, - showShadow: false, - backgroundColor: AppColor.neutral100, - showAsBottomSheet: true, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, - onSelect: (status) { - if (status != null) { - requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; - setState(() {}); - } - }, - ), - 8.height, - AppTimer( - label: context.translation.timer, - timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, - enabled: enableTimer, - timerProgress: (isRunning) { - print("timerProgress:$isRunning"); - }, - onChange: (timer) async { - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; - if (timer.startAt != null && timer.endAt != null) { - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? []; - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer); - } - return true; - }, - ), - // Row( - // mainAxisSize: MainAxisSize.min, - // children: [ - // ADatePicker( - // label: context.translation.startTime, - // hideShadow: true, - // backgroundColor: AppColor.neutral100, - // date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, - // formatDateWithTime: true, - // onDatePicker: (selectedDate) { - // showTimePicker( - // context: context, - // initialTime: TimeOfDay.now(), - // ).then((selectedTime) { - // // Handle the selected date and time here. - // if (selectedTime != null) { - // DateTime selectedDateTime = DateTime( - // selectedDate.year, - // selectedDate.month, - // selectedDate.day, - // selectedTime.hour, - // selectedTime.minute, - // ); - // requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; - // requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; - // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // _workingHoursController.clear(); - // ServiceRequestUtils.calculateAndAssignWorkingHours( - // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - // workingHoursController: _workingHoursController, - // updateModel: (hours) { - // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - // }, - // ); - // } - // }); - // }, - // ).expanded, - // 8.width, - // ADatePicker( - // label: context.translation.endTime, - // hideShadow: true, - // backgroundColor: AppColor.neutral100, - // date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, - // formatDateWithTime: true, - // onDatePicker: (selectedDate) { - // showTimePicker( - // context: context, - // initialTime: TimeOfDay.now(), - // ).then((selectedTime) { - // // Handle the selected date and time here. - // if (selectedTime != null) { - // DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); - // if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && - // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { - // "End Date time must be greater then start date".showToast; - // return; - // } - // requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; - // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // ServiceRequestUtils.calculateAndAssignWorkingHours( - // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - // workingHoursController: _workingHoursController, - // updateModel: (hours) { - // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - // }, - // ); - // } - // }); - // }, - // ).expanded, - // ], - // ), - 8.height, - if (totalWorkingHours > 0.0) ...[ - Container( + child: IgnorePointer( + ignoring: _requestDetailProvider!.isReadOnlyRequest, + child: Column( + children: [ + Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // SingleItemDropDownMenu( + // context: context, + // height: 56.toScreenHeight, + // title: context.translation.activityStatus, + // showShadow: false, + // backgroundColor: AppColor.neutral100, + // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, + // onSelect: (status) { + // print('status i got is ${status?.toJson()}'); + // requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; + // }, + // ), + // 8.height, + SingleItemDropDownMenu( + context: context, height: 56.toScreenHeight, - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Total Working Time", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - ), - Text( - " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyMedium, - ), - ], + title: context.translation.activityStatus, + showShadow: false, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, + onSelect: (status) { + if (status != null) { + requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; + setState(() {}); + } + }, + ), + 8.height, + AppTimer( + label: context.translation.timer, + timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, + enabled: enableTimer, + timerProgress: (isRunning) { + print("timerProgress:$isRunning"); + }, + onChange: (timer) async { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; + if (timer.startAt != null && timer.endAt != null) { + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? []; + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer); + } + return true; + }, + ), + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // ADatePicker( + // label: context.translation.startTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // _workingHoursController.clear(); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // 8.width, + // ADatePicker( + // label: context.translation.endTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); + // if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && + // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { + // "End Date time must be greater then start date".showToast; + // return; + // } + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // ], + // ), + 8.height, + if (totalWorkingHours > 0.0) ...[ + Container( + height: 56.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + alignment: Alignment.centerLeft, + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral40 : AppColor.background(context), + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Total Working Time", + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + ), + Text( + " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), ), + 8.height, + ], + // if (totalWorkingHours > 0.0) ...[ + // AppTextFormField( + // labelText: context.translation.workingHours, + // backgroundColor: AppColor.neutral80, + // controller: _workingHoursController, + // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', + // textAlign: TextAlign.center, + // labelStyle: AppTextStyles.textFieldLabelStyle, + // enable: false, + // showShadow: false, + // style: Theme.of(context).textTheme.titleMedium, + // ), + // 8.height, + // ], + AppTextFormField( + labelText: context.translation.travelingHours, + controller: _travellingHoursController, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(), + textInputType: TextInputType.number, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value); // int.tryParse(value); + }, + // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?; + }, + ), + 16.height, + repairLocationWidget(context, requestDetailProvider), + 16.height, + AppTextFormField( + labelText: context.translation.assignedEmployee, + backgroundColor: AppColor.neutral80, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + enable: false, + style: Theme.of(context).textTheme.titleMedium, ), 8.height, + AppTextFormField( + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + ), ], - // if (totalWorkingHours > 0.0) ...[ - // AppTextFormField( - // labelText: context.translation.workingHours, - // backgroundColor: AppColor.neutral80, - // controller: _workingHoursController, - // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', - // textAlign: TextAlign.center, - // labelStyle: AppTextStyles.textFieldLabelStyle, - // enable: false, - // showShadow: false, - // style: Theme.of(context).textTheme.titleMedium, - // ), - // 8.height, - // ], - AppTextFormField( - labelText: context.translation.travelingHours, - controller: _travellingHoursController, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(), - textInputType: TextInputType.number, - onChange: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value) ;// int.tryParse(value); - }, - // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), - onSaved: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?; - }, - ), - 16.height, - repairLocationWidget(context, requestDetailProvider), - 16.height, - AppTextFormField( - labelText: context.translation.assignedEmployee, - backgroundColor: AppColor.neutral80, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName, - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - showShadow: false, - enable: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - AppTextFormField( - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, - labelText: context.translation.technicalComment, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - alignLabelWithHint: true, - textInputType: TextInputType.multiline, - onChange: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; - }, - onSaved: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; - }, - ), - - ], - ), - ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), - const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), - 100.height, - ], + ), + ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), + const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), + 100.height, + ], + ), ), ); }); diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index e60383bb..21e93670 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -18,7 +18,7 @@ import 'package:test_sa/service_request_latest/views/forms/maintenance_request/c import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart'; class MaintenanceRequestForm extends StatefulWidget { - const MaintenanceRequestForm({Key? key}) : super(key: key); + MaintenanceRequestForm({Key? key}) : super(key: key); @override _MaintenanceRequestFormState createState() => _MaintenanceRequestFormState(); diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 3df20c4c..8a4e2575 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -148,7 +148,7 @@ class _SparePartRequestState extends State with TickerProvider 12.height, SingleItemDropDownMenu( context: context, - title: context.translation.partNo, + title: context.translation.part, staticData: _spareParts, showShadow: false, showAsBottomSheet: true, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 16cb8850..0f2c5720 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -57,11 +57,13 @@ class _RoomInspectionCardState extends State { required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context, }) { - bool status = model.attribute != null - ? model.attributeValue == 'true' - ? true - : false - : false; + bool status = (model.attribute == null || model.attributeValue == null) + ? true + : model.attribute != null + ? model.attributeValue == 'true' + ? true + : false + : false; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -71,7 +73,7 @@ class _RoomInspectionCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - model.attribute!.name!, + model.attribute?.name ?? '', overflow: TextOverflow.ellipsis, maxLines: 1, style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 407449bc..bd1771ba 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -11,6 +11,7 @@ import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; @@ -56,11 +57,15 @@ class RecurrentTaskInfoWidget extends StatelessWidget { 8.height, buildingInfoWidget(label: context.translation.room, value: model?.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - _timerWidget(context, model!.totalWorkingHours!) + _timerWidget(context, model!.totalWorkingHours!), + 8.height, + _commentWidget(context: context, model: model) ], // ], ).toShadowContainer(context, padding: 12) - : _timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), + : Column( + children: [_timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), 8.height, _commentWidget(context: context, model: model)], + ), ], ); } @@ -104,6 +109,24 @@ class RecurrentTaskInfoWidget extends StatelessWidget { ); }); } + + Widget _commentWidget({RecurrentWoData? model, required BuildContext context}) { + return AppTextFormField( + initialValue: model?.comment, + labelText: context.translation.comment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + model?.comment = value; + }, + onSaved: (value) { + model?.comment = value; + }, + ); + } } Widget buildingInfoWidget({required String label, required String? value, required BuildContext context}) { @@ -118,10 +141,9 @@ Widget buildingInfoWidget({required String label, required String? value, requir ), 3.height, Text( - value??'', + value ?? '', style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), ) ], ).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false); } - diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 8b3eb979..dfabd8c4 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -72,25 +72,27 @@ class _RecurrentWorkOrderViewState extends State { ], ).paddingAll(12), ).paddingOnly(bottom: 85), - FooterActionButton.footerContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - AppFilledButton( - label: context.translation.save, - buttonColor: AppColor.white60, - textColor: AppColor.black10, - onPressed: () => _updateTask(context: context, status: 0), - ).expanded, - 12.width, - AppFilledButton( - label: context.translation.complete, - buttonColor: AppColor.primary10, - onPressed: () => _updateTask(context: context, status: 1), - ).expanded, - ], + if (requestProvider.recurrentWoData?.status?.id != 270) ...[ + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _updateTask(context: context, status: 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _updateTask(context: context, status: 1), + ).expanded, + ], + ), ), - ), + ] ], ) : NoDataFound(message: context.translation.noDataFound).center, diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart index f6484ace..fe6c6ae3 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart @@ -8,6 +8,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/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; diff --git a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart index a5e23ea4..1ed01113 100644 --- a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart @@ -15,9 +15,11 @@ import 'package:test_sa/providers/ppm_electrical_safety_provider.dart'; import 'package:test_sa/providers/ppm_service_provider.dart'; import 'package:test_sa/providers/ppm_task_status_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; +import 'package:test_sa/models/device/asset.dart'; import '../../../../../models/lookup.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart'; @@ -36,8 +38,6 @@ class WoInfoForm extends StatefulWidget { } class _WoInfoFormState extends State { - //TODO need to move this to provider ... - @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { @@ -78,8 +78,10 @@ class _WoInfoFormState extends State { '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), //need to add in translation it's suggestion from ahmed.. 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.creationDate}: ${widget.planPreventiveVisit.creationDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.closedDate}: ${widget.planPreventiveVisit.closedDate != null ? widget.planPreventiveVisit.closedDate?.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' .bodyText2(context) @@ -97,7 +99,22 @@ class _WoInfoFormState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), - "info_icon".toSvgAsset(height: 17, width: 17), + "info_icon".toSvgAsset(height: 17, width: 17).onPress( + () { + // There is only limited information for asset is returned from backend to show all info need to return the whole model from backend... + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => _buildAssetDetailBottomSheet(context), + ); + }, + ) ], ), 2.height, @@ -292,6 +309,23 @@ class _WoInfoFormState extends State { }); } + _buildAssetDetailBottomSheet(BuildContext context) { + PlanPreventiveVisit model = widget.planPreventiveVisit; + + Asset asset = Asset(id: model.asset?.id, assetSerialNo: model.asset?.assetSerialNo, assetNumber: model.asset?.assetNumber); + return AssetDetailBottomSheet(asset); + } + + // Future getAssetById () async { + // Asset asset = Asset(); + // AssetProvider _assetProvider = Provider.of(context, listen: false); + // if(widget.planPreventiveVisit.asset!=null){ + // AssetByIdModel ?assetByIdModel = await _assetProvider.getAssetById(widget.planPreventiveVisit.asset!.id!.toInt(), context.translation); + // asss + // } + // return asset; + // } + Widget _timerWidget(BuildContext context, double totalWorkingHours) { return Column( children: [ diff --git a/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart b/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart index 1b75aeae..474ae1a3 100644 --- a/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart +++ b/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart @@ -48,9 +48,9 @@ class AssetDetailBottomSheet extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ "${context.translation.assetNo}: ${asset!.assetNumber}".bodyText(context), - "${context.translation.modelName}: ${asset!.modelDefinition!.modelName}".bodyText(context), + "${context.translation.modelName}: ${asset!.modelDefinition?.modelName}".bodyText(context), "${context.translation.supplier}: ${asset!.supplier?.suppliername?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"}".bodyText(context), - "${context.translation.manufacture}: ${asset!.modelDefinition!.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context), + "${context.translation.manufacture}: ${asset!.modelDefinition?.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context), //"${context.translation.location}: ${assetModel.site.custName?.cleanupWhitespace?.capitalizeFirstOfEach}".bodyText(context), ], ).expanded, diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index 1fe5a186..a6a2242d 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -18,6 +18,7 @@ class MultiFilesPicker extends StatefulWidget { final String label; final bool error; final List files; + final List attachment ; final bool enabled, onlyImages; double? buttonHeight; Widget? buttonIcon; @@ -28,6 +29,7 @@ class MultiFilesPicker extends StatefulWidget { MultiFilesPicker( {Key? key, this.files = const [], + this.attachment = const [], required this.label, this.error = false, this.buttonHeight, @@ -123,10 +125,10 @@ class _MultiFilesPickerState extends State { "Attach File".heading4(context), 12.height, GridView( - padding: EdgeInsets.all(0), + padding: const EdgeInsets.all(0), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), children: [ gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), @@ -141,38 +143,34 @@ class _MultiFilesPickerState extends State { ).paddingAll(21), )) as ImageSource; - if (source == null) return; - final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); if (pickedFile != null) { File fileImage = File(pickedFile.path); - if (fileImage != null) { - widget.files.add(fileImage); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - setState(() {}); + widget.files.add(fileImage); + if (widget.onChange != null) { + widget.onChange!(widget.files); } - } + setState(() {}); + } } Widget gridItem(IconData iconData, String title) { return Container( - padding: EdgeInsets.all(12), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), - border: Border.all(color: Color(0xffF1F1F1), width: 1), + border: Border.all(color: const Color(0xffF1F1F1), width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon(iconData, color: Color(0xff7D859A), size: 36), + Icon(iconData, color: const Color(0xff7D859A), size: 36), Text( title, - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), ), ], ), @@ -285,3 +283,295 @@ class _MultiFilesPickerState extends State { setState(() {}); } } + + + + + +class AttachmentModel { + int id =0; + File ? file; + AttachmentModel(this.id,this.file); + + factory AttachmentModel.fromJson(Map json) { + return AttachmentModel( + json['id'] ?? 0, + json['file'] != null ? File(json['file']) : null, + ); + } + + Map toJson() { + return { + 'id': id, + 'file': file?.path, + }; + } + + +} + +class AttachmentPicker extends StatefulWidget { + final String label; + final bool error; + final List attachment ; + final bool enabled, onlyImages; + double? buttonHeight; + Widget? buttonIcon; + Color? buttonColor; + final Function(List)? onChange; + final bool showAsGrid; + + AttachmentPicker( + {Key? key, + this.attachment = const [], + required this.label, + this.error = false, + this.buttonHeight, + this.buttonIcon, + this.enabled = true, + this.onlyImages = false, + this.onChange, + this.showAsGrid = false, + this.buttonColor}) + : super(key: key); + + @override + State createState() => _AttachmentPickerState(); +} + +class _AttachmentPickerState extends State { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppDashedButton( + title: widget.label, + height: widget.buttonHeight, + buttonColor: widget.buttonColor, + icon: widget.buttonIcon, + onPressed: (widget.enabled == false) + ? () {} + : widget.showAsGrid + ? showFileSourceSheet + : onFilePicker), + 16.height, + if (widget.attachment.isNotEmpty) + Wrap( + spacing: 8.toScreenWidth, + children: List.generate( + widget.attachment.length, + (index) { + File image = widget.attachment[index].file!; + return MultiFilesPickerItem( + file: image, + enabled: widget.enabled, + onRemoveTap: (image) { + if (!widget.enabled) { + return; + } + widget.attachment.remove(image); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + }, + ); + }, + ), + ), + ], + ); + } + + fromFilePicker() async { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowMultiple: true, + allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], + ); + if (result != null) { + for (var path in result.paths) { + widget.attachment.add(AttachmentModel(0, File(path!))); + } + setState(() {}); + } + } + + void showFileSourceSheet() async { + if (widget.attachment.length >= 5) { + Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + return; + } + + ImageSource source = (await showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Attach File".heading4(context), + 12.height, + GridView( + padding: const EdgeInsets.all(0), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), + children: [ + gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), + gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), + gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async { + await fromFilePicker(); + Navigator.pop(context); + }), + ], + ), + 12.height, + ], + ).paddingAll(21), + )) as ImageSource; + + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); + + if (pickedFile != null) { + File fileImage = File(pickedFile.path); + widget.attachment.add(AttachmentModel(0, fileImage)); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + } + } + + Widget gridItem(IconData iconData, String title) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xffF1F1F1), width: 1), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Icon(iconData, color: const Color(0xff7D859A), size: 36), + Text( + title, + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + ), + ], + ), + ); + } + + onFilePicker() async { + if (widget.attachment.length >= 5) { + Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + return; + } + ImageSource? source = await showModalBottomSheet( + context: context, + builder: (BuildContext context) { + Widget listCard({required String icon, required String label, required VoidCallback onTap}){ + return GestureDetector( + onTap: onTap, + child: Container( + constraints: BoxConstraints(minWidth: 111.toScreenWidth,minHeight: 111.toScreenHeight), + padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth,vertical: 12.toScreenHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all(width: 1,color:AppColor.white70) + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + icon.toSvgAsset(), + 24.height, + label.bodyText2(context).custom(color: AppColor.black20), + ], + ), + ), + ); + } + return Container( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + listCard( + icon: 'camera_icon', + label: '${context.translation.open}\n${context.translation.camera}', + onTap: () { + Navigator.of(context).pop(ImageSource.camera); + }, + ), + listCard( + icon: 'gallery_icon', + label: '${context.translation.open}\n${context.translation.gallery}', + onTap: () { + Navigator.of(context).pop(ImageSource.gallery); + }, + ), + listCard( + icon: 'file_icon', + label: '${context.translation.open}\n${context.translation.files}', + onTap: () async { + await fromFilePicker(); + Navigator.pop(context); + }, + ), + ], + ), + ); + }, + ); + // ImageSource source = await showDialog( + // context: context, + // builder: (dialogContext) => CupertinoAlertDialog( + // actions: [ + // TextButton( + // child: Text(context.translation.pickFromCamera), + // onPressed: () { + // Navigator.of(dialogContext).pop(ImageSource.camera); + // }, + // ), + // TextButton( + // child: Text(context.translation.pickFromGallery), + // onPressed: () { + // Navigator.of(dialogContext).pop(ImageSource.gallery); + // }, + // ), + // TextButton( + // child: Text(context.translation.pickFromFiles), + // onPressed: () async { + // await fromFilePicker(); + // Navigator.pop(context); + // }, + // ), + // ], + // ), + // ); + if (source == null) return; + + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); + + if (pickedFile != null) { + File fileImage = File(pickedFile.path); + widget.attachment.add(AttachmentModel(0, fileImage)); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + } + + setState(() {}); + } +} From 4954549594781e8f0c0032137f11134a6c645e4b Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 27 Mar 2025 16:24:26 +0300 Subject: [PATCH 18/36] bug fixes for workorder detail view --- .../new_models/work_order_detail_model.dart | 13 +++-- lib/new_views/app_style/app_color.dart | 22 +++++++++ .../service_request_detail_provider.dart | 3 +- .../action_button/footer_action_button.dart | 1 - .../components/activities_list_view.dart | 25 +++++++--- .../views/components/asset_detail_card.dart | 48 ++++++++++++------- .../service_request_detail_view.dart | 42 ++++++++-------- .../maintenance_request_main.dart | 29 ++++++----- 8 files changed, 119 insertions(+), 64 deletions(-) diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index b8c16719..18c63a95 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -89,7 +89,7 @@ class WorkOrderData { this.closedDate, this.since, this.cmFrame, - this.lastComment, + this.rejectComment, this.callResponse, required this.workOrderHistory, required this.activities, @@ -143,7 +143,7 @@ class WorkOrderData { String? iHaveArrivedDate; String? closedDate; Lookup? rejectReason; - String? lastComment; // need to replace with reject comments. + String? rejectComment; // need to replace with reject comments. String? callResponse; // need to replace with reject comments. int? since; List workOrderHistory; @@ -166,7 +166,7 @@ class WorkOrderData { floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]), department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]), room: json["room"], - lastComment: json["lastComment"], + rejectComment: json["rejectComment"], callResponse: json["callResponse"], iHaveArrivedDate: json["iHaveArrivedDate"], closedDate: json["closedDate"], @@ -527,9 +527,9 @@ class WorkOrderContactPerson { String? name; String? employeeId; String? position; - String extension; + String? extension; String? email; - String mobilePhone; + String ?mobilePhone; WorkOrderAssignedEmployee? contactUser; factory WorkOrderContactPerson.fromJson(Map json) { @@ -642,6 +642,7 @@ class ActivityMaintenance { String? supplierStartTime; String? supplierEndTime; double? supplierWorkingHours; + String? activityType; List? assistantEmployees; List? activityMaintenanceTimers; @@ -661,6 +662,7 @@ class ActivityMaintenance { this.supplierEngineer, this.supplierStartTime, this.supplierEndTime, + this.activityType, this.supplierWorkingHours, this.assistantEmployees}); @@ -670,6 +672,7 @@ class ActivityMaintenance { startTime = json['startTime']; endTime = json['endTime']; workingHours = json['workingHours']; + activityType = json['activityType']; travelHours = json['travelHours']; lastSituation = json['lastSituation'] != null ? Lookup.fromJson(json['lastSituation']) : null; repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 4e4421fe..847b6b59 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -47,6 +47,7 @@ class AppColor { static const Color white60 = Color(0xffEFEFEF); static const Color white70 = Color(0xffF1F1F1); static const Color white80 = Color(0xffF2F4FA); + static const Color white90 = Color(0xffBFD1E4); static const Color white936 = Color(0xff212936); //black @@ -137,6 +138,27 @@ class AppColor { return Colors.white; } } + static Color getActivityTypeBgColor(String type) { + switch (type) { + case "Internal": + return neutral50; + case "External": + return white90; + default: + + return primary10; + } + } +static Color getActivityTypeTextColor(String type) { + switch (type) { + case "Internal": + return white10; + case "External": + return black10; + default: + return Colors.white; + } + } static Color getHistoryLogStatusColorByName(String status) { switch ((status).toLowerCase()) { diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index fc989218..7fa906f7 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -225,7 +225,8 @@ class ServiceRequestDetailProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); - if (currentWorkOrder?.data?.status?.id == 3498) { + //need to check on value as id changed on different env. + if (currentWorkOrder?.data?.status?.value == 3 || currentWorkOrder?.data?.status?.value == 5 || currentWorkOrder?.data?.status?.value == 6) { isReadOnlyRequest = true; } else { isReadOnlyRequest = false; diff --git a/lib/service_request_latest/views/components/action_button/footer_action_button.dart b/lib/service_request_latest/views/components/action_button/footer_action_button.dart index 34446263..b5a67159 100644 --- a/lib/service_request_latest/views/components/action_button/footer_action_button.dart +++ b/lib/service_request_latest/views/components/action_button/footer_action_button.dart @@ -60,7 +60,6 @@ class FooterActionButton { case WorkOrderNextStepEnum.nTakeAction: // const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: ''); //Need to add enum for these values in future instead of static values.. - if (requestDetailProvider.isReadOnlyRequest) { return footerContainer( child: AppFilledButton( diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 6793817a..1acd0ba2 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -275,13 +275,26 @@ class _ActivitiesListViewState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ //TODO will be here when fixed from backend.. - StatusLabel( - label: activity.activityStatus?.name, - textColor: AppColor.white10, - // textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!), - // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), - backgroundColor: AppColor.primary10, + Row( + children: [ + StatusLabel( + label: activity.activityStatus?.name, + textColor: AppColor.white10, + // textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!), + // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), + backgroundColor: AppColor.primary10, + ), + 5.width, + StatusLabel( + label: activity.activityMaintenance?.activityType, + // textColor: AppColor.white10, + textColor: AppColor.getActivityTypeTextColor(activity.activityMaintenance?.activityType??''), + backgroundColor: AppColor.getActivityTypeBgColor(activity.activityMaintenance?.activityType??''), + // backgroundColor: AppColor.primary10, + ), + ], ), + // "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3) Row( diff --git a/lib/service_request_latest/views/components/asset_detail_card.dart b/lib/service_request_latest/views/components/asset_detail_card.dart index 5c4b858e..914b847d 100644 --- a/lib/service_request_latest/views/components/asset_detail_card.dart +++ b/lib/service_request_latest/views/components/asset_detail_card.dart @@ -27,25 +27,37 @@ class AssetDetailCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - StatusLabel( - label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name, - id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0, - radius: 4, - textColor: AppColor.white10, - backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0), + Row( + children: [ + StatusLabel( + label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name, + id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0, + radius: 4, + textColor: AppColor.white10, + backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0), + ), + 5.width, + StatusLabel( + label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.serviceType?.name, + id: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.serviceType?.id ?? 0, + radius: 4, + textColor: AppColor.getActivityTypeTextColor(requestDetailProvider.engineerUpdateWorkOrderHelperModel!.serviceType?.name ?? ''), + backgroundColor: AppColor.getActivityTypeBgColor(requestDetailProvider.engineerUpdateWorkOrderHelperModel!.serviceType?.name ?? ''), + ), + ], ), - //hide if status is closed. - if(!requestDetailProvider.isReadOnlyRequest) - "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async{ - requestDetailProvider.refreshTimer = false; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => VerifyAssetDetails( - isEdit: true, - ))); - requestDetailProvider.refreshTimer = true; - }), + //hide if status is closed or complete . + if (!requestDetailProvider.isReadOnlyRequest) + "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async { + requestDetailProvider.refreshTimer = false; + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => VerifyAssetDetails( + isEdit: true, + ))); + requestDetailProvider.refreshTimer = true; + }), ]), 6.height, Text( diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index 8cf0c060..92ca9575 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -34,12 +34,13 @@ class ServiceRequestDetailView extends StatefulWidget { } class _ServiceRequestDetailViewState extends State { - List _workOrderAttachments = []; + List _workOrderAttachments = []; @override void initState() { ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? []; + _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? []; + // _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? []; super.initState(); } @@ -79,9 +80,10 @@ class _ServiceRequestDetailViewState extends State { context: context), ], ), - if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ - const TimerWidget(), - ] + //no need to show timer as discussed with backend + // if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ + // const TimerWidget(), + // ] ], ); }); @@ -255,10 +257,10 @@ class _ServiceRequestDetailViewState extends State { '${context.translation.callResponse}: ${workOrder.callResponse ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), - Text( - '${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}', - style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), - ), + // Text( + // '${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}', + // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + // ), 8.height, if (workOrder.rejectReason != null) ...[ @@ -275,7 +277,7 @@ class _ServiceRequestDetailViewState extends State { ), 8.height, Text( - '${context.translation.comment}: ${workOrder.lastComment ?? '-'}', + '${context.translation.comment}: ${workOrder.rejectComment ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], @@ -296,17 +298,17 @@ class _ServiceRequestDetailViewState extends State { 8.height, const Divider().defaultStyle(context), - AttachmentPicker( + MultiFilesPicker( label: context.translation.attachments, - // files: _workOrderAttachments, - attachment: _workOrderAttachments, + files: _workOrderAttachments, + // attachment: _workOrderAttachments, buttonColor: AppColor.primary10, onlyImages: false, buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), onChange: (attachment) { print('i am called.'); // print('attachment value is ${attachment.last.file?.path}'); - // requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); + requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); }, ), @@ -401,27 +403,27 @@ class _ServiceRequestDetailViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '${workOrder.workOrderContactPerson[index].name}', + '${workOrder.workOrderContactPerson[index].name??'-'}', style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), Text( - '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId}', + '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId??'-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone}', + '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone??'-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Job: ${workOrder.workOrderContactPerson[index].position}', + 'Job: ${workOrder.workOrderContactPerson[index].position??'-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email}', + '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email??'-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Extension: ${workOrder.workOrderContactPerson[index].extension}', + 'Extension: ${workOrder.workOrderContactPerson[index].extension??'-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index 41759c3c..ad0e5f01 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -18,7 +18,7 @@ import 'package:test_sa/service_request_latest/views/forms/maintenance_request/c import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart'; class MaintenanceRequestForm extends StatefulWidget { - MaintenanceRequestForm({Key? key}) : super(key: key); + MaintenanceRequestForm({Key? key}) : super(key: key); @override _MaintenanceRequestFormState createState() => _MaintenanceRequestFormState(); @@ -51,9 +51,11 @@ class _MaintenanceRequestFormState extends State with Si backgroundColor: AppColor.neutral110, appBar: DefaultAppBar( title: "CM Activity", - onWillPopScope: () { - save(requestDetailProvider); - }, + onWillPopScope: requestDetailProvider.isReadOnlyRequest + ? null + : () { + save(requestDetailProvider); + }, ), body: Stack( children: [ @@ -97,19 +99,20 @@ class _MaintenanceRequestFormState extends State with Si ], ), ), - FooterActionButton.footerContainer( - child: AppFilledButton( - label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label - buttonColor: AppColor.primary10, - onPressed: () async { - save(requestDetailProvider); - }, + if (!requestDetailProvider.isReadOnlyRequest) + FooterActionButton.footerContainer( + child: AppFilledButton( + label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label + buttonColor: AppColor.primary10, + onPressed: () async { + save(requestDetailProvider); + }, + ), ), - ), ], ), ).handlePopScope(context, () { - save(requestDetailProvider); + requestDetailProvider.isReadOnlyRequest ? null : save(requestDetailProvider); }); }); } From ab91baf216d00517d95521beb4c035c2159a9ae2 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Mon, 7 Apr 2025 11:54:04 +0300 Subject: [PATCH 19/36] bug fixes mentioned on excel sheet and tested with backend --- .../providers/api/parts_provider.dart | 20 +- .../providers/api/ppm_provider.dart | 13 + lib/extensions/widget_extensions.dart | 4 +- .../plan_preventive_visit_model.dart | 260 +++++----- lib/models/service_request/spare_parts.dart | 14 +- .../land_page/requests/ppm_item_view.dart | 2 +- .../service_request_detail_view.dart | 2 +- .../forms/spare_part/spare_part_request.dart | 2 +- .../pages/user/ppm/ppm_details_page.dart | 12 +- .../components/room_inspection_card.dart | 2 + .../components/task_info_widget.dart | 2 +- .../recurrent_work_order_view.dart | 3 +- .../ppm_calibration_tools_form.dart | 131 ++--- .../update_ppm/ppm_external_details_form.dart | 308 ++++++------ .../update_ppm/ppm_pm_check_list_form.dart | 126 ++--- .../user/ppm/update_ppm/ppm_pm_kits_form.dart | 129 ++--- .../pages/user/ppm/update_ppm/update_ppm.dart | 76 +-- .../user/ppm/update_ppm/wo_info_form.dart | 465 +++++++++--------- 18 files changed, 844 insertions(+), 727 deletions(-) diff --git a/lib/controllers/providers/api/parts_provider.dart b/lib/controllers/providers/api/parts_provider.dart index 7ec4d8fc..fc2829b8 100644 --- a/lib/controllers/providers/api/parts_provider.dart +++ b/lib/controllers/providers/api/parts_provider.dart @@ -96,11 +96,29 @@ class PartsProvider extends ChangeNotifier { 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)).toList(); + 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/controllers/providers/api/ppm_provider.dart b/lib/controllers/providers/api/ppm_provider.dart index 0af12483..ea5dc266 100644 --- a/lib/controllers/providers/api/ppm_provider.dart +++ b/lib/controllers/providers/api/ppm_provider.dart @@ -22,6 +22,14 @@ class PpmProvider extends ChangeNotifier { PlanPreventiveVisit? _planPreventiveVisit; late int _totalTabs = 4; TabController? tabController; + bool _isReadOnly = false; + + bool get isReadOnly => _isReadOnly; + + set isReadOnly(bool value) { + _isReadOnly = value; + notifyListeners(); + } int get totalTabs => _totalTabs; @@ -155,6 +163,11 @@ class PpmProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { ppmPlanAttachments = []; planPreventiveVisit = PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]); + if(planPreventiveVisit?.visitStatus?.value! == 1 || planPreventiveVisit?.visitStatus?.value == 3){ + isReadOnly =true; + }else{ + isReadOnly =false; + } isLoading = false; notifyListeners(); return planPreventiveVisit; diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 23a5a6a1..dd971fd4 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -55,8 +55,8 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); - Widget handlePopScope(BuildContext _cxt, VoidCallback onSave) { - return PopScope( + Widget handlePopScope(BuildContext _cxt, VoidCallback onSave,) { + return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) { diff --git a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart index 1dcb94f6..3a131ae1 100644 --- a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart +++ b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart @@ -783,136 +783,136 @@ class PreventiveVisitSuppliers { } } -class Supplier { - int? id; - String? suppliername; - String? name; - String? website; - String? email; - String? code; - int? suppNo; - String? suppStatusId; - String? cityId; - String? person; - String? comment; - String? zipcode; - String? contact; - List? telephones; - List? faxes; - List? addresses; - List? attachments; - List? suppPersons; - List? suppTCodes; - - Supplier( - {this.id, - this.suppliername, - this.name, - this.website, - this.email, - this.code, - this.suppNo, - this.suppStatusId, - this.cityId, - this.person, - this.comment, - this.zipcode, - this.contact, - this.telephones, - this.faxes, - this.addresses, - this.attachments, - this.suppPersons, - this.suppTCodes}); - - Supplier.fromJson(Map json) { - id = json['id']; - suppliername = json['suppliername']; - name = json['name']; - website = json['website']; - email = json['email']; - code = json['code']; - suppNo = json['suppNo']; - suppStatusId = json['suppStatusId']; - cityId = json['cityId']; - person = json['person']; - comment = json['comment']; - zipcode = json['zipcode']; - contact = json['contact']; - if (json['telephones'] != null) { - telephones = []; - json['telephones'].forEach((v) { - telephones!.add(v); - }); - } - if (json['faxes'] != null) { - faxes = []; - json['faxes'].forEach((v) { - faxes!.add(v); - }); - } - if (json['addresses'] != null) { - addresses = []; - json['addresses'].forEach((v) { - addresses!.add(v); - }); - } - if (json['attachments'] != null) { - attachments = []; - json['attachments'].forEach((v) { - attachments!.add(v); - }); - } - if (json['suppPersons'] != null) { - suppPersons = []; - json['suppPersons'].forEach((v) { - suppPersons!.add(SuppPersons.fromJson(v)); - }); - } - if (json['suppTCodes'] != null) { - suppTCodes = []; - json['suppTCodes'].forEach((v) { - suppTCodes!.add(v); - }); - } - } - - Map toJson() { - final Map data = {}; - data['id'] = id; - data['suppliername'] = suppliername; - data['name'] = name; - data['website'] = website; - data['email'] = email; - data['code'] = code; - data['suppNo'] = suppNo; - data['suppStatusId'] = suppStatusId; - data['cityId'] = cityId; - data['person'] = person; - data['comment'] = comment; - data['zipcode'] = zipcode; - data['contact'] = contact; - if (telephones != null) { - data['telephones'] = telephones!.map((v) => v).toList(); - } - if (faxes != null) { - data['faxes'] = faxes!.map((v) => v).toList(); - } - if (addresses != null) { - data['addresses'] = addresses!.map((v) => v).toList(); - } - if (attachments != null) { - data['attachments'] = attachments!.map((v) => v).toList(); - } - if (suppPersons != null) { - data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList(); - } - if (suppTCodes != null) { - data['suppTCodes'] = suppTCodes!.map((v) => v).toList(); - } - return data; - } -} +// class Supplier { +// int? id; +// String? suppliername; +// String? name; +// String? website; +// String? email; +// String? code; +// int? suppNo; +// String? suppStatusId; +// String? cityId; +// String? person; +// String? comment; +// String? zipcode; +// String? contact; +// List? telephones; +// List? faxes; +// List? addresses; +// List? attachments; +// List? suppPersons; +// List? suppTCodes; +// +// Supplier( +// {this.id, +// this.suppliername, +// this.name, +// this.website, +// this.email, +// this.code, +// this.suppNo, +// this.suppStatusId, +// this.cityId, +// this.person, +// this.comment, +// this.zipcode, +// this.contact, +// this.telephones, +// this.faxes, +// this.addresses, +// this.attachments, +// this.suppPersons, +// this.suppTCodes}); +// +// Supplier.fromJson(Map json) { +// id = json['id']; +// suppliername = json['suppliername']; +// name = json['name']; +// website = json['website']; +// email = json['email']; +// code = json['code']; +// suppNo = json['suppNo']; +// suppStatusId = json['suppStatusId']; +// cityId = json['cityId']; +// person = json['person']; +// comment = json['comment']; +// zipcode = json['zipcode']; +// contact = json['contact']; +// if (json['telephones'] != null) { +// telephones = []; +// json['telephones'].forEach((v) { +// telephones!.add(v); +// }); +// } +// if (json['faxes'] != null) { +// faxes = []; +// json['faxes'].forEach((v) { +// faxes!.add(v); +// }); +// } +// if (json['addresses'] != null) { +// addresses = []; +// json['addresses'].forEach((v) { +// addresses!.add(v); +// }); +// } +// if (json['attachments'] != null) { +// attachments = []; +// json['attachments'].forEach((v) { +// attachments!.add(v); +// }); +// } +// if (json['suppPersons'] != null) { +// suppPersons = []; +// json['suppPersons'].forEach((v) { +// suppPersons!.add(SuppPersons.fromJson(v)); +// }); +// } +// if (json['suppTCodes'] != null) { +// suppTCodes = []; +// json['suppTCodes'].forEach((v) { +// suppTCodes!.add(v); +// }); +// } +// } +// +// Map toJson() { +// final Map data = {}; +// data['id'] = id; +// data['suppliername'] = suppliername; +// data['name'] = name; +// data['website'] = website; +// data['email'] = email; +// data['code'] = code; +// data['suppNo'] = suppNo; +// data['suppStatusId'] = suppStatusId; +// data['cityId'] = cityId; +// data['person'] = person; +// data['comment'] = comment; +// data['zipcode'] = zipcode; +// data['contact'] = contact; +// if (telephones != null) { +// data['telephones'] = telephones!.map((v) => v).toList(); +// } +// if (faxes != null) { +// data['faxes'] = faxes!.map((v) => v).toList(); +// } +// if (addresses != null) { +// data['addresses'] = addresses!.map((v) => v).toList(); +// } +// if (attachments != null) { +// data['attachments'] = attachments!.map((v) => v).toList(); +// } +// if (suppPersons != null) { +// data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList(); +// } +// if (suppTCodes != null) { +// data['suppTCodes'] = suppTCodes!.map((v) => v).toList(); +// } +// return data; +// } +// } // class SuppPersons { // int? id; diff --git a/lib/models/service_request/spare_parts.dart b/lib/models/service_request/spare_parts.dart index 5571d179..11f183a9 100644 --- a/lib/models/service_request/spare_parts.dart +++ b/lib/models/service_request/spare_parts.dart @@ -5,7 +5,7 @@ class SparePartsWorkOrders extends Base { SparePartsWorkOrders.fromJson(dynamic json) { id = json['id']; - sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart']) : null; + sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart'],true) : null; qty = json['qty']; returnQty = json['returnQty']; @@ -40,33 +40,37 @@ class SparePart extends Base { this.partNo, this.partName, this.oracleCode, + this.displayName, this.assetId, }) : super(identifier: id?.toString(), name: partName); - SparePart.fromJson(dynamic json) { + SparePart.fromJson(dynamic json,bool ?isDisplayName) { id = json['id']; identifier = id?.toString(); partNo = json['partNo']; partName = json['partName']; + displayName = json['displayName']; oracleCode = json['oracleCode']; - name = partName; + name = isDisplayName!=null&&isDisplayName?displayName: partName; assetId = json['assetId']; } num? id; String? partNo; String? partName; + String? displayName; String? oracleCode; num? assetId; - SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode}) => - SparePart(id: id ?? this.id,oracleCode: oracleCode?? this.oracleCode, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId); + SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode,String ?displayName}) => + SparePart(id: id ?? this.id,oracleCode: oracleCode?? this.oracleCode, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId,displayName: displayName??this.displayName); Map toJson() { final map = {}; map['id'] = id; map['partNo'] = partNo; map['partName'] = partName; + map['displayName'] = displayName; map['oracleCode'] = oracleCode; map['assetId'] = assetId; return map; diff --git a/lib/new_views/pages/land_page/requests/ppm_item_view.dart b/lib/new_views/pages/land_page/requests/ppm_item_view.dart index ba30b5c7..100f47de 100644 --- a/lib/new_views/pages/land_page/requests/ppm_item_view.dart +++ b/lib/new_views/pages/land_page/requests/ppm_item_view.dart @@ -100,7 +100,7 @@ class PpmItemView extends StatelessWidget { 8.height, (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), 8.height, - '${context.translation.assetName}: ${requestDetails!.assetName}'.bodyText(context), + '${context.translation.assetName}: ${requestDetails!.assetName}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index 92ca9575..3979e955 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -126,7 +126,7 @@ class _ServiceRequestDetailViewState extends State { radius: 4, label:'${workOrder.since} days', textColor: AppColor.neutral50, - backgroundColor: AppColor.orange80, + backgroundColor: AppColor.orange30, ), ], 1.width.expanded, diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 36d5c6a4..44b105b8 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -80,7 +80,7 @@ class _SparePartRequestState extends State with TickerProvider _isLoading = true; _files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => MultiFilesPickerModel(e.id!, File(e.name!))).toList() ?? []; setState(() {}); - _spareParts = await _partsProvider!.getPartsList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id); + _spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id); _isLoading = false; setState(() {}); diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index ecd40444..0ad5d7a0 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -106,7 +106,7 @@ class _PpmDetailsPageState extends State { ], ).toShadowContainer(context).paddingAll(16), ).expanded, - if (userProvider!.user!.type == UsersTypes.engineer && (planPreventiveVisit.visitStatus!.id! != 270 && planPreventiveVisit.visitStatus!.id! != 269)) + if (userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly))...[ AppFilledButton( onPressed: () async { await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); @@ -114,6 +114,16 @@ class _PpmDetailsPageState extends State { }, label: context.translation.updateWorkOrder, ).paddingAll(16) + ] + else ...[ + AppFilledButton( + onPressed: () async { + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); + getVisitData(); + }, + label: context.translation.viewDetails, + ).paddingAll(16) + ] ]); }), ), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 0f2c5720..a4161ce5 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -57,6 +57,7 @@ class _RoomInspectionCardState extends State { required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context, }) { + bool status = (model.attribute == null || model.attributeValue == null) ? true : model.attribute != null @@ -65,6 +66,7 @@ class _RoomInspectionCardState extends State { : false : false; + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index aace2400..95a90f16 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -79,7 +79,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { label: context.translation.timer, timer: snapshot.recurrentWoData?.recurrentWoTimerModel, width: double.infinity, - // enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null, + enabled: snapshot.recurrentWoData?.status?.value != 1, decoration: BoxDecoration( color: AppColor.neutral100, borderRadius: BorderRadius.circular(10), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 0edb2d7c..ef25b37b 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -65,7 +65,6 @@ class _RecurrentWorkOrderViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData), - // 8.height, requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty ? Column( children: [ @@ -77,7 +76,7 @@ class _RecurrentWorkOrderViewState extends State { ], ).paddingAll(12), ).paddingOnly(bottom: 85), - if (requestProvider.recurrentWoData?.status?.id != 270) ...[ + if (requestProvider.recurrentWoData?.status?.value != 1) ...[ FooterActionButton.footerContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart index fe6c6ae3..9684d49a 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart @@ -30,7 +30,8 @@ class _PpmCalibrationToolsFormState extends State { @override Widget build(BuildContext context) { final userProvider = Provider.of(context); - int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); + int totalTabs = ppmProvider.totalTabs; int currentIndex = totalTabs == 4 ? 2 : 1; return ListView.separated( itemCount: widget.models!.length + 1, @@ -38,27 +39,30 @@ class _PpmCalibrationToolsFormState extends State { separatorBuilder: (cxt, index) => 16.height, itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More Calibration Tools".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: () async { - if (widget.models?.isNotEmpty ?? false) { - if (widget.models!.last.asset?.id == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); - return; + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More Calibration Tools".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: () async { + if (widget.models?.isNotEmpty ?? false) { + if (widget.models!.last.asset?.id == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); + return; + } + if (widget.models!.last.calibrationDateOfTesters == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); + return; + } } - if (widget.models!.last.calibrationDateOfTesters == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); - return; - } - } - widget.models!.add(PreventiveVisitCalibrations(id: 0)); - setState(() {}); - }, + widget.models!.add(PreventiveVisitCalibrations(id: 0)); + setState(() {}); + }, + ), ); } PreventiveVisitCalibrations model = widget.models![index]; @@ -69,48 +73,51 @@ class _PpmCalibrationToolsFormState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (index == 0 ? "$currentIndex /$totalTabs . Calibration Tools" : "").heading5(context), - "trash".toSvgAsset(height: 20, width: 15).onPress(() { - widget.models!.remove(model); + child: IgnorePointer( + ignoring:ppmProvider.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (index == 0 ? "$currentIndex /$totalTabs . Calibration Tools" : "").heading5(context), + "trash".toSvgAsset(height: 20, width: 15).onPress(() { + widget.models!.remove(model); + setState(() {}); + }), + ], + ), + 16.height, + CalibrationToolAssetPicker( + initialValue: model.asset?.id == null ? null : Lookup(id: model.asset?.id?.toInt(), name: model.asset?.assetNumber ?? ""), + hospitalId: userProvider.user!.clientId, + onPick: (asset) { + model.asset = Asset(id: asset.id, assetNumber: asset.assetNumber, assetSerialNo: asset.assetSerialNo); + setState(() {}); + }, + ), + 12.height, + if (model.asset?.assetNumber != null) + Text("Asset Number: ${model.asset?.assetNumber?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + // if (model.assetName != null) Text("Asset Name: ${model.assetName?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + if (model.asset?.assetSerialNo != null) + Text("Asset Serial No: ${model.asset?.assetSerialNo?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + 12.height, + ADatePicker( + label: context.translation.calibrationDate, + date: DateTime.tryParse(model.calibrationDateOfTesters ?? ""), + from: DateTime.now().subtract(const Duration(days: 90)), + backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral100, + withBorder: false, + hideShadow: true, + onDatePicker: (date) { + model.calibrationDateOfTesters = date.toIso8601String(); setState(() {}); - }), - ], - ), - 16.height, - CalibrationToolAssetPicker( - initialValue: model.asset?.id == null ? null : Lookup(id: model.asset?.id?.toInt(), name: model.asset?.assetNumber ?? ""), - hospitalId: userProvider.user!.clientId, - onPick: (asset) { - model.asset = Asset(id: asset.id, assetNumber: asset.assetNumber, assetSerialNo: asset.assetSerialNo); - setState(() {}); - }, - ), - 12.height, - if (model.asset?.assetNumber != null) - Text("Asset Number: ${model.asset?.assetNumber?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - // if (model.assetName != null) Text("Asset Name: ${model.assetName?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - if (model.asset?.assetSerialNo != null) - Text("Asset Serial No: ${model.asset?.assetSerialNo?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - 12.height, - ADatePicker( - label: context.translation.calibrationDate, - date: DateTime.tryParse(model.calibrationDateOfTesters ?? ""), - from: DateTime.now().subtract(const Duration(days: 90)), - backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral100, - withBorder: false, - hideShadow: true, - onDatePicker: (date) { - model.calibrationDateOfTesters = date.toIso8601String(); - setState(() {}); - }, - ), - ], + }, + ), + ], + ), ), ); }, diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart index 72aba1aa..8fb7db23 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart @@ -237,6 +237,8 @@ // } import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/ppm_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'; @@ -289,20 +291,23 @@ class _PpmExternalDetailsFormState extends State { @override Widget build(BuildContext context) { - print("widget.models!.length:${widget.models!.length}"); + final ppmProvider = Provider.of(context, listen: false); return ListView.builder( itemCount: widget.models!.length + 1, padding: const EdgeInsets.all(16), itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More External Details".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: _addNewEntry, + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More External Details".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: _addNewEntry, + ), ); } // return !isLoading @@ -336,10 +341,12 @@ class ExternalDetailItem extends StatefulWidget { class _ExternalDetailItemState extends State { TextEditingController? controller; + PpmProvider? _ppmProvider; @override void initState() { controller = TextEditingController(text: widget.model.workingHours != null ? widget.model.workingHours.toString() : ''); + _ppmProvider= Provider.of(context,listen:false); super.initState(); } @@ -353,148 +360,151 @@ class _ExternalDetailItemState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), - Container( - height: 32, - width: 32, - padding: const EdgeInsets.all(6), - child: "trash".toSvgAsset(height: 20, width: 20), - ).onPress(() { - widget.onRemove(); - }), - ], - ), - 16.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.supplier, - initialValue: widget.model.supplier, - backgroundColor: AppColor.neutral100, - showAsBottomSheet: true, - showShadow: false, - onSelect: (supplier) { - if (supplier != null) { - setState(() { - widget.model.supplier = supplier; - }); - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.supplierEngineer, - enabled: widget.model.supplier != null, - backgroundColor: AppColor.neutral100, - initialValue: widget.model.suppPerson, - staticData: widget.model.supplier?.suppPersons, - showAsBottomSheet: true, - showShadow: false, - onSelect: (suppPerson) { - if (suppPerson != null) { - widget.model.suppPerson = suppPerson; - } - }, - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.model.startDateTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - setState(() { - widget.model.startDateTime = selectedDateTime; - }); - widget.model.endDateTime = null; - controller?.clear(); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: widget.model.startDateTime, - endTime: widget.model.endDateTime, - workingHoursController: controller!, - updateModel: (hours) { - widget.model.workingHours = hours; - }, - ); - } + child: IgnorePointer( + ignoring: _ppmProvider!.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), + Container( + height: 32, + width: 32, + padding: const EdgeInsets.all(6), + child: "trash".toSvgAsset(height: 20, width: 20), + ).onPress(() { + widget.onRemove(); + }), + ], + ), + 16.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplier, + initialValue: widget.model.supplier, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + showShadow: false, + onSelect: (supplier) { + if (supplier != null) { + setState(() { + widget.model.supplier = supplier; }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.model.endDateTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { - "End Date time must be greater than start date".showToast; - return; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplierEngineer, + enabled: widget.model.supplier != null, + backgroundColor: AppColor.neutral100, + initialValue: widget.model.suppPerson, + staticData: widget.model.supplier?.suppPersons, + showAsBottomSheet: true, + showShadow: false, + onSelect: (suppPerson) { + if (suppPerson != null) { + widget.model.suppPerson = suppPerson; + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.startDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.model.startDateTime = selectedDateTime; + }); + widget.model.endDateTime = null; + controller?.clear(); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); } - setState(() { - widget.model.endDateTime = selectedDateTime; - }); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: widget.model.startDateTime, - endTime: widget.model.endDateTime, - workingHoursController: controller!, - updateModel: (hours) { - widget.model.workingHours = hours; - }, - ); - } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: controller, - textAlign: TextAlign.center, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - ], + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.endDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { + "End Date time must be greater than start date".showToast; + return; + } + setState(() { + widget.model.endDateTime = selectedDateTime; + }); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: controller, + textAlign: TextAlign.center, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], + ), ), ); } diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart index f8c55d5d..7d6e727e 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart @@ -32,6 +32,7 @@ class _PpmPmChecklistFormState extends State { @override Widget build(BuildContext context) { int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); int currentIndex = totalTabs == 4 ? 4 : 3; List? list = widget.checkList ?? []; return (list.isEmpty) @@ -42,68 +43,71 @@ class _PpmPmChecklistFormState extends State { shrinkWrap: true, separatorBuilder: (cxt, index) => 12.height, itemBuilder: (context, index) { - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (index == 0) ...[ - "$currentIndex /$totalTabs . PM Checklist".heading5(context), - 16.height, + return IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (index == 0) ...[ + "$currentIndex /$totalTabs . PM Checklist".heading5(context), + 16.height, + ], + AppTextFormField( + labelText: "Task".addTranslation, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].instructionText?.text ?? "", + enable: false, + showShadow: false, + makeMultiLinesNull: true, + enableColor: AppColor.neutral100, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + // backgroundColor: context.isDark ? AppColor.neutral50 : null, + onChange: (text) { + list[index].taskComment = text; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + showShadow: false, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + initialValue: list[index].taskStatus?.id == null ? null : Lookup(id: list[index].taskStatus?.id?.toInt(), name: list[index].taskStatus?.name), + title: context.translation.taskStatus, + onSelect: (value) { + if (value != null) { + list[index].taskStatus = Lookup(id: value.id, name: value.name, value: value.value); + } + }, + ), + 8.height, + AppTextFormField( + labelText: context.translation.measuredValue, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].measuredValue ?? "", + // enable: false, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + showShadow: false, + onChange: (text) { + list[index].measuredValue = text; + }, + ), + 8.height, + AppTextFormField( + labelText: "Task Comment".addTranslation, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].taskComment ?? "", + textInputType: TextInputType.multiline, + makeMultiLinesNull: true, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + showShadow: false, + onChange: (text) { + list[index].taskComment = text; + }, + ), ], - AppTextFormField( - labelText: "Task".addTranslation, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].instructionText?.text ?? "", - enable: false, - showShadow: false, - makeMultiLinesNull: true, - enableColor: AppColor.neutral100, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - // backgroundColor: context.isDark ? AppColor.neutral50 : null, - onChange: (text) { - list[index].taskComment = text; - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - showShadow: false, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - initialValue: list[index].taskStatus?.id == null ? null : Lookup(id: list[index].taskStatus?.id?.toInt(), name: list[index].taskStatus?.name), - title: context.translation.taskStatus, - onSelect: (value) { - if (value != null) { - list[index].taskStatus = Lookup(id: value.id, name: value.name, value: value.value); - } - }, - ), - 8.height, - AppTextFormField( - labelText: context.translation.measuredValue, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].measuredValue ?? "", - // enable: false, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - showShadow: false, - onChange: (text) { - list[index].measuredValue = text; - }, - ), - 8.height, - AppTextFormField( - labelText: "Task Comment".addTranslation, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].taskComment ?? "", - textInputType: TextInputType.multiline, - makeMultiLinesNull: true, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - showShadow: false, - onChange: (text) { - list[index].taskComment = text; - }, - ), - ], - ).toShadowContainer(context, showShadow: false, borderRadius: 20); + ).toShadowContainer(context, showShadow: false, borderRadius: 20), + ); }, ); } diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart index fc3ffc94..516250a5 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart @@ -26,7 +26,8 @@ class PpmPMKitsForm extends StatefulWidget { class _PpmPMKitsFormState extends State { @override Widget build(BuildContext context) { - int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); + int totalTabs = ppmProvider.totalTabs; int currentIndex = totalTabs == 4 ? 3 : 2; return ListView.builder( itemCount: widget.models!.length + 1, @@ -34,27 +35,30 @@ class _PpmPMKitsFormState extends State { padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More PM Kits".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: () async { - if (widget.models?.isNotEmpty ?? false) { - if (widget.models!.last.partCatalogItem?.partNumber == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNumber}"); - return; + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More PM Kits".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: () async { + if (widget.models?.isNotEmpty ?? false) { + if (widget.models!.last.partCatalogItem?.partNumber == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNumber}"); + return; + } + if (widget.models!.last.partCatalogItem?.partName == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partName}"); + return; + } } - if (widget.models!.last.partCatalogItem?.partName == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partName}"); - return; - } - } - widget.models!.add(PreventiveVisitKits(id: 0)); - setState(() {}); - }, + widget.models!.add(PreventiveVisitKits(id: 0)); + setState(() {}); + }, + ), ); } final model = widget.models![index]; @@ -66,47 +70,50 @@ class _PpmPMKitsFormState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context), - Container( - height: 32, - width: 32, - padding: const EdgeInsets.all(6), - child: "trash".toSvgAsset(height: 20, width: 20), - ).onPress(() { - widget.models!.remove(model); + child: IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context), + Container( + height: 32, + width: 32, + padding: const EdgeInsets.all(6), + child: "trash".toSvgAsset(height: 20, width: 20), + ).onPress(() { + widget.models!.remove(model); + setState(() {}); + }), + ], + ), + 16.height, + AutoCompletePartsField( + assetId: widget.assetId, + clearAfterPick: false, + byName: true, + initialValue: model.partCatalogItem?.partName ?? "", + onPick: (part) { + model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); + setState(() {}); + }, + ), + 8.height, + AutoCompletePartsField( + assetId: widget.assetId, + clearAfterPick: false, + byName: false, + initialValue: model.partCatalogItem?.partNumber ?? "", + onPick: (part) { + model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); setState(() {}); - }), - ], - ), - 16.height, - AutoCompletePartsField( - assetId: widget.assetId, - clearAfterPick: false, - byName: true, - initialValue: model.partCatalogItem?.partName ?? "", - onPick: (part) { - model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); - setState(() {}); - }, - ), - 8.height, - AutoCompletePartsField( - assetId: widget.assetId, - clearAfterPick: false, - byName: false, - initialValue: model.partCatalogItem?.partNumber ?? "", - onPick: (part) { - model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); - setState(() {}); - }, - ), - ], + }, + ), + ], + ), ), ); }, diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index 51255a31..a0fcbf30 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -79,9 +79,12 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { @override void initState() { + ppmProvider = Provider.of(context, listen: false); _planPreventiveVisit = widget.planPreventiveVisit; - initTabs(_planPreventiveVisit.typeOfService); + // WidgetsBinding.instance.addPostFrameCallback((_) { + initTabs(_planPreventiveVisit.typeOfService); + // }); super.initState(); } @@ -112,7 +115,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { backgroundColor: AppColor.neutral110, appBar: DefaultAppBar( title: context.translation.preventiveMaintenance, - onWillPopScope: () { + onWillPopScope:ppmProvider.isReadOnly?null: () { _onSubmit(status: 0); }, ), @@ -186,8 +189,8 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { children: [ if (tabIndex == 1) ...[ AppFilledButton( - buttonColor: _tabController!.index == 0 ? null:AppColor.background(context), - textColor: _tabController!.index == 0 ? null: AppColor.blueStatus(context), + buttonColor: _tabController!.index == 0 ? null : AppColor.background(context), + textColor: _tabController!.index == 0 ? null : AppColor.blueStatus(context), showBorder: true, disableButton: _tabController!.index == 0, onPressed: () { @@ -202,30 +205,47 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ).expanded, 8.width, ], - AppFilledButton( - buttonColor: AppColor.white60, - textColor: AppColor.neutral50, - onPressed: () { - _onSubmit(status: 0); - }, - label: context.translation.save, - ).expanded, - 8.width, - AppFilledButton( - onPressed: () { - if (tabIndex == 0) { - _onSubmit(status: 1); - return; - } - if (ppmProvider.totalTabs == _tabController!.index + 1) { - _onSubmit(status: 1); - } else { - _tabController?.animateTo(_tabController!.index + 1); - setState(() {}); - } - }, - label: tabIndex == 0 ? "Complete".addTranslation : ((ppmProvider.totalTabs == _tabController!.index + 1) ? "Complete".addTranslation : context.translation.next), - ).expanded, + if (!ppmProvider.isReadOnly) ...[ + AppFilledButton( + buttonColor: AppColor.white60, + textColor: AppColor.neutral50, + onPressed: () { + _onSubmit(status: 0); + }, + label: context.translation.save, + ).expanded, + 8.width, + AppFilledButton( + onPressed: () { + if (tabIndex == 0) { + _onSubmit(status: 1); + return; + } + if (ppmProvider.totalTabs == _tabController!.index + 1) { + _onSubmit(status: 1); + } else { + _tabController?.animateTo(_tabController!.index + 1); + setState(() {}); + } + }, + label: tabIndex == 0 ? "Complete".addTranslation : ((ppmProvider.totalTabs == _tabController!.index + 1) ? "Complete".addTranslation : context.translation.next), + ).expanded, + ] else ...[ + Visibility( + visible: tabIndex != 0, + child: AppFilledButton( + onPressed: () { + if(ppmProvider.totalTabs == _tabController!.index + 1){ + Navigator.pop(context); + return; + } + _tabController?.animateTo(_tabController!.index + 1); + setState(() {}); + }, + label:ppmProvider.totalTabs == _tabController!.index + 1? context.translation.close: context.translation.next, + ).expanded, + ), + ] ], ).toShadowContainer(context, showShadow: false, borderRadius: 0), ], diff --git a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart index 577dcc2d..1000d39e 100644 --- a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart @@ -6,8 +6,15 @@ import 'package:test_sa/controllers/providers/api/ppm_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/models/device/model_definition.dart'; +import 'package:test_sa/models/device/supplier.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/building.dart'; +import 'package:test_sa/models/new_models/department.dart'; +import 'package:test_sa/models/new_models/floor.dart'; +import 'package:test_sa/models/new_models/room_model.dart'; +import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/providers/ppm_asset_availability_provider.dart'; @@ -59,232 +66,238 @@ class _WoInfoFormState extends State { totalWorkingHours = totalWorkingHours; return Consumer(builder: (context, ppmProvider, child) { + return ListView( padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.planPreventiveVisit.visitStatus != null) - StatusLabel( - label: widget.planPreventiveVisit.visitStatus?.name, - textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), - backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), - ), - 8.height, - widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), - 2.height, - '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), - //need to add in translation it's suggestion from ahmed.. - 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.creationDate}: ${widget.planPreventiveVisit.creationDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.closedDate}: ${widget.planPreventiveVisit.closedDate != null ? widget.planPreventiveVisit.closedDate?.toMonthYearFormat : '-'}' - .bodyText2(context) - .custom(color: AppColor.neutral120), - - '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' - .bodyText2(context) - .custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), - 12.height, - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), - "info_icon".toSvgAsset(height: 17, width: 17).onPress( - () { - // There is only limited information for asset is returned from backend to show all info need to return the whole model from backend... - showModalBottomSheet( - context: context, - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - clipBehavior: Clip.antiAliasWithSaveLayer, - builder: (BuildContext context) => _buildAssetDetailBottomSheet(context), - ); - }, - ) - ], - ), - 2.height, - '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), + IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.planPreventiveVisit.visitStatus != null) + StatusLabel( + label: widget.planPreventiveVisit.visitStatus?.name, + textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + ), + 8.height, + widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), + 2.height, + '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), + //need to add in translation it's suggestion from ahmed.. + 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.creationDate}: ${widget.planPreventiveVisit.creationDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.closedDate}: ${widget.planPreventiveVisit.closedDate != null ? widget.planPreventiveVisit.closedDate?.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), - // SingleItemDropDownMenu( - // context: context, - // initialValue: - // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), - // title: context.translation.ppmVisit, - // onSelect: (value) { - // if (value?.value == 4) { - // "Status cannot be change to ${value?.name}.".addTranslation.showToast; - // setState(() {}); - // return; - // } - // - // if (value != null) { - // widget.planPreventiveVisit.visitStatus?.name = value.name; - // widget.planPreventiveVisit.visitStatus?.id = value.id; - // } - // }, - // ), + '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), + 12.height, + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), + "info_icon".toSvgAsset(height: 17, width: 17).onPress( + () { + // There is only limited information for asset is returned from backend to show all info need to return the whole model from backend... + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => _buildAssetDetailBottomSheet(context), + ); + }, + ) + ], + ), + 2.height, + '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), - // SingleItemDropDownMenu( - // context: context, - // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), - // title: context.translation.deviceStatus, - // onSelect: (value) { - // if (value != null) { - // widget.planPreventiveVisit.deviceStatusId = value.id; - // widget.planPreventiveVisit.deviceStatusName = value.name; - // } - // }, - // ), - 8.height, - Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - //TODO Ahmed need to provide look up value.... + // SingleItemDropDownMenu( + // context: context, + // initialValue: + // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), + // title: context.translation.ppmVisit, + // onSelect: (value) { + // if (value?.value == 4) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // + // if (value != null) { + // widget.planPreventiveVisit.visitStatus?.name = value.name; + // widget.planPreventiveVisit.visitStatus?.id = value.id; + // } + // }, + // ), - SingleItemDropDownMenu( - context: context, - showShadow: false, - initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), - title: context.translation.pmTestResult, - backgroundColor: AppColor.neutral100, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.taskStatus = value; - } - }, - ), - 8.height, - ADatePicker( - label: context.translation.actualVisit, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.planPreventiveVisit.acutalDateOfVisit, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - setState(() { - widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime; - }); - } - }); - }, - ), - // SingleItemDropDownMenu( - // context: context, - // backgroundColor: AppColor.neutral100, - // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), - // title: context.translation.actualVisit, - // onSelect: (value) { - // if (value != null) { - // widget.planPreventiveVisit.safety = value; - // // widget.planPreventiveVisit.safety?.id = value.id; - // // widget.planPreventiveVisit.safety?.name = value.name; - // } - // }, - // ), + // SingleItemDropDownMenu( + // context: context, + // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), + // title: context.translation.deviceStatus, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.deviceStatusId = value.id; + // widget.planPreventiveVisit.deviceStatusName = value.name; + // } + // }, + // ), + 8.height, + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SingleItemDropDownMenu( + context: context, + showShadow: false, + initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), + title: context.translation.pmTestResult, + backgroundColor: AppColor.neutral100, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.taskStatus = value; + } + }, + ), + 8.height, + ADatePicker( + label: context.translation.actualVisit, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.planPreventiveVisit.acutalDateOfVisit, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime; + }); + } + }); + }, + ), + // SingleItemDropDownMenu( + // context: context, + // backgroundColor: AppColor.neutral100, + // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + // title: context.translation.actualVisit, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.safety = value; + // // widget.planPreventiveVisit.safety?.id = value.id; + // // widget.planPreventiveVisit.safety?.name = value.name; + // } + // }, + // ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), - title: "Electrical Safety", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.safety = value; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.assetAvailability == null - ? null - : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), - title: "Asset Availability", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.assetAvailability = value; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.typeOfService == null - ? null - : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), - title: context.translation.typeOfPm, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.typeOfService = value; - if (widget.planPreventiveVisit.typeOfService?.id == 66) { - ppmProvider.totalTabs = 4; - } else { - ppmProvider.totalTabs = 3; - } - widget.onTypeOfServiceChange!(value); - } - }, - ), - 8.height, - _timerWidget(context, totalWorkingHours), - 8.height, - AppTextFormField( - labelText: context.translation.comment, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - onChange: (value) { - widget.planPreventiveVisit.comments = value; - }, - ), - 16.height, - MultiFilesPicker( - label: context.translation.attachments, - files: ppmProvider.ppmPlanAttachments, - buttonColor: AppColor.black10, - onlyImages: false, - buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), - ), - ], - ).toShadowContainer(context), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + title: "Electrical Safety", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.safety = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.assetAvailability == null + ? null + : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), + title: "Asset Availability", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.assetAvailability = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.typeOfService == null + ? null + : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), + title: context.translation.typeOfPm, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.typeOfService = value; + if (widget.planPreventiveVisit.typeOfService?.id == 66) { + ppmProvider.totalTabs = 4; + } else { + ppmProvider.totalTabs = 3; + } + widget.onTypeOfServiceChange!(value); + } + }, + ), + 8.height, + _timerWidget(context, totalWorkingHours), + 8.height, + AppTextFormField( + labelText: context.translation.comment, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + onChange: (value) { + widget.planPreventiveVisit.comments = value; + }, + ), + 16.height, + MultiFilesPicker( + label: context.translation.attachments, + files: ppmProvider.ppmPlanAttachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + ], + ).toShadowContainer(context), + ], + ), + ), //TODO need to check this also... // ESignature( // title: context.translation.nurseSignature, @@ -311,8 +324,18 @@ class _WoInfoFormState extends State { _buildAssetDetailBottomSheet(BuildContext context) { PlanPreventiveVisit model = widget.planPreventiveVisit; - - Asset asset = Asset(id: model.asset?.id, assetSerialNo: model.asset?.assetSerialNo, assetNumber: model.asset?.assetNumber); + Asset asset = Asset( + id: model.asset?.id, + assetSerialNo: model.asset?.assetSerialNo, + assetNumber: model.asset?.assetNumber, + building: Building(name: model.buildingName), + floor: Floor(name: model.floorName), + site: Site(custName: model.siteName), + supplier: Supplier(suppliername: model.supplierName), + modelDefinition: ModelDefinition(modelName: model.model, manufacturerName: model.manufacturer), + room: Rooms(value: int.tryParse(model.roomName??'')), + department: Department(departmentName: model.departmentName), + ); return AssetDetailBottomSheet(asset); } From 045c890a27b2440fde150b07dd67b6d5bb52adac Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Tue, 8 Apr 2025 09:59:18 +0300 Subject: [PATCH 20/36] bug fixes --- lib/extensions/widget_extensions.dart | 8 ++++---- .../maintenance_request/maintenance_request_main.dart | 4 ++-- .../recurrent_wo/recurrent_work_order_view.dart | 2 +- lib/views/pages/user/ppm/update_ppm/update_ppm.dart | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index dd971fd4..7d8dd44f 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -55,15 +55,15 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); - Widget handlePopScope(BuildContext _cxt, VoidCallback onSave,) { - return PopScope( + Widget handlePopScope({required BuildContext cxt, required VoidCallback onSave, bool? showPopUp =true}) { + return showPopUp! ? PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) { return; } showDialog( - context: _cxt, + context: cxt, builder: (BuildContext cxt) => AcknowledgeWorkDialog( onSave: () => onSave(), onDiscard: () { @@ -72,7 +72,7 @@ extension WidgetExtensions on Widget { ), ); }, - child: this); + child: this):const SizedBox(); } Widget toShimmer({bool isShow = true, double radius = 20}) => isShow diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index ad0e5f01..3bc93f10 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -111,8 +111,8 @@ class _MaintenanceRequestFormState extends State with Si ), ], ), - ).handlePopScope(context, () { - requestDetailProvider.isReadOnlyRequest ? null : save(requestDetailProvider); + ).handlePopScope(cxt: context, showPopUp: !requestDetailProvider.isReadOnlyRequest, onSave: () { + save(requestDetailProvider); }); }); } diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index ef25b37b..93a67e1b 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -100,7 +100,7 @@ class _RecurrentWorkOrderViewState extends State { ], ) : NoDataFound(message: context.translation.noDataFound).center, - ).handlePopScope(context, () { + ).handlePopScope(cxt: context,onSave: () { _updateTask(context: context, status: 0); }); }); diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index a0fcbf30..9188e24c 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -251,7 +251,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ], ), ), - ).handlePopScope(context, () { + ).handlePopScope(cxt: context, showPopUp:!ppmProvider.isReadOnly ,onSave: () { _onSubmit(status: 0); }); } From 5031c3cbb881759e0e97cdd0a580264bddf201c5 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Wed, 9 Apr 2025 09:07:34 +0300 Subject: [PATCH 21/36] gas refill fixes --- lib/controllers/api_routes/urls.dart | 12 ++++++------ .../providers/api/gas_refill_comments.dart | 4 ++-- .../providers/api/gas_refill_provider.dart | 2 +- .../activity_maintenance_model.dart | 1 - lib/models/new_models/gas_refill_model.dart | 10 +++++----- .../land_page/requests/gas_refill_item_view.dart | 2 ++ .../pages/user/gas_refill/gas_refill_details.dart | 10 +++++----- 7 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 900aafd6..7f0995d8 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -169,12 +169,12 @@ class URLs { static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // get - static get requestGasRefill => "$_baseUrl/GazRefill/AddGazRefill"; // get - static get updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get - static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // get - static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get - static get getGazRefillComments => "$_baseUrl/GazRefill/GetHistoryComments"; // get - static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add + static get requestGasRefill => "$_baseUrl/GasRefill/AddGasRefill"; // get + static get updateGasRefill => "$_baseUrl/GasRefill/UpdateGasRefill"; // get + static get getGasRefill => "$_baseUrl/GasRefill/GetGasRefills"; // get + static get getGasRefillById => "$_baseUrl/GasRefill/GetGasRefillById"; // get + static get getGasRefillComments => "$_baseUrl/GasRefill/GetHistoryComments"; // get + static get addGasRefillComment => "$_baseUrl/GasRefill/AddHistoryComment"; // add //device transfer static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get diff --git a/lib/controllers/providers/api/gas_refill_comments.dart b/lib/controllers/providers/api/gas_refill_comments.dart index 71e85f01..281ba4b3 100644 --- a/lib/controllers/providers/api/gas_refill_comments.dart +++ b/lib/controllers/providers/api/gas_refill_comments.dart @@ -47,7 +47,7 @@ class GasRefillCommentsProvider extends ChangeNotifier { notifyListeners(); late Response response; try { - response = await ApiManager.instance.get(URLs.getGazRefillComments + "?gasRefillId=$callId"); + response = await ApiManager.instance.get(URLs.getGasRefillComments + "?gasRefillId=$callId"); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { @@ -87,7 +87,7 @@ class GasRefillCommentsProvider extends ChangeNotifier { late Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.post(URLs.addGazRefillComment, body: {"id": 0, "gasRefillId": id, "comment": comment}); + response = await ApiManager.instance.post(URLs.addGasRefillComment, body: {"id": 0, "gasRefillId": id, "comment": comment}); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index a5d59016..c2892a0d 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -46,7 +46,7 @@ class GasRefillProvider extends ChangeNotifier { Future getGasRefillObjectById(num id) async { try { - Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gazRefillId=$id"); + Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id"); if (response.statusCode >= 200 && response.statusCode < 300) { return GasRefillModel.fromJson(json.decode(response.body)["data"]); diff --git a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart index 046cf913..9580c1a9 100644 --- a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart +++ b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart @@ -12,7 +12,6 @@ class ActivityMaintenanceHelperModel { //remove this int? lastSituationId; Lookup? lastSituation; - Lookup? activityStatus; DateTime? startTime; DateTime? endTime; diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 938d94e4..61f566c4 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -42,7 +42,7 @@ class GasRefillModel { GasRefillModel.fromJson(dynamic json) { id = json['id']; - gazRefillNo = json['gazRefillNo']; + gazRefillNo = json['gasRefillNo']; expectedDate = json['expectedDate']; expectedTime = json['expectedTime']; startDate = json['startDate']; @@ -80,9 +80,9 @@ class GasRefillModel { department = json['department'] != null ? Department.fromJson(json['department']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; status = json['status'] != null ? Lookup.fromJson(json['status']) : null; - if (json['gazRefillDetails'] != null) { + if (json['gasRefillDetails'] != null) { gazRefillDetails = []; - json['gazRefillDetails'].forEach((v) { + json['gasRefillDetails'].forEach((v) { gazRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gazRefillDetails is initialized here }); } @@ -167,7 +167,7 @@ class GasRefillModel { Map toJson() { final map = {}; map['id'] = id ?? 0; - map['gazRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; + map['gasRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; map['expectedDate'] = expectedDate; map['expectedTime'] = expectedTime; map['startDate'] = startDate; @@ -201,7 +201,7 @@ class GasRefillModel { map['status'] = status?.toJson(); // Use '?.' for null safety } if (gazRefillDetails != null) { - map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null + map['gasRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null } return map; } 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 a817e22f..00f848f6 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,7 +21,9 @@ class GasRefillItemView extends StatelessWidget { @override Widget build(BuildContext context) { + if (requestData != null) { + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index b341c310..424410b1 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -109,9 +109,9 @@ class _GasRefillDetailsPageState extends State { context.translation.gasRefillRequest.heading5(context), 8.height, - '${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails![0].gasType?.name}'.bodyText(context), - '${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails![0].cylinderType?.name}'.bodyText(context), - '${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails![0].cylinderSize?.name}'.bodyText(context), + '${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails?[0].gasType?.name}'.bodyText(context), + '${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails?[0].cylinderType?.name}'.bodyText(context), + '${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails?[0].cylinderSize?.name}'.bodyText(context), '${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.requestNo}: ${gasRefillModel.gazRefillNo}'.bodyText(context), @@ -122,8 +122,8 @@ class _GasRefillDetailsPageState extends State { infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), const Divider().defaultStyle(context), - '${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), - '${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), + '${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails?[0].requestedQty ?? 0}'.bodyText(context), + '${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails?[0].deliverdQty ?? 0}'.bodyText(context), 8.height, if (gasRefillModel.comment?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), From 6795ba7f7208af2945fd8aba5373adf78c1db0eb Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Wed, 9 Apr 2025 09:39:04 +0300 Subject: [PATCH 22/36] device transfer gas refill merged in ppm_newflow --- lib/controllers/providers/api/gas_refill_comments.dart | 4 ++-- lib/l10n/app_ar.arb | 4 ++-- lib/l10n/app_en.arb | 4 ++-- lib/new_views/common_widgets/default_app_bar.dart | 5 +++-- .../views/components/activities_list_view.dart | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/controllers/providers/api/gas_refill_comments.dart b/lib/controllers/providers/api/gas_refill_comments.dart index 281ba4b3..71e85f01 100644 --- a/lib/controllers/providers/api/gas_refill_comments.dart +++ b/lib/controllers/providers/api/gas_refill_comments.dart @@ -47,7 +47,7 @@ class GasRefillCommentsProvider extends ChangeNotifier { notifyListeners(); late Response response; try { - response = await ApiManager.instance.get(URLs.getGasRefillComments + "?gasRefillId=$callId"); + response = await ApiManager.instance.get(URLs.getGazRefillComments + "?gasRefillId=$callId"); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { @@ -87,7 +87,7 @@ class GasRefillCommentsProvider extends ChangeNotifier { late Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.post(URLs.addGasRefillComment, body: {"id": 0, "gasRefillId": id, "comment": comment}); + response = await ApiManager.instance.post(URLs.addGazRefillComment, body: {"id": 0, "gasRefillId": id, "comment": comment}); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index b80e88e9..826307a2 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -551,8 +551,8 @@ "externalEngineerName": "اسم المهندس الخارجي", "telephone": "الهاتف", "transferAsset": "نقل الأصل", - "createAssetTransferRequest": "إنشاء طلب نقل أصل" - "telephone": "الهاتف", + "createAssetTransferRequest": "إنشاء طلب نقل أصل", + "arrivedDate": "تاريخ الوصول", "closedDate": "تاريخ الإغلاق", "since": "منذ", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index aa710514..0ca42862 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -552,9 +552,9 @@ "attachments": "Attachments", "supplierName": "Supplier Name", "externalEngineerName": "External Engineer Name", - "telephone": "Telephone", + "transferAsset": "Transfer Asset", - "createAssetTransferRequest": "Create Asset Transfer Request" + "createAssetTransferRequest": "Create Asset Transfer Request", "telephone": "Telephone", "arrivedDate": "Arrived Date", "closedDate": "Closed Date", diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index 7d28abaa..faaca183 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -14,8 +14,9 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { final Function? onBackPress; final bool showHomeActionButton; final VoidCallback? onWillPopScope; + final TextStyle? titleStyle; - const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); + const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions,this.titleStyle, this.showHomeActionButton = false, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -63,7 +64,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { 10.width, Text( title ?? "", - style: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + style:titleStyle?? AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ).expanded, ], ), diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 1acd0ba2..94a70328 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -364,7 +364,7 @@ class _ActivitiesListViewState extends State { ], ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { if (requestDetailProvider.isReadOnlyRequest) { - onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); + // onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); } }); } From e74f506be0ab69bc3b26e57cbdcd96d09f31abbe Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Wed, 9 Apr 2025 16:48:13 +0300 Subject: [PATCH 23/36] part avalibility ui implemented --- lib/controllers/api_routes/urls.dart | 9 +- lib/models/service_request/spare_parts.dart | 45 ++++++++++ .../service_request_detail_provider.dart | 38 ++++++++ .../components/activities_list_view.dart | 6 +- .../forms/spare_part/spare_part_request.dart | 90 ++++++++++++++++++- 5 files changed, 180 insertions(+), 8 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 89e78aee..edc1bcfe 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -3,12 +3,12 @@ class URLs { static const String appReleaseBuildNumber = "14"; // 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"; // new V3 apis static String _host = host1; @@ -159,6 +159,7 @@ class URLs { static get getAssetTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=500"; // get static get getPersonRoles => "$_baseUrl/Lookups/GetLookup?lookupEnum=36"; // get static get getPartNumber => "$_baseUrl/PartCatalog/GetPartAutoComplete"; // get + static get getSparePartAvailableQuantity => "$_baseUrl/SparePart/GetAvailablityQtyForSparePartByPartId"; // get static get getServiceReportPriority => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get diff --git a/lib/models/service_request/spare_parts.dart b/lib/models/service_request/spare_parts.dart index 11f183a9..8b4be559 100644 --- a/lib/models/service_request/spare_parts.dart +++ b/lib/models/service_request/spare_parts.dart @@ -76,3 +76,48 @@ class SparePart extends Base { return map; } } + +class StoreAvailability { + final int ?id; + final int? storeId; + final int ?availablityQty; + final String? siteName; + final String ?storeName; + final int? requestedQty; + final bool? alreadyRequestFromThisStore; + + StoreAvailability({ + this.id, + this.storeId, + this.availablityQty, + this.siteName, + this.storeName, + this.requestedQty, + this.alreadyRequestFromThisStore, + }); + + factory StoreAvailability.fromJson(Map json) { + return StoreAvailability( + id: json['id'] ?? 0, + storeId: json['storeId'] ?? 0, + availablityQty: json['availablityQty'] ?? 0, + siteName: json['siteName'] ?? '', + storeName: json['storeName'] ?? '', + requestedQty: json['requestedQty'] ?? 0, + alreadyRequestFromThisStore: json['alreadyRequestFromThisStore'] ?? false, + ); + } + + Map toJson() { + return { + 'id': id, + 'storeId': storeId, + 'availablityQty': availablityQty, + 'siteName': siteName, + 'storeName': storeName, + 'requestedQty': requestedQty, + 'alreadyRequestFromThisStore': alreadyRequestFromThisStore, + }; + } +} + diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index 7fa906f7..2902002b 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -14,6 +14,7 @@ import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_mo import 'package:test_sa/models/new_models/arrival_verification_type_model.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; +import 'package:test_sa/models/service_request/spare_parts.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; @@ -104,6 +105,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier { AssetRetiredHelperModel? assetRetiredHelperModel = AssetRetiredHelperModel(); ActivityMaintenanceHelperModel? activityMaintenanceHelperModel = ActivityMaintenanceHelperModel(); SparePartHelperModel? sparePartHelperModel; + List _storeAvailability= []; + + List get storeAvailability => _storeAvailability; + + set storeAvailability(List value) { + _storeAvailability = value; + notifyListeners(); + } + FixRemotelyHelperModel? fixRemotelyHelperModel = FixRemotelyHelperModel(); NeedVisitHelperModel? needVisitHelperModel = NeedVisitHelperModel(); NurseActionHelperModel? nurseActionHelperModel; @@ -242,6 +252,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + //upload workorder attachment by engineer.. Future addWorkOrderAttachment({required int woId, required List attachments}) async { try { @@ -742,6 +753,33 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + Future getStoreAvailabilityById({required num? partId}) async { + try { + isLoading = true; + notifyListeners(); + + final response = await ApiManager.instance.post( + URLs.getSparePartAvailableQuantity + "?PartId=$partId", + body: {}, + ); + + print('response i got is ${response.body}'); + stateCode = response.statusCode; + + if (response.statusCode >= 200 && response.statusCode < 300) { + final List data = json.decode(response.body)["data"]; + storeAvailability = data.map((item) => StoreAvailability.fromJson(item)).toList(); + } + + isLoading = false; + notifyListeners(); + } catch (e) { + log("getStoreAvalivility [error] : $e"); + isLoading = false; + notifyListeners(); + } + } + Future deleteActivitySparePart({required int id, required int workOrderId}) async { isLoading = true; notifyListeners(); diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 94a70328..54b09a45 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -363,9 +363,9 @@ class _ActivitiesListViewState extends State { // ] ], ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { - if (requestDetailProvider.isReadOnlyRequest) { - // onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); - } + // if (requestDetailProvider.isReadOnlyRequest) { + // onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); + // } }); } diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 44b105b8..8b1454a6 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/parts_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -11,6 +12,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/size_config.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/single_item_drop_down_menu.dart'; @@ -19,6 +21,7 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/views/widgets/images/new_multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import '../../../../../../models/service_request/spare_parts.dart'; import '../../../../../../new_views/common_widgets/app_text_form_field.dart'; @@ -119,6 +122,7 @@ class _SparePartRequestState extends State with TickerProvider key: _scaffoldKey, appBar: DefaultAppBar(title: context.translation.sparePartRequest), body: Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { + print('data i got is ${requestDetailProvider.sparePartHelperModel?.sparePart?.toJson()}'); return SafeArea( child: Form( key: _formKey, @@ -155,7 +159,7 @@ class _SparePartRequestState extends State with TickerProvider loading: _isLoading, initialValue: requestDetailProvider.sparePartHelperModel?.sparePart, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, - onSelect: (part) { + onSelect: (part) async { if (part != null) { requestDetailProvider.sparePartHelperModel?.sparePart = part; _oracleNoController.text = part.oracleCode ?? ''; @@ -163,6 +167,36 @@ class _SparePartRequestState extends State with TickerProvider } }, ), + + if(requestDetailProvider.sparePartHelperModel?.sparePart?.id!=null)...[ + 12.height, + SizedBox( + height: 30.toScreenHeight, + child: Text('View Parts Availability',style:TextStyle( + fontSize: 12.toScreenWidth, + fontWeight: FontWeight.w500, + fontStyle: FontStyle.normal, + color:AppColor.primary10 , + decorationColor: AppColor.primary10, + decoration: TextDecoration.underline, + )).onPress( + () async { + requestDetailProvider.getStoreAvailabilityById(partId: requestDetailProvider.sparePartHelperModel?.sparePart?.id); + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => PartDetailBottomSheetSheet(), + ); + }, + ), + ), + ], 12.height, AppTextFormField( controller: _partQtyController, @@ -309,4 +343,58 @@ class _SparePartRequestState extends State with TickerProvider }), ); } + +} + + +class PartDetailBottomSheetSheet extends StatelessWidget { + + PartDetailBottomSheetSheet( {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: SizeConfig.screenHeight!/2.2, + width: SizeConfig.screenWidth, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + 'Parts Availability'.heading6(context).paddingOnly(top: 12,start: 12), + Consumer( + builder: (context, requestDetailProvider,child) { + return requestDetailProvider.isLoading + ? const CircularProgressIndicator(color: AppColor.primary10).center + : requestDetailProvider.storeAvailability.isEmpty + ? const NoDataFound().center + : ListView.separated( + padding: const EdgeInsets.all(16), + itemCount: requestDetailProvider.storeAvailability.length, + separatorBuilder: (czt, index) => 12.height, + itemBuilder: (context, index) { + StoreAvailability model = requestDetailProvider.storeAvailability[index]; + return partAvailableQuantityCard(context: context,model:model); + }, + ); + } + ).expanded, + ], + ), + ); + } + Widget partAvailableQuantityCard({required StoreAvailability model,required BuildContext context }){ + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 'Site Name: ${model.siteName??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + 'Store Name: ${model.storeName??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + 'Available Quantity: ${model.availablityQty??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + ] + ).toShadowContainer(context, padding: 12, showShadow: false,backgroundColor: AppColor.neutral110); + } } From 4d45dcf0b9c6ddb71d5d7e82553c0bebba66e2bb Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Sun, 13 Apr 2025 11:37:26 +0300 Subject: [PATCH 24/36] maintenance request complete ui issue fixes --- lib/extensions/widget_extensions.dart | 2 +- .../views/components/activities_list_view.dart | 17 ++++++++++++++--- .../maintenance_request_main.dart | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 7d8dd44f..6d9ba5af 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -72,7 +72,7 @@ extension WidgetExtensions on Widget { ), ); }, - child: this):const SizedBox(); + child: this): this; } Widget toShimmer({bool isShow = true, double radius = 20}) => isShow diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 54b09a45..cb1b7932 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -363,9 +363,9 @@ class _ActivitiesListViewState extends State { // ] ], ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { - // if (requestDetailProvider.isReadOnlyRequest) { - // onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); - // } + if (requestDetailProvider.isReadOnlyRequest) { + onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); + } }); } @@ -446,3 +446,14 @@ class ReorderWidget extends StatelessWidget { ); } } +class DummyClass extends StatelessWidget { + const DummyClass({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + + + diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index 3bc93f10..9da93430 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -47,7 +47,7 @@ class _MaintenanceRequestFormState extends State with Si Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; - return Scaffold( + return Scaffold( backgroundColor: AppColor.neutral110, appBar: DefaultAppBar( title: "CM Activity", From b506616f4831e7c0e4d54408ea5cf65094127e33 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Mon, 14 Apr 2025 15:48:30 +0300 Subject: [PATCH 25/36] bug fixes for recurrent task and service request added missing details mentioned in bugs sheet --- .../workorder/work_order_helper_models.dart | 3 ++ .../requests/recurrent_wo_item_view.dart | 4 +- .../requests/service_request_item_view.dart | 10 ++-- .../service_request_detail_view.dart | 47 +++++++++---------- .../asset_retired/verify_asset_detail.dart | 19 +++++++- .../components/task_info_widget.dart | 8 ++-- 6 files changed, 55 insertions(+), 36 deletions(-) diff --git a/lib/models/helper_data_models/workorder/work_order_helper_models.dart b/lib/models/helper_data_models/workorder/work_order_helper_models.dart index 2eae7084..a1fcdc26 100644 --- a/lib/models/helper_data_models/workorder/work_order_helper_models.dart +++ b/lib/models/helper_data_models/workorder/work_order_helper_models.dart @@ -81,6 +81,7 @@ class EngineerUpdateWorkOrderHelperModel { Lookup? failureReason; FaultDescription? faultDescription; String? solution; + String? callResponse; EngineerUpdateWorkOrderHelperModel({ this.workOrderId, @@ -93,6 +94,7 @@ class EngineerUpdateWorkOrderHelperModel { this.serviceType, this.solution, this.returnToService, + this.callResponse, }); Map toJson() { @@ -104,6 +106,7 @@ class EngineerUpdateWorkOrderHelperModel { data['loanAssetId'] = loanAssetId; data['failureReasonId'] = failureReason?.id; data['faultDescriptionId'] = faultDescription?.id; + data['callResponse'] = callResponse; return data; } } diff --git a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart index ec9223f3..1387d6dc 100644 --- a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart +++ b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart @@ -52,7 +52,7 @@ class RecurrentWoItemView extends StatelessWidget { // '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + '${context.translation.taskNo}: ${requestData!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, @@ -102,7 +102,7 @@ class RecurrentWoItemView extends StatelessWidget { // '${context.translation.taskNo}: ${requestDetails!.id}'.bodyText(context), '${context.translation.site}: ${requestDetails!.site}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + '${context.translation.taskNo}: ${requestDetails!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/new_views/pages/land_page/requests/service_request_item_view.dart b/lib/new_views/pages/land_page/requests/service_request_item_view.dart index 928dc950..4eb0fbef 100644 --- a/lib/new_views/pages/land_page/requests/service_request_item_view.dart +++ b/lib/new_views/pages/land_page/requests/service_request_item_view.dart @@ -52,12 +52,14 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, (requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context), 8.height, - '${context.translation.assetName}: ${requestData!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + '${context.translation.assetName}: ${requestData?.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + '${context.translation.assetNumber}: ${requestData?.assetNumber}'.bodyText(context), + // '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), 'CM Number: ${requestData!.requestNo}'.bodyText(context), if (requestData?.statusName == 'Canceled') ...[ - '${context.translation.rejectionReason}: ${requestData!.rejectReason}'.bodyText(context), + '${context.translation.rejectionReason}: ${requestData?.rejectReason}'.bodyText(context), ], 8.height, Row( @@ -112,9 +114,9 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, // '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), - 'CM Number: ${requestDetails!.requestNo}'.bodyText(context), - '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), + 'CM Number: ${requestDetails!.requestNo}'.bodyText(context), 8.height, Row( diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index 3979e955..c4d25e0e 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -120,11 +120,11 @@ class _ServiceRequestDetailViewState extends State { textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!), backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!), ), - if(workOrder.since!=null)...[ + if (workOrder.since != null) ...[ 8.width, StatusLabel( radius: 4, - label:'${workOrder.since} days', + label: '${workOrder.since} days', textColor: AppColor.neutral50, backgroundColor: AppColor.orange30, ), @@ -296,21 +296,21 @@ class _ServiceRequestDetailViewState extends State { ), ], - 8.height, - const Divider().defaultStyle(context), - MultiFilesPicker( - label: context.translation.attachments, - files: _workOrderAttachments, - // attachment: _workOrderAttachments, - buttonColor: AppColor.primary10, - onlyImages: false, - buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), - onChange: (attachment) { - print('i am called.'); - // print('attachment value is ${attachment.last.file?.path}'); - requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); - }, - ), + if (!requestProvider.isReadOnlyRequest) ...[ + 8.height, + const Divider().defaultStyle(context), + MultiFilesPicker( + label: context.translation.attachments, + files: _workOrderAttachments, + // attachment: _workOrderAttachments, + buttonColor: AppColor.primary10, + onlyImages: false, + buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), + onChange: (attachment) { + requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); + }, + ), + ], if (workOrder.voiceNote?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), @@ -403,27 +403,27 @@ class _ServiceRequestDetailViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '${workOrder.workOrderContactPerson[index].name??'-'}', + '${workOrder.workOrderContactPerson[index].name ?? '-'}', style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), Text( - '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId??'-'}', + '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone??'-'}', + '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Job: ${workOrder.workOrderContactPerson[index].position??'-'}', + 'Job: ${workOrder.workOrderContactPerson[index].position ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email??'-'}', + '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Extension: ${workOrder.workOrderContactPerson[index].extension??'-'}', + 'Extension: ${workOrder.workOrderContactPerson[index].extension ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], @@ -473,7 +473,6 @@ class _ServiceRequestDetailViewState extends State { } Widget assetDetailCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) { - print('id i got is ${requestDetailProvider.currentWorkOrder?.data?.status?.id}'); if ((userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) || requestDetailProvider.isReadOnlyRequest) { WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!; diff --git a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart index 25c26a43..6952d29b 100644 --- a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart +++ b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart @@ -13,6 +13,7 @@ import 'package:test_sa/models/new_models/work_order_detail_model.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_lazy_loading.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.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/service_request_providers/equipment_status_provider.dart'; @@ -74,6 +75,7 @@ class _VerifyAssetDetailsState extends State with TickerProv solution: currentWorkOrderData.faultDescription?.workPerformed, returnToService: currentWorkOrderData.returnToService, serviceType: currentWorkOrderData.serviceType, + callResponse: currentWorkOrderData.callResponse, ); if (currentWorkOrderData.assetLoan != null) { loanAvailabilityAsset = Asset( @@ -219,9 +221,22 @@ class _VerifyAssetDetailsState extends State with TickerProv context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), 8.height, requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null - ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120) + ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120,align: TextAlign.justify) : const SizedBox(), - ] + ], + 8.height, + AppTextFormField( + labelText: context.translation.callResponse, + backgroundColor: AppColor.neutral100, + initialValue: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.callResponse, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + onChange: (value){ + requestDetailProvider.engineerUpdateWorkOrderHelperModel?.callResponse = value; + }, + style: Theme.of(context).textTheme.titleMedium, + ), ], ).toShadowContainer(context).paddingAll(16), ).expanded, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index ce72938b..26f5ba20 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -51,11 +51,11 @@ class RecurrentTaskInfoWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.department, value: model!.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.floor, value: model!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.room, value: model!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, _timerWidget(context, model!.totalWorkingHours!), 8.height, @@ -129,7 +129,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { } } -Widget buildingInfoWidget({required String label, required String value, required BuildContext context}) { +Widget buildingInfoWidget({required String label, required String ?value, required BuildContext context}) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, From f043c6ff6c70aba810168de3a47084f8079264be Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Apr 2025 14:49:29 +0300 Subject: [PATCH 26/36] point 8 fixed, --- .../my_request/all_requests_filter_page.dart | 38 +- .../components/assistant_employee_list.dart | 546 ++++++++++++++++++ .../commissioning_status_buttons.dart | 2 +- 3 files changed, 566 insertions(+), 20 deletions(-) create mode 100644 lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart 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 684eb99d..ac7c3b92 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 @@ -161,25 +161,25 @@ class _AllRequestsFilterPageState extends State { ], ), 16.height, - "Archived WO".heading5(context), - // 8.height, - Row( - children: [ - Checkbox( - value: search?.isArchived ?? false, - activeColor: AppColor.blueStatus(context), - onChanged: (value) { - if (search?.isArchived != value) { - search?.isArchived = value!; - } - if (mounted) setState(() {}); - }), - "View Archived Requests".bodyText(context).expanded, - ], - ).onPress(() { - search?.isArchived = !search!.isArchived; - setState(() {}); - }), + // "Archived WO".heading5(context), + // // 8.height, + // Row( + // children: [ + // Checkbox( + // value: search?.isArchived ?? false, + // activeColor: AppColor.blueStatus(context), + // onChanged: (value) { + // if (search?.isArchived != value) { + // search?.isArchived = value!; + // } + // if (mounted) setState(() {}); + // }), + // "View Archived Requests".bodyText(context).expanded, + // ], + // ).onPress(() { + // search?.isArchived = !search!.isArchived; + // setState(() {}); + // }), ], ).paddingOnly(start: 16, end: 16), ).expanded, diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart new file mode 100644 index 00000000..0b102c0f --- /dev/null +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart @@ -0,0 +1,546 @@ +// // import 'package:flutter/material.dart'; +// // import 'package:fluttertoast/fluttertoast.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/string_extensions.dart'; +// // import 'package:test_sa/extensions/text_extensions.dart'; +// // import 'package:test_sa/extensions/widget_extensions.dart'; +// // import 'package:test_sa/models/lookup.dart'; +// // import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; +// // import 'package:test_sa/models/ppm/ppm_calibration_tools.dart'; +// // import 'package:test_sa/models/service_request/supplier_details.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/single_item_drop_down_menu.dart'; +// // import 'package:test_sa/providers/loading_list_notifier.dart'; +// // import 'package:test_sa/providers/ppm_service_provider.dart'; +// // import 'package:test_sa/providers/work_order/vendor_provider.dart'; +// // import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +// // import 'package:test_sa/views/widgets/pentry/calibration_tool_asset_picker.dart'; +// // +// // import '../../../../../new_views/app_style/app_color.dart'; +// // import '../../../../widgets/date_and_time/date_picker.dart'; +// // +// // class AssistantEmployeeList extends StatefulWidget { +// // final List? models; +// // +// // const AssistantEmployeeList({Key? key, this.models = const []}) : super(key: key); +// // +// // @override +// // State createState() => _AssistantEmployeeListState(); +// // } +// // +// // class _AssistantEmployeeListState extends State { +// // final TextEditingController _workingHoursController = TextEditingController(); +// // +// // @override +// // Widget build(BuildContext context) { +// // return ListView.builder( +// // itemCount: widget.models!.length + 1, +// // padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), +// // itemBuilder: (context, index) { +// // if (index == widget.models!.length) { +// // return AppFilledButton( +// // label: "Add More External Details".addTranslation, +// // maxWidth: true, +// // textColor: AppColor.black10, +// // buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, +// // icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), +// // showIcon: true, +// // onPressed: () async { +// // // if (widget.models?.isNotEmpty ?? false) { +// // // if (widget.models!.last.assetId == null) { +// // // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); +// // // return; +// // // } +// // // if (widget.models!.last.calibrationDateOfTesters == null) { +// // // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); +// // // return; +// // // } +// // // } +// // // widget.models!.add(PpmCalibrationTools(id: 0)); +// // // setState(() {}); +// // }, +// // ); +// // } +// // final model = widget.models![index]; +// // // _workingHoursController.text = model.workingHours != null ? model.workingHours.toString() : ''; +// // return Container( +// // padding: const EdgeInsets.all(16), +// // margin: EdgeInsets.only(bottom: 16.toScreenHeight), +// // decoration: BoxDecoration( +// // color: AppColor.background(context), +// // borderRadius: BorderRadius.circular(20), +// // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], +// // ), +// // child: Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // Row( +// // mainAxisAlignment: MainAxisAlignment.spaceBetween, +// // children: [ +// // (index == 0 ? "1 /4 . External Details" : "").heading5(context), +// // "trash".toSvgAsset(height: 20, width: 15).onPress(() { +// // widget.models!.remove(model); +// // +// // setState(() {}); +// // }), +// // ], +// // ), +// // 16.height, +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.supplier, +// // initialValue: model.supplier, +// // backgroundColor: AppColor.neutral100, +// // showAsBottomSheet: true, +// // onSelect: (supplier) { +// // if (supplier != null) { +// // model.supplier = supplier; +// // print('supplier dtails is ${supplier.toJson()}'); +// // setState(() {}); +// // } +// // }, +// // ), +// // 8.height, +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.supplierEngineer, +// // enabled: model.suppPerson != null, +// // backgroundColor: AppColor.neutral100, +// // initialValue: model.suppPerson, +// // staticData: model.supplier?.suppPersons, +// // showAsBottomSheet: true, +// // onSelect: (suppPerson) { +// // if (suppPerson != null) { +// // model.suppPerson = suppPerson; +// // print('supply person is ${model.suppPerson?.toJson()}'); +// // } +// // }, +// // ), +// // 8.height, +// // AppTextFormField( +// // labelText: "Telephone", +// // initialValue: model.supplier?.telephones != null && model.supplier!.telephones!.isNotEmpty ? (model.supplier?.telephones?[0].telephone ?? "").toString() : '', +// // textAlign: TextAlign.center, +// // backgroundColor: AppColor.neutral100, +// // style: Theme.of(context).textTheme.titleMedium, +// // textInputType: TextInputType.number, +// // onChange: (value) { +// // model.supplier?.telephones?[0].telephone = value; +// // }, +// // ), +// // 8.height, +// // Row( +// // mainAxisSize: MainAxisSize.min, +// // children: [ +// // ADatePicker( +// // label: context.translation.startTime, +// // hideShadow: true, +// // backgroundColor: AppColor.neutral100, +// // date: model.startDateTime, +// // formatDateWithTime: true, +// // onDatePicker: (selectedDate) { +// // showTimePicker( +// // context: context, +// // initialTime: TimeOfDay.now(), +// // ).then((selectedTime) { +// // // Handle the selected date and time here. +// // if (selectedTime != null) { +// // DateTime selectedDateTime = DateTime( +// // selectedDate.year, +// // selectedDate.month, +// // selectedDate.day, +// // selectedTime.hour, +// // selectedTime.minute, +// // ); +// // setState(() { +// // model.startDateTime = selectedDateTime; +// // }); +// // model.endDateTime = null; +// // _workingHoursController.clear(); +// // ServiceRequestUtils.calculateAndAssignWorkingHours( +// // startTime: model.startDateTime, +// // endTime: model.endDateTime, +// // workingHoursController: _workingHoursController, +// // updateModel: (hours) { +// // model.workingHours = hours; +// // }, +// // ); +// // } +// // }); +// // }, +// // ).expanded, +// // 8.width, +// // ADatePicker( +// // label: context.translation.endTime, +// // hideShadow: true, +// // backgroundColor: AppColor.neutral100, +// // date: model.endDateTime, +// // formatDateWithTime: true, +// // onDatePicker: (selectedDate) { +// // showTimePicker( +// // context: context, +// // initialTime: TimeOfDay.now(), +// // ).then((selectedTime) { +// // // Handle the selected date and time here. +// // if (selectedTime != null) { +// // DateTime selectedDateTime = DateTime( +// // selectedDate.year, +// // selectedDate.month, +// // selectedDate.day, +// // selectedTime.hour, +// // selectedTime.minute, +// // ); +// // if (model.startDateTime != null && selectedDateTime.isBefore(model.startDateTime!)) { +// // "End Date time must be greater then start date".showToast; +// // return; +// // } +// // model.endDateTime = selectedDateTime; +// // setState(() {}); +// // ServiceRequestUtils.calculateAndAssignWorkingHours( +// // startTime: model.startDateTime, +// // endTime: model.endDateTime, +// // workingHoursController: _workingHoursController, +// // updateModel: (hours) { +// // model.workingHours = hours; +// // }, +// // ); +// // } +// // }); +// // }, +// // ).expanded, +// // ], +// // ), +// // 8.height, +// // AppTextFormField( +// // labelText: context.translation.workingHours, +// // backgroundColor: AppColor.neutral80, +// // controller: _workingHoursController, +// // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), +// // // initialValue: model.workingHours != null ? model.workingHours.toString() : '', +// // textAlign: TextAlign.center, +// // labelStyle: AppTextStyles.textFieldLabelStyle, +// // enable: false, +// // showShadow: false, +// // style: Theme.of(context).textTheme.titleMedium, +// // ), +// // 8.height, +// // ], +// // ), +// // ); +// // }, +// // ); +// // } +// // } +// +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/ppm_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/string_extensions.dart'; +// import 'package:test_sa/extensions/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/new_models/assistant_employee.dart'; +// import 'package:test_sa/models/new_models/work_order_detail_model.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/service_request_latest/service_request_detail_provider.dart'; +// import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +// import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +// import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; +// +// class AssistantEmployeeList extends StatefulWidget { +// final List? models; +// +// const AssistantEmployeeList({Key? key, this.models = const []}) : super(key: key); +// +// @override +// State createState() => _AssistantEmployeeListState(); +// } +// +// class _AssistantEmployeeListState extends State { +// bool isLoading = false; +// +// //TODO add loader when adding or deleting item.. +// +// void _addNewEntry() { +// setState(() { +// // isLoading = true; +// widget.models!.add(ActivityMaintenanceAssistantEmployees()); +// // Future.delayed(Duration(seconds: 1)).whenComplete(() { +// // setState(() { +// // isLoading = false; +// // }); +// // }); +// }); +// } +// +// void _removeEntry(int index) { +// setState(() { +// isLoading = true; +// widget.models!.removeAt(index); +// // isLoading = false; +// }); +// } +// +// @override +// Widget build(BuildContext context) { +// final ppmProvider = Provider.of(context, listen: false); +// return ListView.builder( +// itemCount: widget.models!.length + 1, +// padding: const EdgeInsets.all(16), +// itemBuilder: (context, index) { +// if (index == widget.models!.length) { +// return Visibility( +// visible: !ppmProvider.isReadOnly, +// child: AppFilledButton( +// label: "Add More Assistant Employees".addTranslation, +// maxWidth: true, +// textColor: AppColor.black10, +// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, +// icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), +// showIcon: true, +// onPressed: _addNewEntry, +// ), +// ); +// } +// // return !isLoading +// // ? +// return AssistantEmployeeItem( +// model: widget.models![index], +// // index: index, +// // onRemove: () => _removeEntry(index), +// ); +// // : const ALoading(); +// }, +// ); +// } +// } +// class AssistantEmployeeItem extends StatefulWidget { +// final ActivityMaintenanceAssistantEmployees model; +// const AssistantEmployeeItem({required this.model,super.key}); +// +// @override +// State createState() => _AssistantEmployeeItemState(); +// } +// +// class _AssistantEmployeeItemState extends State { +// bool status = false; +// final TextEditingController _workingHoursController = TextEditingController(text: ''); +// bool isCurrentUserIsAssistantEmp = false; +// bool isExpanded = false; +// +// @override +// void initState() { +// // TODO: implement initState +// WidgetsBinding.instance.addPostFrameCallback((_) { +// getInitialData(); +// }); +// super.initState(); +// } +// +// Future getInitialData() async { +// final user = Provider.of(context, listen: false).user!; +// ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); +// if( requestDetailProvider.isReadOnlyRequest){ +// isExpanded = true; +// setState(() { +// }); +// } +// isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); +// +// // if (isCurrentUserIsAssistantEmp) { +// // // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; +// // } +// } +// +// @override +// void dispose() { +// // TODO: implement dispose +// _workingHoursController.dispose(); +// super.dispose(); +// } +// +// @override +// Widget build(BuildContext context) { +// return Consumer(builder: (context, requestDetailProvider, child) { +// return Column( +// children: [ +// SizedBox( +// height: 56.toScreenHeight, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// context.translation.assistantEmployee.bodyText(context).custom(color: AppColor.black20), +// Icon(isExpanded ? Icons.arrow_drop_up_outlined : Icons.arrow_drop_down), +// ], +// ), +// ).onPress(() { +// setState(() { +// isExpanded = !isExpanded; +// }); +// }), +// isExpanded +// ? Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: [ +// ServiceReportAssistantEmployeeMenu( +// title: context.translation.select, +// backgroundColor: AppColor.neutral100, +// assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!, +// initialValue: widget.model., +// onSelect: (employee) { +// if (employee == null) { +// requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = []; +// } else { +// widget.model = [employee.copyWith(id: 0)]; +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); +// } +// }, +// ), +// 8.height, +// Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// ADatePicker( +// label: context.translation.startTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime; +// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// workingHoursController: _workingHoursController, +// updateModel: (hours){ +// requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; +// }); +// } +// }); +// }, +// ).expanded, +// 8.width, +// ADatePicker( +// label: context.translation.endTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null && +// selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) { +// "End Date time must be greater then start date".showToast; +// return; +// } +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime; +// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, +// workingHoursController: _workingHoursController, +// updateModel: (hours){ +// requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; +// }); +// } +// }); +// }, +// ).expanded, +// ], +// ), +// 8.height, +// AppTextFormField( +// labelText: context.translation.workingHours, +// backgroundColor: AppColor.neutral80, +// controller: _workingHoursController, +// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), +// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null +// ? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString() +// : '', +// textAlign: TextAlign.center, +// labelStyle: AppTextStyles.textFieldLabelStyle, +// enable: false, +// showShadow: false, +// style: Theme.of(context).textTheme.titleMedium, +// ), +// 8.height, +// AppTextFormField( +// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment, +// labelText: context.translation.technicalComment, +// backgroundColor: AppColor.neutral100, +// showShadow: false, +// labelStyle: AppTextStyles.textFieldLabelStyle, +// alignLabelWithHint: true, +// textInputType: TextInputType.multiline, +// onChange: (value) { +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; +// }, +// onSaved: (value) { +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; +// }, +// ), +// 8.height, +// ], +// ) +// : const SizedBox(), +// ], +// ); +// }); +// } +// +// // //TODO move this to some common place....@waseem +// // double calculateWorkingHours(DateTime? startTime, DateTime? endTime) { +// // if (startTime != null && endTime != null) { +// // Duration difference = endTime.difference(startTime); +// // int hours = difference.inHours; +// // int minutes = difference.inMinutes % 60; +// // return hours.toDouble(); +// // } else { +// // return -1; +// // } +// // } +// // +// // assignWorkingHours({required RequestDetailProvider requestDetailProvider}) { +// // double hours = calculateWorkingHours( +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate); +// // if (hours != -1) { +// // _workingHoursController.text = hours.toString(); +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours = hours; +// // } +// // } +// } +// diff --git a/lib/views/widgets/equipment/commissioning_status_buttons.dart b/lib/views/widgets/equipment/commissioning_status_buttons.dart index 67931dc8..ba6e59fe 100644 --- a/lib/views/widgets/equipment/commissioning_status_buttons.dart +++ b/lib/views/widgets/equipment/commissioning_status_buttons.dart @@ -54,7 +54,7 @@ class _CommissioningStatusButtonsState extends State return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - context.translation.equipmentStatus.heading5(context).paddingOnly(start: 16, end: 16), + context.translation.assetStatus.heading5(context).paddingOnly(start: 16, end: 16), 8.height, Consumer( builder: (context, snapshot, _) { From ac0cf47a8d45f715b137722cb52cdb70a752ce41 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 15 Apr 2025 15:05:04 +0300 Subject: [PATCH 27/36] point 49 fixed, --- .../land_page/requests/service_request_item_view.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/new_views/pages/land_page/requests/service_request_item_view.dart b/lib/new_views/pages/land_page/requests/service_request_item_view.dart index 4eb0fbef..e3fabae7 100644 --- a/lib/new_views/pages/land_page/requests/service_request_item_view.dart +++ b/lib/new_views/pages/land_page/requests/service_request_item_view.dart @@ -52,12 +52,12 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, (requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context), 8.height, - '${context.translation.assetName}: ${requestData?.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + 'CM Number: ${requestData!.requestNo}'.bodyText(context), '${context.translation.assetNumber}: ${requestData?.assetNumber}'.bodyText(context), - + '${context.translation.assetName}: ${requestData?.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), // '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), - 'CM Number: ${requestData!.requestNo}'.bodyText(context), + if (requestData?.statusName == 'Canceled') ...[ '${context.translation.rejectionReason}: ${requestData?.rejectReason}'.bodyText(context), ], @@ -114,10 +114,9 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, // '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), - '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), 'CM Number: ${requestDetails!.requestNo}'.bodyText(context), - + '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), + '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), 8.height, Row( // mainAxisSize: MainAxisSize.min, From be276f327d8815bc124520571625dc55c4f2c79c Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Wed, 16 Apr 2025 11:03:31 +0300 Subject: [PATCH 28/36] view activities for closed request issue fixed --- .../action_button/footer_action_button.dart | 23 +++++++++++++++++-- .../components/assistant_employee_card.dart | 1 - 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/service_request_latest/views/components/action_button/footer_action_button.dart b/lib/service_request_latest/views/components/action_button/footer_action_button.dart index b5a67159..4fbbf7bc 100644 --- a/lib/service_request_latest/views/components/action_button/footer_action_button.dart +++ b/lib/service_request_latest/views/components/action_button/footer_action_button.dart @@ -57,9 +57,28 @@ class FooterActionButton { case WorkOrderNextStepEnum.markedAsFixed: break; // TODO: Handle this case. + case WorkOrderNextStepEnum.endWorkFlow: + if (requestDetailProvider.isReadOnlyRequest) { + return footerContainer( + child: AppFilledButton( + label: context.translation.activities, + buttonColor: AppColor.neutral50, + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const ActivitiesListView())); + }, + ), + ); + } + return footerContainer( + child: AppFilledButton( + label: context.translation.close, + // maxWidth: true, + buttonColor: AppColor.primary10, + onPressed: () async { + Navigator.pop(context); + }, + )); case WorkOrderNextStepEnum.nTakeAction: - // const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: ''); - //Need to add enum for these values in future instead of static values.. if (requestDetailProvider.isReadOnlyRequest) { return footerContainer( child: AppFilledButton( diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart index 6e575c3c..6dd67f9e 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -39,7 +39,6 @@ class _AssistantEmployeeCardState extends State { Future getInitialData() async { final user = Provider.of(context, listen: false).user!; ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - print('readonly value is ${requestDetailProvider.isReadOnlyRequest}'); if( requestDetailProvider.isReadOnlyRequest){ isExpanded = true; setState(() { From b592e114bc97420d11abfa36d319d619e9cbe42c Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 17 Apr 2025 11:02:39 +0300 Subject: [PATCH 29/36] gas refill attachment issue fixed --- .../pages/new_gas_refill_request_page.dart | 2 + .../update_device_transfer.dart | 16 +- .../user/gas_refill/gas_refill_details.dart | 141 ++++++++++-------- .../user/gas_refill/request_gas_refill.dart | 1 - .../widgets/images/multi_image_picker.dart | 24 +-- 5 files changed, 106 insertions(+), 78 deletions(-) diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index d778d5ce..f9f9dadc 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -67,10 +67,12 @@ class _NewGasRefillRequestPageState extends State { @override void dispose() { super.dispose(); + _gasRefillProvider!.gasRefillAttachments.clear(); } @override Widget build(BuildContext context) { + return Scaffold( appBar: DefaultAppBar(title: context.translation.newGasRefillRequest), body: Column( diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 5ab3a914..7e4071dd 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -636,11 +636,17 @@ class _AssistantEmployeeCardState extends State { } else { employeeList = widget.formModel!.assetTransferAssistantEmployeesReceiver ?? []; } - widget.formModel?.modelAssistantEmployees = employeeList.isNotEmpty ? employeeList[0] : AssetTransferAssistantEmployees(); - AssignedEmployee? assignedUser = AssignedEmployee( - id: employeeList[0].employeeId, - name: employeeList[0].employeeName, - ); + + + widget.formModel?.modelAssistantEmployees = employeeList.isEmpty ? AssetTransferAssistantEmployees():employeeList[0]; + + AssignedEmployee? assignedUser = AssignedEmployee(); + if(employeeList.isNotEmpty){ + assignedUser= AssignedEmployee( + id: employeeList[0].employeeId, + name: employeeList[0].employeeName, + ); + } selectedEmployee = AssistantEmployees(userId: assignedUser.id, user: assignedUser); } diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index c35e71f6..908e4da5 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_comments.dart'; @@ -10,6 +12,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; @@ -39,6 +42,7 @@ class _GasRefillDetailsPageState extends State { final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); + List _attachments = []; @override void initState() { @@ -63,6 +67,8 @@ class _GasRefillDetailsPageState extends State { return const ALoading(); } else if (snap.hasData) { _model = snap.data as GasRefillModel; + _attachments = _model.gasRefillAttachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? []; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -139,7 +145,19 @@ class _GasRefillDetailsPageState extends State { const Divider().defaultStyle(context), gasRefillModel.comment!.bodyText(context), 8.height, - ] + ], + if (_attachments.isNotEmpty) ...[ + const Divider().defaultStyle(context), + context.translation.attachments.bodyText(context), + 8.height, + MultiFilesPicker( + label: context.translation.attachments, + files: _attachments, + enabled: false, + onlyImages: false, + ), + 12.height, + ], ], ).expanded, if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, @@ -149,69 +167,70 @@ class _GasRefillDetailsPageState extends State { style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), ), ], + ).paddingOnly(top: 16, start: 16, end: 16), /// TBD - (_userProvider.user!.type == UsersTypes.normal_user - ? Container( - height: 50, - padding: const EdgeInsets.only(left: 16, right: 16), - alignment: Alignment.center, - width: double.infinity, - decoration: ShapeDecoration( - color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(14), - bottomRight: Radius.circular(14), - ), - ), - ), - child: Row( - children: [ - Text( - '${context.translation.commentHere}...', - style: AppTextStyles.heading6.copyWith( - color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), - ), - ).expanded, - "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), - ], - ), - ) - : Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider().defaultStyle(context), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.viewComments, - style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), - ), - 4.width, - Icon( - Icons.arrow_forward, - color: AppColor.blueStatus(context), - size: 14, - ) - ], - ), - ], - ).paddingOnly(bottom: 16, start: 16, end: 16)) - .onPress(() { - showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - useRootNavigator: true, - backgroundColor: Colors.transparent, - builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()), - ); - }), + // (_userProvider.user!.type == UsersTypes.normal_user + // ? Container( + // height: 50, + // padding: const EdgeInsets.only(left: 16, right: 16), + // alignment: Alignment.center, + // width: double.infinity, + // decoration: ShapeDecoration( + // color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, + // shape: const RoundedRectangleBorder( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(14), + // bottomRight: Radius.circular(14), + // ), + // ), + // ), + // child: Row( + // children: [ + // Text( + // '${context.translation.commentHere}...', + // style: AppTextStyles.heading6.copyWith( + // color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), + // ), + // ).expanded, + // "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), + // ], + // ), + // ) + // : Column( + // mainAxisSize: MainAxisSize.min, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Divider().defaultStyle(context), + // 8.height, + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // context.translation.viewComments, + // style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + // ), + // 4.width, + // Icon( + // Icons.arrow_forward, + // color: AppColor.blueStatus(context), + // size: 14, + // ) + // ], + // ), + // ], + // ).paddingOnly(bottom: 16, start: 16, end: 16)) + // .onPress(() { + // showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // useRootNavigator: true, + // backgroundColor: Colors.transparent, + // builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()), + // ); + // }), ], ).toShadowContainer(context, padding: 0); } diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index a802ef50..9a4e23b4 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -176,7 +176,6 @@ class _RequestGasRefillState extends State { @override Widget build(BuildContext context) { - _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _gasRefillProvider ??= Provider.of(context, listen: false); diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index a6a2242d..3608aa5b 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -51,17 +51,19 @@ class _MultiFilesPickerState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - AppDashedButton( - title: widget.label, - height: widget.buttonHeight, - buttonColor: widget.buttonColor, - icon: widget.buttonIcon, - onPressed: (widget.enabled == false) - ? () {} - : widget.showAsGrid - ? showFileSourceSheet - : onFilePicker), - 16.height, + if(widget.enabled)...[ + AppDashedButton( + title: widget.label, + height: widget.buttonHeight, + buttonColor: widget.buttonColor, + icon: widget.buttonIcon, + onPressed: (widget.enabled == false) + ? () {} + : widget.showAsGrid + ? showFileSourceSheet + : onFilePicker), + 16.height, + ], if (widget.files.isNotEmpty) Wrap( spacing: 8.toScreenWidth, From c4c68fbe8b75a1237cc9b97a52bf12a5a1997731 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Apr 2025 11:02:51 +0300 Subject: [PATCH 30/36] asset fixes --- lib/models/device/asset_transfer.dart | 8 +++- .../create__asset_transfer_request.dart | 41 ++++++++++--------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index de7eab0b..d7e22270 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -526,7 +526,7 @@ class AssetTransfer { map['destRoomId'] = destRoomId; map['comment'] = comment; if (attachments != null) { - map['attachment'] = attachments!.map((v) => v.toJson()).toList(); + map['attachments'] = attachments!.map((v) => v.toJson()).toList(); } return map; } @@ -546,7 +546,11 @@ class AssetTransfer { map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList(); } if (modelAssistantEmployees != null) { - map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()]; + if(modelAssistantEmployees!.employeeId!=null) { + map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()]; + }else { + map['assetTransferAssistantEmployees'] =[]; + } } return map; } diff --git a/lib/views/pages/device_transfer/create__asset_transfer_request.dart b/lib/views/pages/device_transfer/create__asset_transfer_request.dart index d9587739..0ffd8dfe 100644 --- a/lib/views/pages/device_transfer/create__asset_transfer_request.dart +++ b/lib/views/pages/device_transfer/create__asset_transfer_request.dart @@ -129,27 +129,27 @@ class _CreateAssetTransferRequestState extends State backgroundColor: AppColor.white936, onPick: (asset) async { _pickedAsset = asset; - await checkAssetForPendingServiceRequest(asset.id!.toInt()); - if (_pickedAsset != null && pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { - showPendingRequestBottomSheet(); - } + // await checkAssetForPendingServiceRequest(asset.id!.toInt()); + // if (_pickedAsset != null && pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + // showPendingRequestBottomSheet(); + // } setState(() {}); }), - if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ - 8.height, - Row( - children: [ - const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), - 8.width, - Text( - "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), - ).expanded, - ], - ).onPress(() { - showPendingRequests(); - }), - ], + // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ + // 8.height, + // Row( + // children: [ + // const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), + // 8.width, + // Text( + // "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", + // style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), + // ).expanded, + // ], + // ).onPress(() { + // showPendingRequests(); + // }), + // ], 21.height, requestTypeWidget(context), 12.height, @@ -177,6 +177,7 @@ class _CreateAssetTransferRequestState extends State title: context.translation.building, initialValue: _assetDestination.building, showShadow: false, + showAsBottomSheet: true, backgroundColor: AppColor.neutral100, enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false, staticData: _assetDestination.site?.buildings ?? [], @@ -197,6 +198,7 @@ class _CreateAssetTransferRequestState extends State context: context, title: context.translation.floor, showShadow: false, + showAsBottomSheet: true, initialValue: _assetDestination.floor, backgroundColor: AppColor.neutral100, enabled: _assetDestination.building?.floors?.isNotEmpty ?? false, @@ -212,6 +214,7 @@ class _CreateAssetTransferRequestState extends State context: context, title: context.translation.department, showShadow: false, + showAsBottomSheet: true, initialValue: _assetDestination.department, backgroundColor: AppColor.neutral100, enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false, From 43820f01d3c0b7b4e0f62cfbfde100dc6ae29bc4 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 17 Apr 2025 11:23:08 +0300 Subject: [PATCH 31/36] asset transfer attachment issue fixed --- lib/models/device/asset_transfer.dart | 8 +++++ .../device_transfer_details.dart | 31 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index de7eab0b..9bfb08ac 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -178,6 +178,14 @@ class AssetTransfer { receiverAttachments!.add(AssetTransferAttachment.fromJson(v)); }); } + if(senderAttachments!=null){ + attachments = senderAttachments; + } + else if(receiverAttachments!=null){ + attachments = receiverAttachments; + } + print('sender attachment i got is ${senderAttachments?.length}'); + assetNumber = json['assetNumber']; assetName = json['assetName']; manufacturerName = json['manufacturerName']; diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index 87f41133..68b5056a 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; @@ -8,6 +10,7 @@ import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/update_device_transfer.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; @@ -31,6 +34,7 @@ class _DeviceTransferDetailsState extends State { AssetTransfer? _model; final bool _isLoading = false; final GlobalKey _formKey = GlobalKey(); + List _attachments = []; final GlobalKey _scaffoldKey = GlobalKey(); @override @@ -41,6 +45,7 @@ class _DeviceTransferDetailsState extends State { @override Widget build(BuildContext context) { _userProvider ??= Provider.of(context); + return Scaffold( appBar: DefaultAppBar(title: context.translation.deviceTransferDetails), key: _scaffoldKey, @@ -52,6 +57,7 @@ class _DeviceTransferDetailsState extends State { return const ALoading(); } else { _model = snapshot.data as AssetTransfer?; + _attachments = _model?.attachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? []; return Form( key: _formKey, @@ -89,6 +95,8 @@ class _DeviceTransferDetailsState extends State { const Divider().defaultStyle(context), 8.height, _buildTextWidget(_model!.comment!), + + ] ], ), @@ -177,6 +185,27 @@ class _DeviceTransferDetailsState extends State { return widget.toShadowContainer(context).paddingOnly(top: 14, start: 14, end: 14); } + Widget attachmentWidget(){ + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + if (_attachments.isNotEmpty) ...[ + const Divider().defaultStyle(context), + context.translation.attachments.bodyText(context), + 8.height, + MultiFilesPicker( + label: context.translation.attachments, + files: _attachments, + enabled: false, + onlyImages: false, + ), + 12.height, + ], + ], + ); + } + _buildTextWidget(String text) { return text.bodyText(context); } @@ -224,6 +253,8 @@ class _DeviceTransferDetailsState extends State { const Divider().defaultStyle(context), 8.height, _buildTextWidget(comment), + attachmentWidget(), + ] ], ).toShadowContainer(context); From 015b73b634b29c7927b31e4092a47d9a24d20e2b Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Apr 2025 15:07:21 +0300 Subject: [PATCH 32/36] ponit 87 fixed. --- .../providers/api/all_requests_provider.dart | 10 ++++++++++ lib/models/new_models/gas_refill_model.dart | 2 +- lib/models/ppm/recurrent_wo.dart | 2 +- .../pages/user/gas_refill/gas_refill_form.dart | 5 ++++- .../components/room_inspection_card.dart | 15 ++------------- .../recurrent_wo/components/task_info_widget.dart | 4 ++-- .../widgets/status/assistant_employee_menu.dart | 5 +++-- .../service_report_assistant_employee_menu.dart | 1 + 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index f4f96064..afaf7b54 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -201,6 +201,16 @@ class AllRequestsProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); + recurrentWoData?.planRecurrentMedicalTaskRooms?.forEach((element){ + element.planRecurrentMedicalTaskRoomTabs?.forEach((tabs){ + tabs.planRecurrentMedicalTaskRoomTabAttributes?.forEach((attribute){ + print(attribute.attribute?.name); + if(attribute.attribute?.type=="bool" && attribute.attributeValue ==null) { + attribute.attributeValue = "true"; + } + }); + }); + }); notifyListeners(); } isLoading = false; diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 0750dd33..bfd69bb2 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -72,7 +72,7 @@ class GasRefillModel { List? gasRefillDetails; // Now nullable Uint8List? localNurseSignature; // Now nullable Uint8List? localEngineerSignature; // Now nullable - TimerModel? timer; + TimerModel? timer = TimerModel(); //TODO need to check when api provided.. List? timerModelList = []; diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index c8161054..e5d27c10 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -294,7 +294,7 @@ class PlanRecurrentMedicalTaskRoomTabAttributes { PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(Map json) { id = json['id']; attribute = json['attribute'] != null ? Attribute.fromJson(json['attribute']) : null; - attributeValue = json['attributeValue'] ?? (json['attribute']['type'] == 'bool' ? (json['attributeValue']?.toString() == 'true') : json['attributeValue']); + attributeValue = json['attributeValue']; } Map toJson() { diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart index a03281e2..b7c89455 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_form.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -203,6 +203,9 @@ class _GasRefillFormState extends State { // setState(() {}); // }); } + double totalWorkingHours = + _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; + return Scaffold( appBar: DefaultAppBar(title: context.translation.gasRefill), key: _scaffoldKey, @@ -263,7 +266,7 @@ class _GasRefillFormState extends State { // : context.translation.onlyNumbers, // ), // 8.height, - _timerWidget(context, _formModel.workingHours ?? 0), + _timerWidget(context, totalWorkingHours), 8.height, // SingleItemDropDownMenu( // context: context, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index a4161ce5..511ae268 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -52,19 +52,8 @@ class _RoomInspectionCardState extends State { ).toShadowContainer(context).paddingOnly(top: 12); } - Widget inspectionStatusRadioWidget({ - required int index, - required PlanRecurrentMedicalTaskRoomTabAttributes model, - required BuildContext context, - }) { - - bool status = (model.attribute == null || model.attributeValue == null) - ? true - : model.attribute != null - ? model.attributeValue == 'true' - ? true - : false - : false; + Widget inspectionStatusRadioWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) { + bool status = (model.attribute == null || model.attributeValue == null) ? true : (model.attribute != null ? (model.attributeValue == 'true' ? true : false) : false); return Row( diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 26f5ba20..a7d81af4 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -64,8 +64,8 @@ class RecurrentTaskInfoWidget extends StatelessWidget { // ], ).toShadowContainer(context, padding: 12) : Column( - children: [_timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), 8.height, _commentWidget(context: context, model: model)], - ), + children: [_timerWidget(context, model!.totalWorkingHours!), 8.height, _commentWidget(context: context, model: model)], + ).toShadowContainer(context, padding: 12), ], ); } diff --git a/lib/views/widgets/status/assistant_employee_menu.dart b/lib/views/widgets/status/assistant_employee_menu.dart index 259d38cc..01d66f8a 100644 --- a/lib/views/widgets/status/assistant_employee_menu.dart +++ b/lib/views/widgets/status/assistant_employee_menu.dart @@ -18,8 +18,9 @@ class AssistantEmployeeMenu extends StatefulWidget { final String? title; // Now nullable final bool enable; final bool showAsBottomSheet; + final bool hideShadow; - AssistantEmployeeMenu({Key? key, required this.statuses, this.title, this.showAsBottomSheet = false, required this.onSelect, this.initialStatus, this.backgroundColor, this.enable = true}) + AssistantEmployeeMenu({Key? key, required this.statuses, this.title, this.showAsBottomSheet = false,this.hideShadow = false, required this.onSelect, this.initialStatus, this.backgroundColor, this.enable = true}) : super(key: key); @override @@ -74,7 +75,7 @@ class _SingleAssistantEmployeeMenuState extends State { decoration: BoxDecoration( color: widget.backgroundColor ?? (context.isDark ? AppColor.neutral50 : AppColor.neutral120), borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + boxShadow: widget.hideShadow ? null : [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), child: Stack( alignment: Alignment.center, diff --git a/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart b/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart index 533faace..636ffe3a 100644 --- a/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart +++ b/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart @@ -31,6 +31,7 @@ class ServiceReportAssistantEmployeeMenu extends StatelessWidget { initialStatus: initialValue, title: title, showAsBottomSheet: true, + hideShadow: true, statuses: menuProvider.assistantEmployees ?? [], backgroundColor: backgroundColor, // Provide an empty list if null From e66ae78c83df3df7b3340be0077b931c0dfafd15 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Apr 2025 15:08:23 +0300 Subject: [PATCH 33/36] files format --- lib/controllers/api_routes/urls.dart | 138 ++++++++++++------ .../providers/api/all_requests_provider.dart | 12 +- lib/models/ppm/recurrent_wo.dart | 3 +- .../user/gas_refill/gas_refill_form.dart | 36 ++--- .../user/gas_refill/request_gas_refill.dart | 16 +- .../components/room_inspection_card.dart | 1 - .../components/room_tabs_widget.dart | 3 +- .../components/task_info_widget.dart | 7 +- .../recurrent_work_order_view.dart | 8 +- 9 files changed, 124 insertions(+), 100 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index edc1bcfe..f2055282 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -2,6 +2,7 @@ class URLs { URLs._(); static const String appReleaseBuildNumber = "14"; + // 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 @@ -42,54 +43,94 @@ class URLs { static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2 static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get //service request new flow urls. - static get nurseDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; - static get nurseDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseDetails'; - static get nurseRejectUrl=> '$_baseUrl/ServiceRequest/NurseReject'; - static get engineerStopTimer=> '$_baseUrl/ServiceRequest/EngineerStopTimer'; - static get nurseConfirmEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseConfirm'; - static get nurseConfirmUrl=> '$_baseUrl/ServiceRequest/NurseConfirm'; - static get nurseRejectEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseNotArrive'; - static get nurseConfirmEngineerArrivalUrl=> '$_baseUrl/ServiceRequest/NurseAccept'; - static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; - static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; - static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; - static get engineerDashboardUpcoming=> '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming'; - static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept'; - static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; - static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject'; - static get engineerFixRemotlyUrl=> '$_baseUrl/ServiceRequest/EngineerFixRemotly'; - static get engineerNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerNeedVisit'; - static get engineerUpdateNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit'; - static get engineerMarkAsFixUrl=> '$_baseUrl/ServiceRequest/EngineerMarkAsFix'; - static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity'; - static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; - static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; - static get engineerSetReminderUrl=> '$_baseUrl/ServiceRequest/EngineerSetReminder'; - static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById'; - static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode'; - static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; - static get deleteActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; - static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart'; - static get createActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; - static get createActivityAssetToBeRetiredUrl=> '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired'; - static get createWorkOrderUrl=> '$_baseUrl/ServiceRequest/CreateWorkOrder'; - static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; - static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; - static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; - static get uploadWorkOrderAttachmentsUrl=> '$_baseUrl/ServiceRequest/UploadAttachmentsWorkOrder'; - - static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; - static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; - static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; + static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; + + static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails'; + + static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject'; + + static get engineerStopTimer => '$_baseUrl/ServiceRequest/EngineerStopTimer'; + + static get nurseConfirmEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseConfirm'; + + static get nurseConfirmUrl => '$_baseUrl/ServiceRequest/NurseConfirm'; + + static get nurseRejectEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseNotArrive'; + + static get nurseConfirmEngineerArrivalUrl => '$_baseUrl/ServiceRequest/NurseAccept'; + + static get engineerDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; + + static get engineerDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; + + static get engineerDashboardNotAssignDetails => '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; + + static get engineerDashboardUpcoming => '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming'; + + static get engineerAcceptUrl => '$_baseUrl/ServiceRequest/EngineerAccept'; + + static get engineerAssignHimSelfUrl => '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; + + static get engineerRejectUrl => '$_baseUrl/ServiceRequest/EngineerReject'; + + static get engineerFixRemotlyUrl => '$_baseUrl/ServiceRequest/EngineerFixRemotly'; + + static get engineerNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerNeedVisit'; + + static get engineerUpdateNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit'; + + static get engineerMarkAsFixUrl => '$_baseUrl/ServiceRequest/EngineerMarkAsFix'; + + static get reOrderActivity => '$_baseUrl/ServiceRequest/ReOrderActivity'; + + static get engineerConfirmArriveUrl => '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; + + static get engineerUpdateWorkOrderUrl => '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; + + static get engineerSetReminderUrl => '$_baseUrl/ServiceRequest/EngineerSetReminder'; + + static get getWorkOrderByIdUrl => '$_baseUrl/ServiceRequest/GetWorkOrderById'; + + static get getQrCodeUrl => '$_baseUrl/ServiceRequest/GetQRCode'; + + static get deleteActivitySparePartUrl => '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; + + static get deleteActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; + + static get createActivitySparePartUrl => '$_baseUrl/ServiceRequest/CreateActivitySparePart'; + + static get createActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; + + static get createActivityAssetToBeRetiredUrl => '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired'; + + static get createWorkOrderUrl => '$_baseUrl/ServiceRequest/CreateWorkOrder'; + + static get updateActivitySparePartUrl => '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; + + static get updateActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; + + static get assignEngineerToWorkOrderUrl => '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; + + static get uploadWorkOrderAttachmentsUrl => '$_baseUrl/ServiceRequest/UploadAttachmentsWorkOrder'; + + static get getArrivalVerificationTypeUrl => '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; + + static get sendOtpUrl => '$_baseUrl/SmsNotification/SendOTP/'; + + static get verifyOtpUrl => '$_baseUrl/SmsNotification/VerifyOTP/'; + // 08051 //Swipe module Api.. - static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; - static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction'; - static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; + static get swipeUrl => '$_baseUrl/Swipe/Swipe'; + + static get getSwipeLastTransactionUrl => '$_baseUrl/Swipe/GetLastTransaction'; + + static get getSwipeTransactionHistoryUrl => '$_baseUrl/Swipe/GetTransactions'; + //Recurrent plan Api... - static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; - static get updateRecurrentPlanUrl=> '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer'; + static get getRecurrentPlanByIdUrl => '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; + static get updateRecurrentPlanUrl => '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer'; //service request..... static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get @@ -147,11 +188,17 @@ class URLs { static get getPpmService => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get for ppm po reason, in mobile there is no use of it. static get getServiceReportReasons => "$_baseUrl/Lookups/GetLookupReason?lookupEnum=505"; + static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; + static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; + static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415"; + static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211"; + static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302"; + static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get static get getServiceReportStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=521"; // get @@ -164,6 +211,7 @@ class URLs { static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName="; + //gas refill static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get // todo check edits with backend @@ -188,7 +236,7 @@ class URLs { //Asset transfer new Apis static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferNewById"; // get - static get createAssetTransferRequest => "$_baseUrl/AssetTransfer/AddAssetTransferMobileNew";// post + static get createAssetTransferRequest => "$_baseUrl/AssetTransfer/AddAssetTransferMobileNew"; // post static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateEngineerAssetTransferNew"; // get // employee diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index afaf7b54..f22d8329 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -4,7 +4,6 @@ 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'; @@ -62,7 +61,7 @@ class AllRequestsProvider extends ChangeNotifier { // AllRequestsAndCount? get completedRequests => _completedRequests; AllRequestsAndCount? get requestDetailList => _requestDetailList; - RecurrentWoData? _recurrentWoData=RecurrentWoData(); + RecurrentWoData? _recurrentWoData = RecurrentWoData(); RecurrentWoData? get recurrentWoData => _recurrentWoData; @@ -201,11 +200,10 @@ class AllRequestsProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); - recurrentWoData?.planRecurrentMedicalTaskRooms?.forEach((element){ - element.planRecurrentMedicalTaskRoomTabs?.forEach((tabs){ - tabs.planRecurrentMedicalTaskRoomTabAttributes?.forEach((attribute){ - print(attribute.attribute?.name); - if(attribute.attribute?.type=="bool" && attribute.attributeValue ==null) { + recurrentWoData?.planRecurrentMedicalTaskRooms?.forEach((element) { + element.planRecurrentMedicalTaskRoomTabs?.forEach((tabs) { + tabs.planRecurrentMedicalTaskRoomTabAttributes?.forEach((attribute) { + if (attribute.attribute?.type == "bool" && attribute.attributeValue == null) { attribute.attributeValue = "true"; } }); diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index e5d27c10..8eda557d 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -55,7 +55,6 @@ class RecurrentWoData { List? timerModelList = []; String? comment; - RecurrentWoData( {this.id, this.title, @@ -72,7 +71,7 @@ class RecurrentWoData { this.planRecurrentMedicalTaskRooms, this.planRecurrentTaskTimers, this.timerModelList, - this.comment, + this.comment, this.totalWorkingHours}); RecurrentWoData.fromJson(Map json) { diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart index b7c89455..3a800653 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_form.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -1,20 +1,16 @@ import 'dart:convert'; -import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_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/controllers/validator/validator.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/widget_extensions.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -27,14 +23,11 @@ import 'package:test_sa/service_request_latest/views/components/action_button/fo import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; -import '../../../../controllers/providers/api/hospitals_provider.dart'; import '../../../../extensions/text_extensions.dart'; import '../../../../models/new_models/gas_refill_model.dart'; import '../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../new_views/common_widgets/default_app_bar.dart'; import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../../../providers/gas_request_providers/gas_status_provider.dart'; -import '../../../widgets/e_signature/e_signature.dart'; import '../../../widgets/timer/app_timer.dart'; class GasRefillForm extends StatefulWidget { @@ -106,8 +99,7 @@ class _GasRefillFormState extends State { if (mounted) super.setState(() {}); } - _onSubmit(BuildContext context,int status) async { - + _onSubmit(BuildContext context, int status) async { if (_formModel.timer?.startAt == null) { await Fluttertoast.showToast(msg: "Working Hours Required"); return false; @@ -116,11 +108,11 @@ class _GasRefillFormState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - if(_currentDetails.deliverdQty==null){ + if (_currentDetails.deliverdQty == null) { await Fluttertoast.showToast(msg: "Delivered Quantity is Required"); return false; } - _formModel.gasRefillDetails=[]; + _formModel.gasRefillDetails = []; _formModel.gasRefillDetails?.add(_currentDetails); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); @@ -139,17 +131,12 @@ class _GasRefillFormState extends State { }); _formModel.gasRefillAttachments = []; for (var item in _gasRefillProvider!.gasRefillAttachments) { - _formModel.gasRefillAttachments - ?.add(GasRefillAttachments(id: 0,gasRefillId: _formModel.id??0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + _formModel.gasRefillAttachments?.add(GasRefillAttachments( + id: 0, gasRefillId: _formModel.id ?? 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); } - await _gasRefillProvider - ?.updateGasRefill( - status: status, - model: _formModel - ) - .whenComplete(() { + await _gasRefillProvider?.updateGasRefill(status: status, model: _formModel).whenComplete(() { if (status == 1) { - AllRequestsProvider allRequestsProvider = Provider.of(context,listen: false); + AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); // when click complete then this request remove from the list and status changes to closed.. _gasRefillProvider?.reset(); allRequestsProvider.getAllRequests(context, typeTransaction: 2); @@ -157,10 +144,8 @@ class _GasRefillFormState extends State { Navigator.pop(context); Navigator.pop(context); }); - } - @override void dispose() { _deliveredQuantityController.dispose(); @@ -203,8 +188,7 @@ class _GasRefillFormState extends State { // setState(() {}); // }); } - double totalWorkingHours = - _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; + double totalWorkingHours = _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; return Scaffold( appBar: DefaultAppBar(title: context.translation.gasRefill), @@ -287,7 +271,6 @@ class _GasRefillFormState extends State { // 8.height, - /// TBD AppTextFormField( labelText: context.translation.technicalComment, @@ -296,7 +279,7 @@ class _GasRefillFormState extends State { backgroundColor: AppColor.neutral100, showShadow: false, controller: _commentController, - onChange: (value){ + onChange: (value) { _formModel.techComment = value; }, onSaved: (value) {}, @@ -355,7 +338,6 @@ class _GasRefillFormState extends State { ], ), ), - ], )), ), diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index 9a4e23b4..d05ea482 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -8,7 +8,6 @@ import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_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/controllers/validator/validator.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'; @@ -59,7 +58,6 @@ class _RequestGasRefillState extends State { final GlobalKey _scaffoldKey = GlobalKey(); bool _firstTime = true; - Lookup? _deliveredQuantity; static List deliveredQuantity = [ @@ -135,7 +133,7 @@ class _RequestGasRefillState extends State { } } - bool _addNewModel(BuildContext context) { + bool _addNewModel(BuildContext context) { _validate = true; if (_currentDetails.deliverdQty == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}"); @@ -151,7 +149,7 @@ class _RequestGasRefillState extends State { _currentDetails.cylinderSize = _formModel.gasRefillDetails![0].cylinderSize; _currentDetails.cylinderType = _formModel.gasRefillDetails![0].cylinderType; _currentDetails.requestedQty = _formModel.gasRefillDetails![0].requestedQty; - if (!( _currentDetails.validate(context))) { + if (!(_currentDetails.validate(context))) { setState(() {}); return false; } @@ -191,11 +189,11 @@ class _RequestGasRefillState extends State { clientName = _userProvider.user?.clientName; } - HospitalsProvider().getHospitalsListByVal(searchVal: clientName??'').then((value) { - _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null); - _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null); - _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null); - _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null); + HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { + _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null); + _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null); + _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null); + _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null); _firstTime = false; setState(() {}); }); diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 511ae268..295eff91 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -55,7 +55,6 @@ class _RoomInspectionCardState extends State { Widget inspectionStatusRadioWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) { bool status = (model.attribute == null || model.attributeValue == null) ? true : (model.attribute != null ? (model.attributeValue == 'true' ? true : false) : false); - return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart index 9d7f01b0..cbf5c9c7 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart @@ -76,7 +76,8 @@ class _RoomTabsWidgetState extends State { ? const ALoading().paddingOnly(top: 150) : ListView( shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map((card) { return RoomInspectionCard(inspectionModel: card); }).toList(), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index a7d81af4..7034f7ca 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -6,10 +6,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/models/all_requests_and_count_model.dart'; -import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; -import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; @@ -79,7 +76,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { label: context.translation.timer, timer: snapshot.recurrentWoData?.recurrentWoTimerModel, width: double.infinity, - enabled: snapshot.recurrentWoData?.status?.value != 1, + enabled: snapshot.recurrentWoData?.status?.value != 1, decoration: BoxDecoration( color: AppColor.neutral100, borderRadius: BorderRadius.circular(10), @@ -129,7 +126,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { } } -Widget buildingInfoWidget({required String label, required String ?value, required BuildContext context}) { +Widget buildingInfoWidget({required String label, required String? value, required BuildContext context}) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index c2702430..c7ca4c5a 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -100,9 +100,11 @@ class _RecurrentWorkOrderViewState extends State { ], ) : NoDataFound(message: context.translation.noDataFound).center, - ).handlePopScope(cxt: context,onSave: () { - _updateTask(context: context, status: 0); - }); + ).handlePopScope( + cxt: context, + onSave: () { + _updateTask(context: context, status: 0); + }); }); } } From b34014e24fc33f8f78e0ea6c7596aacc11511ef0 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Apr 2025 15:19:57 +0300 Subject: [PATCH 34/36] sender and receiver comment fixed --- lib/models/device/asset_transfer.dart | 13 ++++++------- .../device_transfer/update_device_transfer.dart | 10 +++++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index 58fad7e7..db4c9900 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -178,10 +178,9 @@ class AssetTransfer { receiverAttachments!.add(AssetTransferAttachment.fromJson(v)); }); } - if(senderAttachments!=null){ + if (senderAttachments != null) { attachments = senderAttachments; - } - else if(receiverAttachments!=null){ + } else if (receiverAttachments != null) { attachments = receiverAttachments; } print('sender attachment i got is ${senderAttachments?.length}'); @@ -544,7 +543,7 @@ class AssetTransfer { map['id'] = id; map['statusValue'] = statusValue; map['isSender'] = isSender; - map['techComment'] = comment; + map['techComment'] = isSender! ? senderComment : receiverComment; map['assetTransferAssistantEmployees'] = modelAssistantEmployees; map['assetTransferEngineerTimers'] = assetTransferEngineerTimers; if (attachments != null) { @@ -554,10 +553,10 @@ class AssetTransfer { map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList(); } if (modelAssistantEmployees != null) { - if(modelAssistantEmployees!.employeeId!=null) { + if (modelAssistantEmployees!.employeeId != null) { map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()]; - }else { - map['assetTransferAssistantEmployees'] =[]; + } else { + map['assetTransferAssistantEmployees'] = []; } } return map; diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 7e4071dd..fb629265 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -1,4 +1,3 @@ - //older code. // import 'dart:convert'; // import 'dart:io'; @@ -334,6 +333,7 @@ import 'dart:convert'; import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; @@ -355,6 +355,7 @@ import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; + import '../../../extensions/text_extensions.dart'; import '../../../models/ppm/ppm.dart'; import '../../../new_views/app_style/app_color.dart'; @@ -637,12 +638,11 @@ class _AssistantEmployeeCardState extends State { employeeList = widget.formModel!.assetTransferAssistantEmployeesReceiver ?? []; } - - widget.formModel?.modelAssistantEmployees = employeeList.isEmpty ? AssetTransferAssistantEmployees():employeeList[0]; + widget.formModel?.modelAssistantEmployees = employeeList.isEmpty ? AssetTransferAssistantEmployees() : employeeList[0]; AssignedEmployee? assignedUser = AssignedEmployee(); - if(employeeList.isNotEmpty){ - assignedUser= AssignedEmployee( + if (employeeList.isNotEmpty) { + assignedUser = AssignedEmployee( id: employeeList[0].employeeId, name: employeeList[0].employeeName, ); From 71ee34c658a28512d3305e0e03a6b62686c8119e Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 17 Apr 2025 15:28:34 +0300 Subject: [PATCH 35/36] gas refill attachment and device transfer assistant employee issue fixes --- .../providers/api/gas_refill_provider.dart | 9 --------- lib/models/new_models/gas_refill_model.dart | 3 +++ .../pages/new_gas_refill_request_page.dart | 8 ++++---- .../device_transfer/update_device_transfer.dart | 1 + .../pages/user/gas_refill/gas_refill_form.dart | 15 +++++++-------- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index d71e45dc..84c967b7 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -28,7 +28,6 @@ class GasRefillProvider extends ChangeNotifier { building = null; floor = null; department = null; - gasRefillAttachments.clear(); } // state code of current request to defied error message @@ -46,14 +45,6 @@ class GasRefillProvider extends ChangeNotifier { // done _loading = true // failed _loading = false bool isLoading = false; - List _gasRefillAttachments = []; - - List get gasRefillAttachments => _gasRefillAttachments; - - set gasRefillAttachments(List value) { - _gasRefillAttachments = value; - notifyListeners(); - } diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 0750dd33..1c53f2f6 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -267,7 +267,10 @@ class GasRefillModel { employeeId = model.employeeId; name = model.name; techComment = model.techComment; + gasRefillAttachments = model.gasRefillAttachments; createdDate = model.createdDate; + workingHours = model.workingHours; + gasRefillTimers=model.gasRefillTimers; } GasRefillModel copyWith({ diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index f9f9dadc..e1fb13cf 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -45,6 +46,7 @@ class _NewGasRefillRequestPageState extends State { Lookup? _requestedQuantity; final TextEditingController _commentController = TextEditingController(); GasRefillProvider? _gasRefillProvider; + List _files = []; static List gasQuantity = [ Lookup(name: "1", id: 1, value: 1), @@ -61,13 +63,11 @@ class _NewGasRefillRequestPageState extends State { _gasModel =GasRefillModel(); _currentDetails = GasRefillDetails(); _gasModel = GasRefillModel(gasRefillDetails: []); - _gasRefillProvider!.gasRefillAttachments.clear(); } @override void dispose() { super.dispose(); - _gasRefillProvider!.gasRefillAttachments.clear(); } @override @@ -220,7 +220,7 @@ class _NewGasRefillRequestPageState extends State { 8.height, MultiFilesPicker( label: context.translation.attachFiles, - files: _gasRefillProvider!.gasRefillAttachments, + files:_files, buttonColor: AppColor.black10, onlyImages: false, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), @@ -243,7 +243,7 @@ class _NewGasRefillRequestPageState extends State { _gasModel.gasRefillDetails=[]; _gasModel.gasRefillDetails?.add(_currentDetails); _gasModel.gasRefillAttachments = []; - for (var item in _gasRefillProvider!.gasRefillAttachments) { + for (var item in _files) { _gasModel.gasRefillAttachments?.add(GasRefillAttachments( id: 0, gasRefillId: _gasModel.id ?? 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); } diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 7e4071dd..7585da18 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -687,6 +687,7 @@ class _AssistantEmployeeCardState extends State { if (employee == null) { widget.formModel?.assistantEmployees = []; } else { + selectedEmployee = employee; widget.formModel?.assistantEmployees = [employee.copyWith(id: 0)]; widget.formModel?.modelAssistantEmployees?.employeeId = employee.user?.id; } diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart index a03281e2..ebe2ceb1 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_form.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -69,6 +69,7 @@ class _GasRefillFormState extends State { bool _firstTime = true; Lookup? _deliveredQuantity; + List _attachments = []; static List deliveredQuantity = [ Lookup(name: "1", id: 1, value: 1), @@ -86,9 +87,8 @@ class _GasRefillFormState extends State { if (widget.gasRefillModel != null) { _formModel.fromGasRefillModel(widget.gasRefillModel!); - // totalWorkingHours = - // _formModel?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; - + totalWorkingHours = + _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; _commentController.text = _formModel.techComment ?? ""; try { _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); @@ -96,8 +96,7 @@ class _GasRefillFormState extends State { } catch (ex) {} } if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) { - _gasRefillProvider?.gasRefillAttachments = []; - _gasRefillProvider?.gasRefillAttachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList()); + _attachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList()); } } @@ -138,7 +137,7 @@ class _GasRefillFormState extends State { ); }); _formModel.gasRefillAttachments = []; - for (var item in _gasRefillProvider!.gasRefillAttachments) { + for (var item in _attachments) { _formModel.gasRefillAttachments ?.add(GasRefillAttachments(id: 0,gasRefillId: _formModel.id??0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); } @@ -263,7 +262,7 @@ class _GasRefillFormState extends State { // : context.translation.onlyNumbers, // ), // 8.height, - _timerWidget(context, _formModel.workingHours ?? 0), + _timerWidget(context, totalWorkingHours ?? 0), 8.height, // SingleItemDropDownMenu( // context: context, @@ -301,7 +300,7 @@ class _GasRefillFormState extends State { 16.height, MultiFilesPicker( label: context.translation.attachFiles, - files: _gasRefillProvider!.gasRefillAttachments, + files: _attachments, buttonColor: AppColor.black10, onlyImages: false, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), From 353ff337f7988b3388a54cd52b0964c1614e0dc9 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 17 Apr 2025 15:36:40 +0300 Subject: [PATCH 36/36] file format --- lib/models/new_models/assistant_employee.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/models/new_models/assistant_employee.dart b/lib/models/new_models/assistant_employee.dart index 29947d70..181c9482 100644 --- a/lib/models/new_models/assistant_employee.dart +++ b/lib/models/new_models/assistant_employee.dart @@ -1,5 +1,6 @@ import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/new_models/assigned_employee.dart'; + // int? id; // String? userId; // DateTime? startDate; @@ -7,9 +8,9 @@ import 'package:test_sa/models/new_models/assigned_employee.dart'; // int? workingHours; // String? technicalComment; - class AssistantEmployees extends Base { String? userId; + AssistantEmployees({ this.id, this.user,