From 7df18179a18ae920933b6433337467880ce602b7 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 20 Feb 2025 09:11:57 +0300 Subject: [PATCH] ppm task supplier ui completed and save and update api implemented --- .../providers/api/ppm_provider.dart | 111 ++- lib/l10n/app_ar.arb | 7 +- lib/l10n/app_en.arb | 7 +- .../plan_preventive_visit_model.dart | 151 ++-- .../utilities/service_request_utils.dart | 4 + .../pages/user/ppm/ppm_details_page.dart | 36 +- .../update_ppm/ppm_external_details_form.dart | 520 ++++++++++++-- .../pages/user/ppm/update_ppm/update_ppm.dart | 57 +- .../user/ppm/update_ppm/wo_info_form.dart | 650 ++++++++---------- 9 files changed, 973 insertions(+), 570 deletions(-) diff --git a/lib/controllers/providers/api/ppm_provider.dart b/lib/controllers/providers/api/ppm_provider.dart index a1d1a172..229d2e35 100644 --- a/lib/controllers/providers/api/ppm_provider.dart +++ b/lib/controllers/providers/api/ppm_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'; @@ -18,7 +19,33 @@ class PpmProvider extends ChangeNotifier { // number of items call in each request final pageItemNumber = 12; - //reset provider data + PlanPreventiveVisit? _planPreventiveVisit; + late int _totalTabs = 4; + TabController? tabController; + + int get totalTabs => _totalTabs; + + set totalTabs(int value) { + _totalTabs = value; + notifyListeners(); + } + + List _ppmPlanAttachments = []; + + List get ppmPlanAttachments => _ppmPlanAttachments; + + set ppmPlanAttachments(List value) { + _ppmPlanAttachments = value; + notifyListeners(); + } + + PlanPreventiveVisit? get planPreventiveVisit => _planPreventiveVisit; + + set planPreventiveVisit(PlanPreventiveVisit? value) { + _planPreventiveVisit = value; + notifyListeners(); + } //reset provider data + void reset() { ppms = null; nextPage = true; @@ -122,22 +149,32 @@ class PpmProvider extends ChangeNotifier { // } Future getPlanPreventiveVisitById(int id) async { - // try { - Response response = await ApiManager.instance.get(URLs.getPlanPreventiveVisitById + "?planPreventiveVisitId=$id"); - if (response.statusCode >= 200 && response.statusCode < 300) { - return PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]); - } - return null; + // try { + isLoading = true; + Response response = await ApiManager.instance.get(URLs.getPlanPreventiveVisitById + "?planPreventiveVisitId=$id"); + if (response.statusCode >= 200 && response.statusCode < 300) { + planPreventiveVisit = PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]); + print('data i got is ${planPreventiveVisit?.toJson(status: 0)}'); + isLoading = false; + notifyListeners(); + return planPreventiveVisit; + } + isLoading = false; + notifyListeners(); + return null; // } catch (error) { + // isLoading= false; + // notifyListeners(); // return null; // } } - Future updateRecurrentWo({required int status,required PlanPreventiveVisit planPreventiveVisit}) async { + Future updateVisitByEngineer({required int status}) async { isLoading = true; Response response; try { - response = await ApiManager.instance.post(URLs.updateRecurrentPlanUrl, body: planPreventiveVisit.toJson(status: status)); + response = await ApiManager.instance.post(URLs.updateVisitByEngineer, body: planPreventiveVisit!.toJson(status: status)); + print('response i got is ${response.body}'); stateCode = response.statusCode; isLoading = false; notifyListeners(); @@ -150,34 +187,34 @@ class PpmProvider extends ChangeNotifier { } } - Future updateVisitByEngineer(BuildContext context, {required User user, required Ppm ppm}) async { - try { - ppm.visitTimers?.add( - VisitTimers( - id: 0, - startDateTime: ppm.tbsTimer?.startAt!.toIso8601String(), // Handle potential null - endDateTime: ppm.tbsTimer?.endAt?.toIso8601String(), // Handle potential null - workingHours: ((ppm.tbsTimer?.durationInSecond ?? 0) / 60 / 60), - ), - ); - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - late Response response; // Using 'late' for initialization later - Map body = ppm.copyWith(assignedEmployeeId: user.userName, tbsTimer: ppm.tbsTimer).toJson(); - response = await ApiManager.instance.put(URLs.updateVisitByEngineer, body: body); - if (response.statusCode >= 200 && response.statusCode < 300) { - reset(); //visit.status = pentry.ppmVisitStatus; - notifyListeners(); - Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); - Navigator.of(context).pop(); - } else { - Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}"); - } - Navigator.of(context).pop(); - return response.statusCode; - } catch (error) { - return -1; - } - } + // Future updateVisitByEngineer(BuildContext context, {required User user, required Ppm ppm}) async { + // try { + // ppm.visitTimers?.add( + // VisitTimers( + // id: 0, + // startDateTime: ppm.tbsTimer?.startAt!.toIso8601String(), // Handle potential null + // endDateTime: ppm.tbsTimer?.endAt?.toIso8601String(), // Handle potential null + // workingHours: ((ppm.tbsTimer?.durationInSecond ?? 0) / 60 / 60), + // ), + // ); + // showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + // late Response response; // Using 'late' for initialization later + // Map body = ppm.copyWith(assignedEmployeeId: user.userName, tbsTimer: ppm.tbsTimer).toJson(); + // response = await ApiManager.instance.put(URLs.updateVisitByEngineer, body: body); + // if (response.statusCode >= 200 && response.statusCode < 300) { + // reset(); //visit.status = pentry.ppmVisitStatus; + // notifyListeners(); + // Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); + // Navigator.of(context).pop(); + // } else { + // Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}"); + // } + // Navigator.of(context).pop(); + // return response.statusCode; + // } catch (error) { + // return -1; + // } + // } /// return -2 if request in progress /// return -1 if error happen when sending request diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 3ad1f2b4..b8cb09a2 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -544,6 +544,11 @@ "executionTimeFrame": "إطار زمني للتنفيذ", "pmTestResult": "نتيجة اختبار الصيانة الوقائية", "actualVisit": "الزيارة الفعلية", - "typeOfPm": "نوع الصيانة الوقائية" + "typeOfPm": "نوع الصيانة الوقائية", + "totalWorkingTime": "إجمالي وقت العمل", + "attachments": "المرفقات", + "supplierName": "اسم المورد", + "externalEngineerName": "اسم المهندس الخارجي", + "telephone": "الهاتف" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e534870d..07b5420a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -547,5 +547,10 @@ "executionTimeFrame": "Execution Time Frame", "pmTestResult": "PM Test Result", "actualVisit": "Actual Visit", - "typeOfPm": "Type of PM" + "totalWorkingTime": "Total Working Time", + "typeOfPm": "Type of PM", + "attachments": "Attachments", + "supplierName": "Supplier Name", + "externalEngineerName": "External Engineer Name", + "telephone": "Telephone" } \ No newline at end of file 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 d02c0e5c..a3181577 100644 --- a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart +++ b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart @@ -1,9 +1,13 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/widgets.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; class PlanPreventiveVisit { String? id; @@ -24,7 +28,7 @@ class PlanPreventiveVisit { String? fromDate; String? toDate; AssignedEmployee? assignedEmployee; - String? acutalDateOfVisit; + DateTime? acutalDateOfVisit; Lookup? typeOfService; Lookup? visitStatus; num? travelingHours; @@ -32,11 +36,12 @@ class PlanPreventiveVisit { int? executionTimeFrame; Lookup? taskStatus; Lookup? deviceStatus; - Lookup? assetAvailability; + Lookup? assetAvailability = Lookup(); Lookup? safety; String? engSignature; String? nurseSignature; List? preventiveVisitAttachments; + List? attachments = []; List? preventiveVisitCalibrations; List? preventiveVisitChecklists; List? preventiveVisitKits; @@ -76,6 +81,7 @@ class PlanPreventiveVisit { this.engSignature, this.nurseSignature, this.preventiveVisitAttachments, + this.attachments, this.preventiveVisitCalibrations, this.preventiveVisitChecklists, this.preventiveVisitKits, @@ -85,7 +91,7 @@ class PlanPreventiveVisit { PlanPreventiveVisit.fromJson(Map json) { id = json['id']; visitNo = json['visitNo']; - asset = json['asset'] != null ? new Asset.fromJson(json['asset']) : null; + asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null; planNo = json['planNo']; planName = json['planName']; nextPMDate = json['nextPMDate']; @@ -100,53 +106,54 @@ class PlanPreventiveVisit { roomName = json['roomName']; fromDate = json['fromDate']; toDate = json['toDate']; - assignedEmployee = json['assignedEmployee'] != null ? new AssignedEmployee.fromJson(json['assignedEmployee']) : null; - acutalDateOfVisit = json['acutalDateOfVisit']; - typeOfService = json['typeOfService'] != null ? new Lookup.fromJson(json['typeOfService']) : null; - visitStatus = json['visitStatus'] != null ? new Lookup.fromJson(json['visitStatus']) : null; + assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; + acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null; + typeOfService = json['typeOfService'] != null ? Lookup.fromJson(json['typeOfService']) : null; + visitStatus = json['visitStatus'] != null ? Lookup.fromJson(json['visitStatus']) : null; travelingHours = json['travelingHours']; comments = json['comments']; executionTimeFrame = json['executionTimeFrame']; - taskStatus = json['taskStatus'] != null ? new Lookup.fromJson(json['taskStatus']) : null; - deviceStatus = json['deviceStatus'] != null ? new Lookup.fromJson(json['deviceStatus']) : null; - assetAvailability = json['assetAvailability']; - safety = json['safety'] != null ? new Lookup.fromJson(json['safety']) : null; + taskStatus = json['taskStatus'] != null ? Lookup.fromJson(json['taskStatus']) : null; + deviceStatus = json['deviceStatus'] != null ? Lookup.fromJson(json['deviceStatus']) : null; + assetAvailability = json['assetAvailability'] != null ? Lookup.fromJson(json['assetAvailability']) : null; + safety = json['safety'] != null ? Lookup.fromJson(json['safety']) : null; engSignature = json['engSignature']; nurseSignature = json['nurseSignature']; if (json['preventiveVisitAttachments'] != null) { preventiveVisitAttachments = []; json['preventiveVisitAttachments'].forEach((v) { - preventiveVisitAttachments!.add(new PreventiveVisitAttachments.fromJson(v)); + preventiveVisitAttachments!.add(PreventiveVisitAttachments.fromJson(v)); }); + } if (json['preventiveVisitCalibrations'] != null) { preventiveVisitCalibrations = []; json['preventiveVisitCalibrations'].forEach((v) { - preventiveVisitCalibrations!.add(new PreventiveVisitCalibrations.fromJson(v)); + preventiveVisitCalibrations!.add(PreventiveVisitCalibrations.fromJson(v)); }); } if (json['preventiveVisitChecklists'] != null) { preventiveVisitChecklists = []; json['preventiveVisitChecklists'].forEach((v) { - preventiveVisitChecklists!.add(new PreventiveVisitChecklists.fromJson(v)); + preventiveVisitChecklists!.add(PreventiveVisitChecklists.fromJson(v)); }); } if (json['preventiveVisitKits'] != null) { preventiveVisitKits = []; json['preventiveVisitKits'].forEach((v) { - preventiveVisitKits!.add(new PreventiveVisitKits.fromJson(v)); + preventiveVisitKits!.add(PreventiveVisitKits.fromJson(v)); }); } if (json['preventiveVisitTimers'] != null) { preventiveVisitTimers = []; json['preventiveVisitTimers'].forEach((v) { - preventiveVisitTimers!.add(new PreventiveVisitTimers.fromJson(v)); + preventiveVisitTimers!.add(PreventiveVisitTimers.fromJson(v)); }); } if (json['preventiveVisitSuppliers'] != null) { preventiveVisitSuppliers = []; json['preventiveVisitSuppliers'].forEach((v) { - preventiveVisitSuppliers!.add( PreventiveVisitSuppliers.fromJson(v)); + preventiveVisitSuppliers!.add(PreventiveVisitSuppliers.fromJson(v)); }); } } @@ -154,10 +161,9 @@ class PlanPreventiveVisit { Map toJson({required int status}) { final Map data = {}; data['id'] = id; - data['acutalDateOfVisit'] = acutalDateOfVisit; - data['statusValue'] = status; + data['acutalDateOfVisit'] = acutalDateOfVisit?.toIso8601String(); data['typeOfServiceId'] = typeOfService?.id; - data['visitStatusValue'] = visitStatus?.value; + data['visitStatusValue'] = status; data['travelingHours'] = travelingHours; data['comments'] = comments; data['taskStatusId'] = taskStatus?.id; @@ -211,8 +217,8 @@ class PlanPreventiveVisit { // data['engSignature'] = engSignature; // data['nurseSignature'] = nurseSignature; - if (preventiveVisitAttachments != null) { + data['preventiveVisitAttachments'] = preventiveVisitAttachments!.map((v) => v.toJson()).toList(); } if (preventiveVisitCalibrations != null) { @@ -354,7 +360,7 @@ class PlanPreventiveVisit { // PlanPreventiveVisit.fromJson(Map json) { // id = json['id']; // visitNo = json['visitNo']; -// asset = json['asset'] != null ? new Asset.fromJson(json['asset']) : null; +// asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null; // planNo = json['planNo']; // planName = json['planName']; // nextPMDate = json['nextPMDate']; @@ -369,10 +375,10 @@ class PlanPreventiveVisit { // roomName = json['roomName']; // fromDate = json['fromDate']; // toDate = json['toDate']; -// assignedEmployee = json['assignedEmployee'] != null ? new AssignedEmployee.fromJson(json['assignedEmployee']) : null; +// assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; // acutalDateOfVisit = json['acutalDateOfVisit']; -// typeOfService = json['typeOfService'] != null ? new TypeOfService.fromJson(json['typeOfService']) : null; -// visitStatus = json['visitStatus'] != null ? new VisitStatus.fromJson(json['visitStatus']) : null; +// typeOfService = json['typeOfService'] != null ? TypeOfService.fromJson(json['typeOfService']) : null; +// visitStatus = json['visitStatus'] != null ? VisitStatus.fromJson(json['visitStatus']) : null; // travelingHours = json['travelingHours']; // comments = json['comments']; // executionTimeFrame = json['executionTimeFrame']; @@ -391,37 +397,37 @@ class PlanPreventiveVisit { // if (json['preventiveVisitCalibrations'] != null) { // preventiveVisitCalibrations = []; // json['preventiveVisitCalibrations'].forEach((v) { -// preventiveVisitCalibrations!.add(new PreventiveVisitChecklists.fromJson(v)); +// preventiveVisitCalibrations!.add( PreventiveVisitChecklists.fromJson(v)); // }); // } // if (json['preventiveVisitChecklists'] != null) { // preventiveVisitChecklists = []; // json['preventiveVisitChecklists'].forEach((v) { -// preventiveVisitChecklists!.add(new PreventiveVisitChecklists.fromJson(v)); +// preventiveVisitChecklists!.add( PreventiveVisitChecklists.fromJson(v)); // }); // } // if (json['preventiveVisitKits'] != null) { // preventiveVisitKits = []; // json['preventiveVisitKits'].forEach((v) { -// preventiveVisitKits!.add(new PreventiveVisitChecklists.fromJson(v)); +// preventiveVisitKits!.add( PreventiveVisitChecklists.fromJson(v)); // }); // } // if (json['preventiveVisitTimers'] != null) { // preventiveVisitTimers = []; // json['preventiveVisitTimers'].forEach((v) { -// preventiveVisitTimers!.add(new PreventiveVisitTimers.fromJson(v)); +// preventiveVisitTimers!.add( PreventiveVisitTimers.fromJson(v)); // }); // } // if (json['preventiveVisitSuppliers'] != null) { // preventiveVisitSuppliers = []; // json['preventiveVisitSuppliers'].forEach((v) { -// preventiveVisitSuppliers!.add(new PreventiveVisitChecklists.fromJson(v)); +// preventiveVisitSuppliers!.add( PreventiveVisitChecklists.fromJson(v)); // }); // } // } // // Map toJson() { -// final Map data = new Map(); +// final Map data = Map(); // data['id'] = this.id; // data['visitNo'] = this.visitNo; // if (this.asset != null) { @@ -536,7 +542,7 @@ class Asset { } Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['id'] = this.id; data['assetNumber'] = this.assetNumber; data['assetSerialNo'] = this.assetSerialNo; @@ -562,7 +568,7 @@ class AssignedEmployee { } Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['userId'] = this.userId; data['userName'] = this.userName; data['email'] = this.email; @@ -586,7 +592,7 @@ class AssignedEmployee { // } // // Map toJson() { -// final Map data = new Map(); +// final Map data = Map(); // data['id'] = this.id; // data['name'] = this.name; // data['value'] = this.value; @@ -608,7 +614,7 @@ class AssignedEmployee { // } // // Map toJson() { -// final Map data = new Map(); +// final Map data = Map(); // data['id'] = this.id; // data['name'] = this.name; // data['value'] = this.value; @@ -627,21 +633,21 @@ class PreventiveVisitChecklists { PreventiveVisitChecklists.fromJson(Map json) { id = json['id']; - taskStatus = json['taskStatus'] != null ? Lookup.fromJson(json['taskStatus']) : null; + taskStatus = json['taskStatus'] != null ? Lookup.fromJson(json['taskStatus']) : null; taskComment = json['taskComment']; measuredValue = json['measuredValue']; - instructionText = json['instructionText'] != null ? InstructionText.fromJson(json['instructionText']) : null; + instructionText = json['instructionText'] != null ? InstructionText.fromJson(json['instructionText']) : null; } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['taskStatus'] = this.taskStatus?.toJson(); - data['taskComment'] = this.taskComment; - data['measuredValue'] = this.measuredValue; - if (this.instructionText != null) { - data['instructionText'] = this.instructionText!.toJson(); - } + final Map data = {}; + data['id'] = id; + data['taskStatusId'] = taskStatus?.id; + data['taskComment'] = taskComment; + data['measuredValue'] = measuredValue; + // if (instructionText != null) { + // data['instructionText'] = instructionText!.toJson(); + // } return data; } } @@ -658,9 +664,9 @@ class InstructionText { } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['text'] = this.text; + final Map data = {}; + data['id'] = id; + data['text'] = text; return data; } } @@ -702,7 +708,7 @@ class PreventiveVisitAttachments { } Map toJson() { - final Map data = {}; + final Map data = {}; data['id'] = id; data['attachmentName'] = attachmentName; return data; @@ -718,15 +724,16 @@ class PreventiveVisitCalibrations { PreventiveVisitCalibrations.fromJson(Map json) { id = json['id']; - asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null; + asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null; calibrationDateOfTesters = json['calibrationDateOfTesters']; } Map toJson() { - final Map data = {}; + final Map data = {}; data['id'] = id; if (asset != null) { - data['asset'] = asset!.toJson(); + // data['asset'] = asset!.toJson(); + data['assetId'] = asset?.id; } data['calibrationDateOfTesters'] = calibrationDateOfTesters; return data; @@ -737,18 +744,19 @@ class PreventiveVisitSuppliers { int? id; SupplierDetails? supplier; SuppPersons? suppPerson; - String? startDateTime; - String? endDateTime; + DateTime? startDateTime; + DateTime? endDateTime; + TextEditingController? workingHoursController; num? workingHours; - PreventiveVisitSuppliers({this.id, this.supplier, this.suppPerson, this.startDateTime, this.endDateTime, this.workingHours}); + PreventiveVisitSuppliers({this.id, this.supplier, this.suppPerson, this.startDateTime, this.endDateTime, this.workingHours, this.workingHoursController}); PreventiveVisitSuppliers.fromJson(Map json) { id = json['id']; - supplier = json['supplier'] != null ? SupplierDetails.fromJson(json['supplier']) : null; - suppPerson = json['suppPerson'] != null ? SuppPersons.fromJson(json['suppPerson']) : null; - startDateTime = json['startDateTime']; - endDateTime = json['endDateTime']; + supplier = json['supplier'] != null ? SupplierDetails.fromJson(json['supplier']) : null; + suppPerson = json['suppPerson'] != null ? SuppPersons.fromJson(json['suppPerson']) : null; + startDateTime = json['startDateTime'] != null ? DateTime.parse(json['startDateTime']) : null; + endDateTime = json['endDateTime'] != null ? DateTime.parse(json['endDateTime']) : null; workingHours = json['workingHours']; } @@ -756,13 +764,15 @@ class PreventiveVisitSuppliers { final Map data = {}; data['id'] = id; if (supplier != null) { - data['supplier'] = supplier!.toJson(); + // data['supplier'] = supplier!.toJson(); + data['supplierId'] = supplier?.id; } if (suppPerson != null) { - data['suppPerson'] = suppPerson!.toJson(); + // data['suppPerson'] = suppPerson!.toJson(); + data['suppPersonId'] = suppPerson?.id; } - data['startDateTime'] = startDateTime; - data['endDateTime'] = endDateTime; + data['startDateTime'] = startDateTime?.toIso8601String(); + data['endDateTime'] = endDateTime?.toIso8601String(); data['workingHours'] = workingHours; return data; } @@ -851,7 +861,7 @@ class Supplier { if (json['suppPersons'] != null) { suppPersons = []; json['suppPersons'].forEach((v) { - suppPersons!.add(new SuppPersons.fromJson(v)); + suppPersons!.add(SuppPersons.fromJson(v)); }); } if (json['suppTCodes'] != null) { @@ -863,7 +873,7 @@ class Supplier { } Map toJson() { - final Map data = {}; + final Map data = {}; data['id'] = id; data['suppliername'] = suppliername; data['name'] = name; @@ -921,7 +931,7 @@ class Supplier { // } // // Map toJson() { -// final Map data = new Map(); +// final Map data = Map(); // data['id'] = this.id; // data['supplierId'] = this.supplierId; // data['personName'] = this.personName; @@ -941,14 +951,15 @@ class PreventiveVisitKits { PreventiveVisitKits.fromJson(Map json) { id = json['id']; - partCatalogItem = json['partCatalogItem'] != null ? new PartCatalogItem.fromJson(json['partCatalogItem']) : null; + partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null; } Map toJson() { - final Map data = new Map(); + final Map data = Map(); data['id'] = id; if (partCatalogItem != null) { - data['partCatalogItem'] = partCatalogItem!.toJson(); + // data['partCatalogItem'] = partCatalogItem!.toJson(); + data['partCatalogItemId'] = partCatalogItem?.id; } return data; } @@ -970,7 +981,7 @@ class PartCatalogItem { } Map toJson() { - final Map data = {}; + final Map data = {}; data['id'] = id; data['partName'] = partName; data['partNumber'] = partNumber; diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index 4c52daba..b18f5ee8 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -37,6 +37,10 @@ class ServiceRequestUtils { return -1; // Indicating invalid input } } + static bool isLocalUrl(String url) { + if (url.isEmpty != false) return false; + return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); + } static String calculateTimeDifference(DateTime startDate, DateTime endDate) { try { diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index e649efb1..d04696bd 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -38,6 +38,7 @@ class _PpmDetailsPageState extends State { @override void initState() { + getVisitData(); super.initState(); } @@ -46,22 +47,24 @@ class _PpmDetailsPageState extends State { super.dispose(); } + Future getVisitData() async { + ppmProvider = Provider.of(context, listen: false); + await ppmProvider?.getPlanPreventiveVisitById(widget.request.id!); + } + @override Widget build(BuildContext context) { userProvider ??= Provider.of(context, listen: false); - ppmProvider ??= Provider.of(context, listen: false); - ppmProvider!.getPlanPreventiveVisitById(widget.request.id!); + // ppmProvider ??= Provider.of(context, listen: false); + // ppmProvider!.getPlanPreventiveVisitById(widget.request.id!); return Scaffold( appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), body: SafeArea( - child: FutureBuilder( - future: ppmProvider!.getPlanPreventiveVisitById(widget.request.id!), - builder: (context, snap) { - if (snap.connectionState == ConnectionState.waiting) { - return const ALoading(); - } else if (snap.hasData) { - PlanPreventiveVisit planPreventiveVisit = snap.data as PlanPreventiveVisit; - return Column(children: [ + child: Consumer(builder: (context, ppmProvider, child) { + PlanPreventiveVisit? planPreventiveVisit = ppmProvider.planPreventiveVisit; + return ppmProvider.isLoading + ? const ALoading() + : Column(children: [ SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -76,8 +79,8 @@ class _PpmDetailsPageState extends State { ), if (widget.request.priority != null) 8.width, StatusLabel( - label: planPreventiveVisit.visitStatus!.name!, - id: planPreventiveVisit.visitStatus!.id!, + label: planPreventiveVisit?.visitStatus!.name!, + id: planPreventiveVisit!.visitStatus!.id!, textColor: AppColor.getRequestStatusTextColorByName(context, planPreventiveVisit.visitStatus!.name!), backgroundColor: AppColor.getRequestStatusColorByName(context, planPreventiveVisit.visitStatus!.name!), ), @@ -92,7 +95,7 @@ class _PpmDetailsPageState extends State { '${context.translation.requestNo}: ${planPreventiveVisit.visitNo}'.bodyText(context), const Divider().defaultStyle(context), // '${context.translation.expectDate}: ${planPreventiveVisit.expectedDate?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, - '${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, + '${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, const Divider().defaultStyle(context), '${context.translation.engineerName}: ${planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText(context), //todo @baha, '${context.translation.site}: ${planPreventiveVisit.siteName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, @@ -106,17 +109,12 @@ class _PpmDetailsPageState extends State { if (userProvider!.user!.type == UsersTypes.engineer && (planPreventiveVisit.visitStatus!.id! != 270 && planPreventiveVisit.visitStatus!.id! != 269)) AppFilledButton( onPressed: () async { - //TODO remove after testing.. - await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit, details: widget.request))); - // setState(() {}); }, label: context.translation.updateRequest, ).paddingAll(16) ]); - } - return NoDataFound(message: context.translation.noDataFound).center; - }), + }), ), ); } diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart index ea6bfa50..b50e6a14 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart @@ -1,36 +1,297 @@ +// import 'package:flutter/material.dart'; +// import 'package:fluttertoast/fluttertoast.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/user_provider.dart'; +// import 'package:test_sa/extensions/context_extension.dart'; +// import 'package:test_sa/extensions/int_extensions.dart'; +// import 'package:test_sa/extensions/string_extensions.dart'; +// import 'package:test_sa/extensions/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/lookup.dart'; +// import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; +// import 'package:test_sa/models/ppm/ppm_calibration_tools.dart'; +// import 'package:test_sa/models/service_request/supplier_details.dart'; +// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +// import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +// import 'package:test_sa/providers/loading_list_notifier.dart'; +// import 'package:test_sa/providers/ppm_service_provider.dart'; +// import 'package:test_sa/providers/work_order/vendor_provider.dart'; +// import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +// import 'package:test_sa/views/widgets/pentry/calibration_tool_asset_picker.dart'; +// +// import '../../../../../new_views/app_style/app_color.dart'; +// import '../../../../widgets/date_and_time/date_picker.dart'; +// +// class PpmExternalDetailsForm extends StatefulWidget { +// final List? models; +// +// const PpmExternalDetailsForm({Key? key, this.models = const []}) : super(key: key); +// +// @override +// State createState() => _PpmExternalDetailsFormState(); +// } +// +// class _PpmExternalDetailsFormState extends State { +// final TextEditingController _workingHoursController = TextEditingController(); +// +// @override +// Widget build(BuildContext context) { +// return ListView.builder( +// itemCount: widget.models!.length + 1, +// padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), +// itemBuilder: (context, index) { +// if (index == widget.models!.length) { +// return AppFilledButton( +// label: "Add More External Details".addTranslation, +// maxWidth: true, +// textColor: AppColor.black10, +// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, +// icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), +// showIcon: true, +// onPressed: () async { +// // if (widget.models?.isNotEmpty ?? false) { +// // if (widget.models!.last.assetId == null) { +// // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); +// // return; +// // } +// // if (widget.models!.last.calibrationDateOfTesters == null) { +// // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); +// // return; +// // } +// // } +// // widget.models!.add(PpmCalibrationTools(id: 0)); +// // setState(() {}); +// }, +// ); +// } +// final model = widget.models![index]; +// // _workingHoursController.text = model.workingHours != null ? model.workingHours.toString() : ''; +// return Container( +// padding: const EdgeInsets.all(16), +// margin: EdgeInsets.only(bottom: 16.toScreenHeight), +// decoration: BoxDecoration( +// color: AppColor.background(context), +// borderRadius: BorderRadius.circular(20), +// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// (index == 0 ? "1 /4 . External Details" : "").heading5(context), +// "trash".toSvgAsset(height: 20, width: 15).onPress(() { +// widget.models!.remove(model); +// +// setState(() {}); +// }), +// ], +// ), +// 16.height, +// SingleItemDropDownMenu( +// context: context, +// title: context.translation.supplier, +// initialValue: model.supplier, +// backgroundColor: AppColor.neutral100, +// showAsBottomSheet: true, +// onSelect: (supplier) { +// if (supplier != null) { +// model.supplier = supplier; +// print('supplier dtails is ${supplier.toJson()}'); +// setState(() {}); +// } +// }, +// ), +// 8.height, +// SingleItemDropDownMenu( +// context: context, +// title: context.translation.supplierEngineer, +// enabled: model.suppPerson != null, +// backgroundColor: AppColor.neutral100, +// initialValue: model.suppPerson, +// staticData: model.supplier?.suppPersons, +// showAsBottomSheet: true, +// onSelect: (suppPerson) { +// if (suppPerson != null) { +// model.suppPerson = suppPerson; +// print('supply person is ${model.suppPerson?.toJson()}'); +// } +// }, +// ), +// 8.height, +// AppTextFormField( +// labelText: "Telephone", +// initialValue: model.supplier?.telephones != null && model.supplier!.telephones!.isNotEmpty ? (model.supplier?.telephones?[0].telephone ?? "").toString() : '', +// textAlign: TextAlign.center, +// backgroundColor: AppColor.neutral100, +// style: Theme.of(context).textTheme.titleMedium, +// textInputType: TextInputType.number, +// onChange: (value) { +// model.supplier?.telephones?[0].telephone = value; +// }, +// ), +// 8.height, +// Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// ADatePicker( +// label: context.translation.startTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: model.startDateTime, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// setState(() { +// model.startDateTime = selectedDateTime; +// }); +// model.endDateTime = null; +// _workingHoursController.clear(); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: model.startDateTime, +// endTime: model.endDateTime, +// workingHoursController: _workingHoursController, +// updateModel: (hours) { +// model.workingHours = hours; +// }, +// ); +// } +// }); +// }, +// ).expanded, +// 8.width, +// ADatePicker( +// label: context.translation.endTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: model.endDateTime, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// if (model.startDateTime != null && selectedDateTime.isBefore(model.startDateTime!)) { +// "End Date time must be greater then start date".showToast; +// return; +// } +// model.endDateTime = selectedDateTime; +// setState(() {}); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: model.startDateTime, +// endTime: model.endDateTime, +// workingHoursController: _workingHoursController, +// updateModel: (hours) { +// model.workingHours = hours; +// }, +// ); +// } +// }); +// }, +// ).expanded, +// ], +// ), +// 8.height, +// AppTextFormField( +// labelText: context.translation.workingHours, +// backgroundColor: AppColor.neutral80, +// controller: _workingHoursController, +// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), +// // initialValue: model.workingHours != null ? model.workingHours.toString() : '', +// textAlign: TextAlign.center, +// labelStyle: AppTextStyles.textFieldLabelStyle, +// enable: false, +// showShadow: false, +// style: Theme.of(context).textTheme.titleMedium, +// ), +// 8.height, +// ], +// ), +// ); +// }, +// ); +// } +// } + import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/lookup.dart'; -import 'package:test_sa/models/ppm/ppm_calibration_tools.dart'; +import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; +import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; -import 'package:test_sa/views/widgets/pentry/calibration_tool_asset_picker.dart'; - -import '../../../../../new_views/app_style/app_color.dart'; -import '../../../../widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/providers/work_order/vendor_provider.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; class PpmExternalDetailsForm extends StatefulWidget { - final List? models; + final List? models; - const PpmExternalDetailsForm({Key? key, this.models = const []}) : super(key: key); + const PpmExternalDetailsForm({Key? key, this.models = const []}) : super(key: key); @override State createState() => _PpmExternalDetailsFormState(); } class _PpmExternalDetailsFormState extends State { + bool isLoading = false; + +//TODO add loader when adding or deleting item.. + + void _addNewEntry() { + setState(() { + // isLoading = true; + widget.models!.add(PreventiveVisitSuppliers(id: 0)); + // Future.delayed(Duration(seconds: 1)).whenComplete(() { + // setState(() { + // isLoading = false; + // }); + // }); + }); + } + + void _removeEntry(int index) { + setState(() { + isLoading = true; + widget.models!.removeAt(index); + // isLoading = false; + }); + } @override Widget build(BuildContext context) { - final userProvider = Provider.of(context); return ListView.builder( itemCount: widget.models!.length + 1, - padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), + padding: const EdgeInsets.all(16), itemBuilder: (context, index) { if (index == widget.models!.length) { return AppFilledButton( @@ -40,70 +301,193 @@ class _PpmExternalDetailsFormState extends State { buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), showIcon: true, - onPressed: () async { - if (widget.models?.isNotEmpty ?? false) { - if (widget.models!.last.assetId == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); - return; - } - if (widget.models!.last.calibrationDateOfTesters == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); - return; - } - } - widget.models!.add(PpmCalibrationTools(id: 0)); - setState(() {}); - }, + onPressed: _addNewEntry, ); } - final model = widget.models![index]; - return Container( - padding: const EdgeInsets.all(16), - margin: EdgeInsets.only(bottom: 16.toScreenHeight), - decoration: BoxDecoration( - color: AppColor.background(context), - borderRadius: BorderRadius.circular(20), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + // return !isLoading + // ? + return ExternalDetailItem( + model: widget.models![index], + index: index, + onRemove: () => _removeEntry(index), + ); + // : const ALoading(); + }, + ); + } +} + +class ExternalDetailItem extends StatefulWidget { + final PreventiveVisitSuppliers model; + final VoidCallback onRemove; + final int index; + + const ExternalDetailItem({ + Key? key, + required this.model, + required this.onRemove, + required this.index, + }) : super(key: key); + + @override + State createState() => _ExternalDetailItemState(); +} + +class _ExternalDetailItemState extends State { + TextEditingController? controller; + + @override + void initState() { + controller = TextEditingController(text: widget.model.workingHours != null ? widget.model.workingHours.toString() : ''); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + margin: EdgeInsets.only(bottom: 16.toScreenHeight), + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: BorderRadius.circular(20), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), + "trash".toSvgAsset(height: 20, width: 15).onPress(() { + widget.onRemove(); + }), + ], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + 16.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplier, + initialValue: widget.model.supplier, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + onSelect: (supplier) { + if (supplier != null) { + setState(() { + widget.model.supplier = supplier; + }); + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplierEngineer, + enabled: widget.model.supplier != null, + backgroundColor: AppColor.neutral100, + initialValue: widget.model.suppPerson, + staticData: widget.model.supplier?.suppPersons, + showAsBottomSheet: true, + onSelect: (suppPerson) { + if (suppPerson != null) { + widget.model.suppPerson = suppPerson; + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (index == 0 ? "1 /4 . External Details" : "").heading5(context), - "trash".toSvgAsset(height: 20, width: 15).onPress(() { - widget.models!.remove(model); - setState(() {}); - }), - ], - ), - 16.height, - CalibrationToolAssetPicker( - initialValue: model.assetId == null ? null : Lookup(id: model.assetId?.toInt(), name: model.assetNumber ?? ""), - hospitalId: userProvider.user!.clientId, - onPick: (number) { - model.assetNumber = number.assetNumber; - model.assetId = number.id; - setState(() {}); + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.startDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.model.startDateTime = selectedDateTime; + }); + widget.model.endDateTime = null; + controller?.clear(); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); + } + }); }, - ), - 8.height, + ).expanded, + 8.width, ADatePicker( - label: context.translation.calibrationDate, - date: DateTime.tryParse(model.calibrationDateOfTesters ?? ""), - from: DateTime.now().subtract(const Duration(days: 90)), - backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.background(context), - withBorder: false, - onDatePicker: (date) { - model.calibrationDateOfTesters = date.toIso8601String(); - setState(() {}); + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.endDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { + "End Date time must be greater than start date".showToast; + return; + } + setState(() { + widget.model.endDateTime = selectedDateTime; + }); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); + } + }); }, - ), + ).expanded, ], ), - ); - }, + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: controller, + textAlign: TextAlign.center, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], + ), ); } } diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index 8db64344..1cabdd30 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -1,7 +1,9 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; @@ -11,7 +13,9 @@ import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart'; import '../../../../../extensions/text_extensions.dart'; @@ -32,30 +36,37 @@ class UpdatePpm extends StatefulWidget { } class _UpdatePpmState extends State with SingleTickerProviderStateMixin { - late UserProvider _userProvider; - late PpmProvider _regularVisitsProvider; - Ppm? _ppm; - late PlanPreventiveVisit _planPreventiveVisit; final GlobalKey _scaffoldKey = GlobalKey(); late TabController _tabController; + late PpmProvider ppmProvider; + + _onSubmit({required int status}) async { + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = []; + for (var item in ppmProvider.ppmPlanAttachments) { + ppmProvider.planPreventiveVisit?.preventiveVisitAttachments + ?.add(PreventiveVisitAttachments(id: 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + } + log('data i got is ${ppmProvider.planPreventiveVisit?.toJson(status: status)}'); - _onSubmit() async { - // if (!(await _ppm.validate(context))) { - // setState(() {}); - // return; - // } - // _ppm.removeEmptyObjects(); - // await _regularVisitsProvider.updatePentry(context, user: _userProvider.user!, ppm: widget.ppm); + await ppmProvider.updateVisitByEngineer(status: status).whenComplete((){ + // if(status==1){// when click complete then this request remove from the list and status changes to closed.. + // + // } + // allRequestsProvider.recurrentWoData?.recurrentWoTimerModel=null; + Navigator.pop(context); + Navigator.pop(context); + }); } @override void initState() { - _ppm = widget.ppm; + ppmProvider = Provider.of(context, listen: false); _planPreventiveVisit = widget.planPreventiveVisit; - _tabController = TabController(length: 3, vsync: this); + _tabController = TabController(length: ppmProvider.totalTabs, vsync: this); super.initState(); } @@ -69,8 +80,6 @@ class _UpdatePpmState extends State with SingleTickerProviderStateMix @override Widget build(BuildContext context) { - _userProvider = Provider.of(context, listen: false); - _regularVisitsProvider = Provider.of(context, listen: false); return Scaffold( backgroundColor: AppColor.neutral110, appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), @@ -122,13 +131,11 @@ class _UpdatePpmState extends State with SingleTickerProviderStateMix physics: const NeverScrollableScrollPhysics(), controller: _tabController, children: [ - // PpmExternalDetailsForm(models: []), + if (ppmProvider.totalTabs == 4) ...[ + PpmExternalDetailsForm(models: _planPreventiveVisit.preventiveVisitSuppliers), + ], PpmCalibrationToolsForm(models: _planPreventiveVisit.preventiveVisitCalibrations), - PpmPMKitsForm(models: _planPreventiveVisit.preventiveVisitKits,assetId: _planPreventiveVisit.asset?.id), - - // PpmExternalDetailsForm(models: _ppm.vCalibrationTools), - // PpmCalibrationToolsForm(models: _ppm.vCalibrationTools), - // PpmPMKitsForm(models: _ppm.vKits, assetId: widget.ppm.assetId), + PpmPMKitsForm(models: _planPreventiveVisit.preventiveVisitKits, assetId: _planPreventiveVisit.asset?.id), PpmPmChecklistForm(checkList: _planPreventiveVisit.preventiveVisitChecklists), ], ) @@ -143,18 +150,20 @@ class _UpdatePpmState extends State with SingleTickerProviderStateMix buttonColor: AppColor.white60, textColor: AppColor.neutral50, onPressed: () { - _onSubmit(); + _onSubmit(status: 0); }, label: context.translation.save, ).expanded, 16.width, AppFilledButton( onPressed: () { + if (tabIndex == 0) { + _onSubmit(status: 1); return; } if (_tabController.index == 3) { - _onSubmit(); + _onSubmit(status: 1); } else { _tabController.animateTo(_tabController.index + 1); setState(() {}); 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 5da2df4e..a9f2dfc1 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 @@ -1,25 +1,27 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; -import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; -import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/ppm_asset_availability_provider.dart'; import 'package:test_sa/providers/ppm_electrical_safety_provider.dart'; import 'package:test_sa/providers/ppm_service_provider.dart'; import 'package:test_sa/providers/ppm_task_status_provider.dart'; -import 'package:test_sa/providers/work_order/vendor_provider.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; - import '../../../../../models/lookup.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../../../../providers/ppm_visit_status_provider.dart'; -import '../../../../widgets/date_and_time/date_picker.dart'; import '../../../../widgets/timer/app_timer.dart'; class WoInfoForm extends StatefulWidget { @@ -33,383 +35,331 @@ class WoInfoForm extends StatefulWidget { } class _WoInfoFormState extends State { - SupplierDetails? initialSupplier; - SuppPersons? _suppPerson; + //TODO need to move this to provider ... @override void initState() { -// TODO need to use model attributes directly no need to assign to new variable. when confirm from backend we need one or multiple suppliers. - if (widget.planPreventiveVisit.preventiveVisitSuppliers != null && widget.planPreventiveVisit.preventiveVisitSuppliers!.isNotEmpty) { - initialSupplier = SupplierDetails.fromJson(widget.planPreventiveVisit.preventiveVisitSuppliers?[0].supplier?.toJson()); - _suppPerson = SuppPersons.fromJson(widget.planPreventiveVisit.preventiveVisitSuppliers?[0].suppPerson?.toJson()); - } + WidgetsBinding.instance.addPostFrameCallback((_) async { + PpmProvider ppmProvider = Provider.of(context, listen: false); + if (widget.planPreventiveVisit.preventiveVisitAttachments != null && widget.planPreventiveVisit.preventiveVisitAttachments!.isNotEmpty) { + ppmProvider.ppmPlanAttachments = []; + ppmProvider.ppmPlanAttachments.addAll(widget.planPreventiveVisit.preventiveVisitAttachments!.map((e) => File(e.attachmentName!)).toList()); + } + }); super.initState(); } @override Widget build(BuildContext context) { - // widget.planPreventiveVisit ??= []; - // widget.planPreventiveVisit.files = (widget.model.files ?? []).where((element) => element.attachmentName?.isNotEmpty ?? false).toList(); - 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 ListView( - padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.planPreventiveVisit.visitStatus != null) - StatusLabel( - label: widget.planPreventiveVisit.visitStatus?.name, - textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), - backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + return Consumer(builder: (context, ppmProvider, child) { + return ListView( + padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.planPreventiveVisit.visitStatus != null) + StatusLabel( + label: widget.planPreventiveVisit.visitStatus?.name, + textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + ), + 8.height, + widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), + 2.height, + '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), + //need to add in translation it's suggestion from ahmed.. + 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}' + .bodyText2(context) + .custom(color: AppColor.neutral120), + '${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}' + .bodyText2(context) + .custom(color: AppColor.neutral120), + + '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), + 12.height, + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), + "info_icon".toSvgAsset(height: 17, width: 17), + ], ), - 8.height, - widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), - 2.height, - '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), - 12.height, - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), - "info_icon".toSvgAsset(height: 17, width: 17), - ], - ), - 2.height, - '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), + 2.height, + '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), - // SingleItemDropDownMenu( - // context: context, - // initialValue: - // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), - // title: context.translation.ppmVisit, - // onSelect: (value) { - // if (value?.value == 4) { - // "Status cannot be change to ${value?.name}.".addTranslation.showToast; - // setState(() {}); - // return; - // } - // - // if (value != null) { - // widget.planPreventiveVisit.visitStatus?.name = value.name; - // widget.planPreventiveVisit.visitStatus?.id = value.id; - // } - // }, - // ), + // SingleItemDropDownMenu( + // context: context, + // initialValue: + // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), + // title: context.translation.ppmVisit, + // onSelect: (value) { + // if (value?.value == 4) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // + // if (value != null) { + // widget.planPreventiveVisit.visitStatus?.name = value.name; + // widget.planPreventiveVisit.visitStatus?.id = value.id; + // } + // }, + // ), - // SingleItemDropDownMenu( - // context: context, - // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), - // title: context.translation.deviceStatus, - // onSelect: (value) { - // if (value != null) { - // widget.planPreventiveVisit.deviceStatusId = value.id; - // widget.planPreventiveVisit.deviceStatusName = value.name; - // } - // }, - // ), - 8.height, - SingleItemDropDownMenu( - context: context, - initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), - title: context.translation.taskStatus, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.taskStatus?.id = value.id; - widget.planPreventiveVisit.taskStatus?.name = value.name; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - initialValue: widget.planPreventiveVisit.assetAvailability == null - ? null - : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), - title: "Asset Availability", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.assetAvailability?.id = value.id; - widget.planPreventiveVisit.assetAvailability?.name = value.name; - } - }, - ), + // SingleItemDropDownMenu( + // context: context, + // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), + // title: context.translation.deviceStatus, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.deviceStatusId = value.id; + // widget.planPreventiveVisit.deviceStatusName = value.name; + // } + // }, + // ), + 8.height, + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + //TODO Ahmed need to provide look up value.... - 8.height, - SingleItemDropDownMenu( - context: context, - initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), - title: "Electrical Safety", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.safety?.id = value.id; - widget.planPreventiveVisit.safety?.name = value.name; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - initialValue: - widget.planPreventiveVisit.typeOfService == null ? null : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), - title: context.translation.serviceType, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.typeOfService?.id = value.id; - widget.planPreventiveVisit.typeOfService?.name = value.name; - //TODO check this why make all values null.. + SingleItemDropDownMenu( + context: context, + initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), + title: context.translation.pmTestResult, + backgroundColor: AppColor.neutral100, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.taskStatus = value; + } + }, + ), + 8.height, + ADatePicker( + label: context.translation.actualVisit, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.planPreventiveVisit.acutalDateOfVisit, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.planPreventiveVisit.acutalDateOfVisit = selectedDate; + }); - // widget.planPreventiveVisit?.preventiveVisitSuppliers?. = null; - // widget.model.supplierName = null; - // initialSupplier = null; - // _suppPerson = null; - // widget.model.suppPersonId = null; - // widget.model.suppPerson = null; + } + }); + }, + ), + // SingleItemDropDownMenu( + // context: context, + // backgroundColor: AppColor.neutral100, + // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + // title: context.translation.actualVisit, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.safety = value; + // // widget.planPreventiveVisit.safety?.id = value.id; + // // widget.planPreventiveVisit.safety?.name = value.name; + // } + // }, + // ), - setState(() {}); - } - }, - ), - 8.height, + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + title: "Electrical Safety", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.safety = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + initialValue: widget.planPreventiveVisit.assetAvailability == null + ? null + : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), + title: "Asset Availability", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.assetAvailability = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + initialValue: widget.planPreventiveVisit.typeOfService == null + ? null + : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), + title: context.translation.typeOfPm, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.typeOfService = value; + if (widget.planPreventiveVisit.typeOfService?.id == 66) { + ppmProvider.totalTabs = 4; + } else { + ppmProvider.totalTabs = 3; + } + } + }, + ), + 8.height, + + _timerWidget(context, totalWorkingHours), + + 8.height, + AppTextFormField( + labelText: context.translation.callComments, + backgroundColor: AppColor.neutral100, + initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + onChange: (value) { + widget.planPreventiveVisit.comments = value; + }, + ), + 8.height, + MultiFilesPicker( + label: context.translation.attachments, + files: ppmProvider.ppmPlanAttachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + ], + ).toShadowContainer(context), + //TODO need to check this also... + // ESignature( + // title: context.translation.nurseSignature, + // oldSignature: widget.planPreventiveVisit.nurseSignature, + // newSignature: widget.planPreventiveVisit.localNurseSignature, + // onChange: (signature) { + // widget.planPreventiveVisit.localNurseSignature = signature; + // widget.planPreventiveVisit.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // }, + // ), + // ESignature( + // title: context.translation.engSign, + // oldSignature: widget.planPreventiveVisit.engSignature, + // newSignature: widget.planPreventiveVisit.localEngineerSignature, + // onChange: (signature) { + // widget.planPreventiveVisit.localEngineerSignature = signature; + // widget.planPreventiveVisit.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // }, + // ), + ], + ); + }); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours) { + return Column( + children: [ AppTimer( - label: context.translation.timer, + label: context.translation.workingHours, + decoration: BoxDecoration(color: AppColor.neutral100, borderRadius: BorderRadius.circular(10)), + width: double.infinity, timer: widget.planPreventiveVisit.tbsTimer, - enabled: widget.planPreventiveVisit.tbsTimer?.endAt == null, - timerProgress: (isRunning) { - print("timerProgress:$isRunning"); - }, + // enabled: widget.planPreventiveVisit.tbsTimer?.endAt == null, + timerProgress: (isRunning) {}, onChange: (timer) async { widget.planPreventiveVisit.tbsTimer = timer; return true; }, ), - 8.height, + 11.height, if (totalWorkingHours > 0.0) ...[ - Container( - height: 56.toScreenHeight, - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Total Working Time", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - ), - Text( - " ${formatDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ), - ), - 8.height, - ], - if (widget.planPreventiveVisit.typeOfService?.id == 66) ...[ - SingleItemDropDownMenu( - context: context, - title: context.translation.supplier, - initialValue: initialSupplier, - showAsBottomSheet: true, - onSelect: (supplier) { - if (supplier != null) { - initialSupplier = supplier; - print('supplier dtails is ${supplier.toJson()}'); - // widget.planPreventiveVisit.preventiveVisitSuppliers?[0].supplier=supplier; - // widget.model.supplierId = supplier.id; - // widget.model.supplierName = supplier.name; - // initialSupplier = supplier; - // _suppPerson = null; - // widget.model.suppPersonId = null; - // widget.model.suppPerson = null; - // setState(() {}); - } - }, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + context.translation.totalWorkingTime.bodyText2(context), + " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}".bodyText(context).custom(color: AppColor.black20), + ], ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.supplierEngineer, - enabled: initialSupplier?.suppPersons?.isNotEmpty ?? false, - initialValue: _suppPerson, - staticData: initialSupplier?.suppPersons, - showAsBottomSheet: true, - onSelect: (suppPerson) { - if (suppPerson != null) { - // _suppPerson = suppPerson; - // widget.model.suppPersonId = suppPerson.id; - // widget.model.suppPerson = suppPerson.name; - // setState(() {}); - } - }, - ), - 8.height, - // AppTextFormField( - // labelText: "Telephone", - // initialValue: (initialSupplier?.telephones?[0].telephone ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.titleMedium, - // textInputType: TextInputType.number, - // onChange: (value) { - // initialSupplier?.telephones?[0].telephone = value; - // }, - // ), - 8.height, - //TODO implement this after feedback from backend. - // AppTimer( - // label: "External Supplier Timer", - // timer: widget.model.externalEngineerTimer, - // enabled: widget.model.externalEngineerTimer?.endAt == null, - // timerProgress: (isRunning) { - // print("timerProgress:$isRunning"); - // }, - // onChange: (timer) async { - // widget.model.externalEngineerTimer = timer; - // return true; - // }, - // ), - // 8.height, ], - ADatePicker( - label: context.translation.actualVisitDate, - date: DateTime.tryParse(widget.planPreventiveVisit.acutalDateOfVisit ?? ""), - from: DateTime.now().subtract(const Duration(days: 30)), - onDatePicker: (date) { - // if (date.isBefore(DateTime.parse(widget.planPreventiveVisit.expectedDate!))) { - // "Actual visit date must be greater then expected date".showToast; - // return; - // } - // - // widget.model.actualDate = date.toIso8601String(); - // setState(() {}); - }, - ), - 8.height, - // ADatePicker( - // label: context.translation.expectedVisitDate, - // date: DateTime.tryParse(widget.model.nextDate ?? ""), - // from: DateTime.now().subtract(const Duration(days: 30)), - // enable: false, - // onDatePicker: (date) { - // widget.model.nextDate = date.toIso8601String(); - // setState(() {}); - // }, - // ), - 8.height, - AppTextFormField( - labelText: context.translation.travelingHours, - initialValue: (widget.planPreventiveVisit.travelingHours ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.number, - onChange: (value) { - widget.planPreventiveVisit.travelingHours = int.parse(value); - }, - ), - 8.height, - // MultiFilesPicker( - // label: context.translation.attachImage, - // files: widget.model.files!.map((e) => File(e.attachmentName!)).toList(), - // onChange: (files) { - // widget.model.files = files.map((e) => PpmAttachments(attachmentName: e.path)).toList(); - // }, - // ), - 8.height, - AppTextFormField( - labelText: context.translation.comments, - initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - onChange: (value) { - widget.planPreventiveVisit.comments = value; - }, - ), - 8.height, - // ESignature( - // title: context.translation.nurseSignature, - // oldSignature: widget.planPreventiveVisit.nurseSignature, - // newSignature: widget.planPreventiveVisit.localNurseSignature, - // onChange: (signature) { - // widget.planPreventiveVisit.localNurseSignature = signature; - // widget.planPreventiveVisit.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - // }, - // ), 8.height, - // ESignature( - // title: context.translation.engSign, - // oldSignature: widget.planPreventiveVisit.engSignature, - // newSignature: widget.planPreventiveVisit.localEngineerSignature, - // onChange: (signature) { - // widget.planPreventiveVisit.localEngineerSignature = signature; - // widget.planPreventiveVisit.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - // }, - // ), ], ); } - String formatDuration1(int seconds) { - int hours = seconds ~/ 3600; - int minutes = (seconds % 3600) ~/ 60; - - String formattedDuration = ''; - if (hours > 0) { - formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; - } - if (minutes > 0) { - formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; - } - if (formattedDuration.isEmpty) { - formattedDuration = 'Less than a minute'; - } - - return formattedDuration.trim(); - } - - 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(); - } +// String formatDuration1(int seconds) { +// int hours = seconds ~/ 3600; +// int minutes = (seconds % 3600) ~/ 60; +// +// String formattedDuration = ''; +// if (hours > 0) { +// formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; +// } +// if (minutes > 0) { +// formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; +// } +// if (formattedDuration.isEmpty) { +// formattedDuration = 'Less than a minute'; +// } +// +// return formattedDuration.trim(); +// } +// +// 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(); +// } }