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(); }