From 3f90630db98879cda9e92b94d9d953318d66a8fc Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 27 Feb 2025 09:23:32 +0300 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6b51805827f323aad6edc067660170bb608ba5e6 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 19 Mar 2025 10:54:43 +0300 Subject: [PATCH 6/6] 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!) ],