diff --git a/android/app/build.gradle b/android/app/build.gradle index e55e2b22..4f0659df 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -54,22 +54,25 @@ android { } signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null - storePassword keystoreProperties['storePassword'] - } +// release { +// keyAlias keystoreProperties['keyAlias'] +// keyPassword keystoreProperties['keyPassword'] +// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null +// storePassword keystoreProperties['storePassword'] +// } } buildTypes { debug { signingConfig signingConfigs.debug } release { - minifyEnabled true - shrinkResources true - signingConfig signingConfigs.release + signingConfig signingConfigs.debug } +// release { +// minifyEnabled true +// shrinkResources true +// signingConfig signingConfigs.release +// } } } diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart index f40b309c..3bbfed51 100644 --- a/lib/controllers/api_routes/api_manager.dart +++ b/lib/controllers/api_routes/api_manager.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart' as http; import 'package:http/http.dart'; @@ -51,9 +52,12 @@ class ApiManager { headers.addAll(_headers); Uri _url = Uri.parse(url); - // print(_url); - // print(headers); - // log(json.encode(body)); + if (!kReleaseMode) { + print("URL:$_url"); + print("Headers:$headers"); + print("Body:$body"); + } + var request = http.Request('POST', _url); request.body = json.encode(body); request.headers.addAll(headers); @@ -83,7 +87,7 @@ class ApiManager { headers.addAll(_headers); Uri _url = Uri.parse(url); - // print(_url); + print(_url); // print(headers); // log(json.encode(body)); var request = http.Request('PUT', _url); diff --git a/lib/controllers/providers/api/device_transfer_provider.dart b/lib/controllers/providers/api/device_transfer_provider.dart index a534fbc0..43c5eced 100644 --- a/lib/controllers/providers/api/device_transfer_provider.dart +++ b/lib/controllers/providers/api/device_transfer_provider.dart @@ -23,7 +23,7 @@ class DeviceTransferProvider extends ChangeNotifier { building = null; floor = null; department = null; - room=""; + room = ""; startDate = null; endDate = null; } @@ -44,7 +44,6 @@ class DeviceTransferProvider extends ChangeNotifier { // failed _loading = false bool isLoading; - Hospital hospital; Buildings building; Floors floor; @@ -115,7 +114,7 @@ class DeviceTransferProvider extends ChangeNotifier { // "transferCode": "string", "destBuildingId": building?.id, "destFloorId": floor.id, - "destRoom": room, + "destRoom": room, // "senderBuildingId": 0, // "senderFloorId": 0, // "senderDepartmentId": 0, @@ -179,8 +178,8 @@ class DeviceTransferProvider extends ChangeNotifier { "senderMachineStatusId": newModel.status.id, "senderComment": newModel.comment, "senderWorkingHours": newModel.workingHours, - "senderStartDate": newModel.startDate?.toIso8601String(), - "senderEndDate": newModel.endDate?.toIso8601String(), + "senderStartDate": newModel.timer?.startAt?.toIso8601String(), + "senderEndDate": newModel.timer?.endAt?.toIso8601String(), "senderTravelingHours": newModel.travelingHours, "senderAttachmentName": "${newModel.signature}.png", "destSiteId": oldModel.receiver.client.id, @@ -189,8 +188,8 @@ class DeviceTransferProvider extends ChangeNotifier { "receiverMachineStatusId": oldModel.receiver.status.id ?? "", "receiverComment": oldModel.receiver.comment, "receiverWorkingHours": oldModel.receiver.workingHours, - "receiverStartDate": oldModel.receiver.startDate?.toIso8601String(), - "receiverEndDate": oldModel.receiver.endDate?.toIso8601String(), + "receiverStartDate": oldModel.receiver.timer?.startAt?.toIso8601String(), + "receiverEndDate": oldModel.receiver.timer?.endAt?.toIso8601String(), "receiverTravelingHours": oldModel.receiver.travelingHours, "receiverAttachmentName": "${oldModel.receiver.signature}.png", }); @@ -202,8 +201,8 @@ class DeviceTransferProvider extends ChangeNotifier { "senderMachineStatusId": oldModel.sender.status.id, "senderComment": oldModel.sender.comment, "senderWorkingHours": oldModel.sender.workingHours, - "senderStartDate": oldModel.sender.startDate?.toIso8601String(), - "senderEndDate": oldModel.sender.endDate?.toIso8601String(), + "senderStartDate": oldModel.sender.timer?.startAt?.toIso8601String(), + "senderEndDate": oldModel.sender.timer?.endAt?.toIso8601String(), "senderTravelingHours": oldModel.sender.travelingHours, "senderAttachmentName": "${oldModel.sender.signature}.png", "destSiteId": newModel.client.id, @@ -212,8 +211,8 @@ class DeviceTransferProvider extends ChangeNotifier { "receiverMachineStatusId": newModel.status?.id ?? "", "receiverComment": newModel.comment, "receiverWorkingHours": newModel.workingHours, - "receiverStartDate": newModel.startDate?.toIso8601String(), - "receiverEndDate": newModel.endDate?.toIso8601String(), + "receiverStartDate": newModel.timer?.startAt?.toIso8601String(), + "receiverEndDate": newModel.timer?.endAt?.toIso8601String(), "receiverTravelingHours": newModel.travelingHours, "receiverAttachmentName": "${newModel.signature}.png", }); @@ -247,5 +246,4 @@ class DeviceTransferProvider extends ChangeNotifier { return -1; } } - } diff --git a/lib/controllers/providers/api/devices_provider.dart b/lib/controllers/providers/api/devices_provider.dart index 4bede208..2d55a2a7 100644 --- a/lib/controllers/providers/api/devices_provider.dart +++ b/lib/controllers/providers/api/devices_provider.dart @@ -147,31 +147,31 @@ class DevicesProvider extends ChangeNotifier { } } - /// return -2 if request in progress - /// return -1 if error happen when sending request - /// return state code if request complete may be 200, 404 or 403 - /// for more details check http state manager - /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getDevicesListBySN({@required String host, @required User user, @required int hospitalId, @required String sn}) async { - Response response; - try { - response = await get( - Uri.parse(URLs.getEquipment + "?client=$hospitalId" + (sn == null || sn.isEmpty ? "" : "&serial_qr=$sn")), - ); - - _stateCode = response.statusCode; - List _page = []; - if (response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _page = categoriesListJson.map((device) => Device.fromJson(device)).toList(); - } - return _page; - } catch (error) { - _loading = false; - _stateCode = -1; - notifyListeners(); - return []; - } - } + // /// return -2 if request in progress + // /// return -1 if error happen when sending request + // /// return state code if request complete may be 200, 404 or 403 + // /// for more details check http state manager + // /// lib\controllers\http_status_manger\http_status_manger.dart + // Future> getDevicesListBySN({@required String host, @required User user, @required int hospitalId, @required String sn}) async { + // Response response; + // try { + // response = await get( + // Uri.parse(URLs.getEquipment + "?client=$hospitalId" + (sn == null || sn.isEmpty ? "" : "&serial_qr=$sn")), + // ); + // + // _stateCode = response.statusCode; + // List _page = []; + // if (response.statusCode >= 200 && response.statusCode < 300) { + // // client's request was successfully received + // List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + // _page = categoriesListJson.map((device) => Device.fromJson(device)).toList(); + // } + // return _page; + // } catch (error) { + // _loading = false; + // _stateCode = -1; + // notifyListeners(); + // return []; + // } + // } } diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index e2401668..faf84d66 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -158,6 +158,8 @@ class GasRefillProvider extends ChangeNotifier { "building": building?.toJson(includeFloors: false), "floor": floor?.toJson(includeDepartments: false), "department": department?.toJson(), + "engSignature": newModel.signatureEngineer, + "nurseSignature": newModel.signatureNurse, }; body["gazRefillDetails"] = newModel.details diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 9fb46d7c..edf5a749 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; @@ -235,6 +236,10 @@ class ServiceRequestsProvider extends ChangeNotifier { "voiceNote": request.audio, "assets": request.deviceId == null ? [] : [request.deviceId], "attachmentsCallRequest": request.devicePhotos?.map((e) => {"name": e})?.toList(), + "assignedEmployee": { + "id": request.engineerId, + "name": request.engineerName, + }, "callSiteContactPerson": [ { "id": callSiteContactPerson['id'] ?? 0, @@ -316,9 +321,9 @@ class ServiceRequestsProvider extends ChangeNotifier { "currentSituation": null, "repairLocation": report.repairLocation?.toMap(), "reason": report.reason?.toMap(), - "startofWorkTime": report.startDate?.toIso8601String() ?? "", - "endofWorkTime": report.endDate?.toIso8601String() ?? "", - "workingHours": ((report?.endDate?.difference(report?.startDate)?.inMinutes ?? 0) / 60), + "startofWorkTime": report.timer?.startAt?.toIso8601String() ?? "", + "endofWorkTime": report.timer?.endAt?.toIso8601String() ?? "", + "workingHours": report?.workingHours, "travelingHours": report.travelingHours, "travelingExpenses": report.travelingExpense ?? 0, if (report.faultDescription != null) "faultDescription": report.faultDescription.toJson(), @@ -395,12 +400,14 @@ class ServiceRequestsProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received Map listJson = json.decode(response.body)["data"]; + log(listJson?.toString()); callRequestForWorkOrder = CallRequestForWorkOrder.fromJson(listJson); } notifyListeners(); return callRequestForWorkOrder; } catch (error) { + print(error); return null; } } @@ -474,26 +481,27 @@ class ServiceRequestsProvider extends ChangeNotifier { // body["token"] = user.token; // body["job_id"] = request.id; // body["report_id"] = request.reportID; - try { - Map body = report.toMap(request); - // body["uid"] = user.id; - // body["token"] = user.token; - response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); - // response = await post( - // Uri.parse( - // host+URLs.updateServiceReport), - // body: body, - // ); - // stateCode = response.statusCode; + // try { + Map body = report.toMap(request); + // body["uid"] = user.id; + // body["token"] = user.token; + response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); + // response = await post( + // Uri.parse( + // host+URLs.updateServiceReport), + // body: body, + // ); + // stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - reset(); - notifyListeners(); - } - return response.statusCode; - } catch (error) { - return -1; + if (response.statusCode >= 200 && response.statusCode < 300) { + reset(); + notifyListeners(); } + return response.statusCode; + // } catch (error) { + // print(error); + // return -1; + // } } Future updateWorkOrderDetails({@required SearchWorkOrder workOrder}) async { @@ -619,6 +627,7 @@ class ServiceRequestsProvider extends ChangeNotifier { "pageNumber": ((workOrders?.length ?? 0) ~/ pageItemNumber) + 1, if (callerId?.isNotEmpty ?? false) "callId": callerId, if (search.assetType != null) "assetSerialNo": search.assetType?.name, + if (search.workOrderNo != null) "workOrderNo": search.workOrderNo, if (search.id != null) "workOrderNo": search.id?.toString(), if (search.calllastSituation != null) "callslastSituationWO": search.calllastSituation.toMap(), if (search.assignedEmployee != null) diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart index 1041a2a2..18720589 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart @@ -41,14 +41,14 @@ class ServiceReportMaintenanceSituationProvider extends ChangeNotifier { /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getOperators() async { + Future getOperators(String woId) async { if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; try { response = await ApiManager.instance.get( - "${URLs.getMaintenanceSituation}", + woId == null ? "${URLs.getMaintenanceSituation}" : "${URLs.getServiceReportLastCalls}?parentWOId=$woId&isAdd=true&id=${0}&typeTransaction='Nothing'", ); // response = await get( // Uri.parse( diff --git a/lib/models/call_request_for_work_order_model.dart b/lib/models/call_request_for_work_order_model.dart index 14572afa..188edce4 100644 --- a/lib/models/call_request_for_work_order_model.dart +++ b/lib/models/call_request_for_work_order_model.dart @@ -82,7 +82,7 @@ class Asset { Department department; String room; String testsDay; - String purchasingPrice; + num purchasingPrice; String nbv; String currency; String poNo; diff --git a/lib/models/device/device_transfer.dart b/lib/models/device/device_transfer.dart index a8202f42..c585a8c0 100644 --- a/lib/models/device/device_transfer.dart +++ b/lib/models/device/device_transfer.dart @@ -5,6 +5,8 @@ import 'package:test_sa/models/device/device_transfer_info.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/lookup.dart'; +import '../timer_model.dart'; + class DeviceTransfer { int id; String userId; @@ -46,21 +48,26 @@ class DeviceTransfer { title: parsedJson["transferCode"], userId: parsedJson["uid"], device: Device( - id: parsedJson["assetId"], - number: parsedJson["assetNumber"], - serialNumber: parsedJson["assetSerialNo"], - destBuildingName: parsedJson["destBuildingName"], - destDepartmentName: parsedJson["destDepartmentName"], - destFloor: parsedJson["destFloor"], - destRoom: parsedJson["destRoom"], - destSiteName: parsedJson["destSiteName"] - ), + id: parsedJson["assetId"], + number: parsedJson["assetNumber"], + serialNumber: parsedJson["assetSerialNo"], + destBuildingName: parsedJson["destBuildingName"], + destDepartmentName: parsedJson["destDepartmentName"], + destFloor: parsedJson["destFloor"], + destRoom: parsedJson["destRoom"], + destSiteName: parsedJson["destSiteName"]), sender: DeviceTransferInfo( travelingHours: parsedJson["senderTravelingHours"], comment: parsedJson["senderComment"], workingHours: parsedJson["senderWorkingHours"], - startDate: parsedJson["senderStartDate"]==null ? null:DateTime.parse(parsedJson["senderStartDate"]), - endDate: parsedJson["senderEndDate"]==null ? null:DateTime.parse(parsedJson["senderEndDate"]), + timer: TimerModel( + startAt: DateTime.tryParse(parsedJson["senderStartDate"] ?? ""), + endAt: DateTime.tryParse(parsedJson["senderEndDate"] ?? ""), + durationInSecond: ((parsedJson["workingHours"] ?? 0) * 60 * 60).toInt(), + stopped: parsedJson["workingHours"] == null ? null : true, + ), + // startDate: parsedJson["senderStartDate"] == null ? null : DateTime.parse(parsedJson["senderStartDate"]), + // endDate: parsedJson["senderEndDate"] == null ? null : DateTime.parse(parsedJson["senderEndDate"]), userId: parsedJson["senderAssignedEmployeeId"], userName: parsedJson["senderAssignedEmployeeName"], assignedEmployeeName: parsedJson["senderAssignedEmployeeName"], @@ -80,8 +87,11 @@ class DeviceTransfer { travelingHours: parsedJson["receiverTravelingHours"], comment: parsedJson["receiverComment"], workingHours: parsedJson["receiverWorkingHours"], - startDate: parsedJson["receiverStartDate"]==null ? null:DateTime.parse(parsedJson["receiverStartDate"]), - endDate: parsedJson["receiverEndDate"]==null ? null:DateTime.parse(parsedJson["receiverEndDate"]), + timer: parsedJson["receiverStartDate"] != null || parsedJson["receiverEndDate"] != null + ? TimerModel(startAt: DateTime.tryParse(parsedJson["receiverStartDate"] ?? ""), endAt: DateTime.tryParse(parsedJson["receiverEndDate"] ?? "")) + : null, + // startDate: parsedJson["receiverStartDate"] == null ? null : DateTime.parse(parsedJson["receiverStartDate"]), + // endDate: parsedJson["receiverEndDate"] == null ? null : DateTime.parse(parsedJson["receiverEndDate"]), userId: parsedJson["receiverAssignedEmployeeId"], userName: parsedJson["receiverAssignedEmployeeName"], assignedEmployeeName: parsedJson["receiverAssignedEmployeeName"], diff --git a/lib/models/device/device_transfer_info.dart b/lib/models/device/device_transfer_info.dart index 41d0843a..00e1d387 100644 --- a/lib/models/device/device_transfer_info.dart +++ b/lib/models/device/device_transfer_info.dart @@ -2,19 +2,22 @@ import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/lookup.dart'; +import '../timer_model.dart'; + class DeviceTransferInfo { String userId; String comment; Hospital client; Department department; String workingHours; - DateTime startDate; - DateTime endDate; + // DateTime startDate; + // DateTime endDate; String travelingHours; String userName; String signature; String assignedEmployeeName; Lookup status; + TimerModel timer; DeviceTransferInfo({ this.userId, @@ -23,12 +26,13 @@ class DeviceTransferInfo { this.client, this.userName, this.travelingHours, - this.startDate, - this.endDate, + // this.startDate, + // this.endDate, this.workingHours, this.signature, this.status, - this.assignedEmployeeName + this.assignedEmployeeName, + this.timer, }); Map toJson(bool isSender) { @@ -37,8 +41,10 @@ class DeviceTransferInfo { if (comment != null && comment.isNotEmpty) body["${baseKey}comment"] = comment; if (workingHours != null && workingHours.isNotEmpty) body["${baseKey}working_hours"] = workingHours; - if (startDate != null) body["${baseKey}start_date"] = startDate?.toIso8601String(); - if (endDate != null) body["${baseKey}end_date"] = endDate?.toIso8601String(); + // if (startDate != null) body["${baseKey}start_date"] = startDate?.toIso8601String(); + // if (endDate != null) body["${baseKey}end_date"] = endDate?.toIso8601String(); + if (timer?.startAt != null) body["${baseKey}start_date"] = timer?.startAt?.toIso8601String(); + if (timer?.endAt != null) body["${baseKey}end_date"] = timer?.endAt?.toIso8601String(); if (travelingHours != null && travelingHours.isNotEmpty) body["${baseKey}travel_hours"] = travelingHours; if (status != null) body["${baseKey}status"] = status.id.toString(); if (signature != null && signature.isNotEmpty) body["${baseKey}image"] = signature; @@ -57,8 +63,9 @@ class DeviceTransferInfo { client = Hospital.fromHospital(old.client); department = Department.fromDepartment(old.department); workingHours = old.workingHours; - startDate = old.startDate; - endDate = old.endDate; + // startDate = old.startDate; + // endDate = old.endDate; + timer = old.timer; travelingHours = old.travelingHours; comment = old.comment; if (withSignature) signature = old.signature; @@ -68,14 +75,20 @@ class DeviceTransferInfo { factory DeviceTransferInfo.fromJson(Map parsedJson, String key) { return DeviceTransferInfo( workingHours: parsedJson["${key}working_hours"], - startDate: parsedJson["${key}start_date"], - endDate: parsedJson["${key}end_date"], + // startDate: parsedJson["${key}start_date"], + // endDate: parsedJson["${key}end_date"], + timer: TimerModel( + startAt: DateTime.tryParse(parsedJson["${key}start_date"] ?? ""), + endAt: DateTime.tryParse(parsedJson["${key}end_date"] ?? ""), + durationInSecond: ((parsedJson["${key}working_hours"] ?? 0) * 60 * 60).toInt(), + stopped: parsedJson["${key}working_hours"] == null || (parsedJson["${key}working_hours"] as String).isEmpty ? null : true, + ), travelingHours: parsedJson["${key}travel_hours"], userName: parsedJson["${key}name"], signature: parsedJson["${key}image"], userId: parsedJson["${key}id"], comment: parsedJson["${key}comment"], - assignedEmployeeName:parsedJson["${key}AssignedEmployeeName"], + assignedEmployeeName: parsedJson["${key}AssignedEmployeeName"], client: Hospital(id: parsedJson["${key}SiteId"], name: parsedJson["${key}SiteName"]), department: Department( id: parsedJson["${key}DepartmentId"], diff --git a/lib/models/gas_refill/gas_refill_model.dart b/lib/models/gas_refill/gas_refill_model.dart index 13a6e6b8..291ee5ad 100644 --- a/lib/models/gas_refill/gas_refill_model.dart +++ b/lib/models/gas_refill/gas_refill_model.dart @@ -1,6 +1,9 @@ +import 'dart:typed_data'; + import 'package:test_sa/models/gas_refill/gas_refill_details.dart'; import 'package:test_sa/models/lookup.dart'; +import '../../controllers/api_routes/urls.dart'; import '../call_request_for_work_order_model.dart'; class GasRefillModel { @@ -14,6 +17,10 @@ class GasRefillModel { Department department; List details; AssignedEmployee assignedEmployee; + String signatureNurse; + String signatureEngineer; + Uint8List localNurseSignature; + Uint8List localEngineerSignature; DateTime startDate, endDate, expectedDate; GasRefillModel({ @@ -30,6 +37,10 @@ class GasRefillModel { this.expectedDate, this.department, this.assignedEmployee, + this.signatureNurse, + this.signatureEngineer, + this.localEngineerSignature, + this.localNurseSignature, }); bool validate() { @@ -58,6 +69,10 @@ class GasRefillModel { endDate = model.endDate; expectedDate = model.expectedDate; assignedEmployee = model.assignedEmployee; + localEngineerSignature = model.localEngineerSignature; + localNurseSignature = model.localNurseSignature; + signatureEngineer = model.signatureEngineer; + signatureNurse = model.signatureNurse; } factory GasRefillModel.fromJson(Map parsedJson) { @@ -80,6 +95,8 @@ class GasRefillModel { endDate: DateTime.tryParse(parsedJson['endDate'] ?? ""), expectedDate: DateTime.tryParse(parsedJson['expectedDate'] ?? ""), assignedEmployee: AssignedEmployee.fromJson(parsedJson['assignedEmployee'] ?? {}), + signatureEngineer: URLs.getFileUrl(parsedJson["engSignature"]), + signatureNurse: URLs.getFileUrl(parsedJson["nurseSignature"]), ); } } diff --git a/lib/models/pantry/pentry.dart b/lib/models/pantry/pentry.dart index 82ef9fd6..40a9034e 100644 --- a/lib/models/pantry/pentry.dart +++ b/lib/models/pantry/pentry.dart @@ -58,7 +58,7 @@ class Pentry { Map toMap(int visitId) { Map map = {}; map["visitStatusId"] = ppmVisitStatus?.id.toString(); - //if(status != null) map["visitStatusId"] = status?.id.toString(); + if (status != null) map["deviceStatusId"] = status?.id.toString(); if (travelingHours != null) map["travelingHours"] = travelingHours; //if(imageFile != null) map["file_attachement"] = base64Encode(imageFile.readAsBytesSync()); map["actualDate"] = actualVisitDate.toIso8601String(); @@ -73,7 +73,7 @@ class Pentry { {"attachmentName": (imageFile.path.split("/").last + base64Encode(imageFile.readAsBytesSync()))} ]; } - + map["travelingHours"] = travelingHours; // if(contacts?.isNotEmpty == true) { // for(int i = 0;i toMap(ServiceRequest request) { Map _map = {}; if (id != null) _map["id"] = id; if (visitDate != null) _map["visitDate"] = visitDate.toIso8601String(); //if(serviceType != null) _map["service_type"] = serviceType.id.toString(); - if (equipmentStatus != null) _map["status"] = equipmentStatus?.toMap(); + if (equipmentStatus != null) _map["equipmentStatus"] = equipmentStatus?.toMap(); if (type != null) _map["typeOfWO"] = type?.toMap(); if (assetType != null) _map["TypeOfWO"] = assetType?.toMap(); //if(faultDescriptionId != null && faultDescriptionId.isNotEmpty) _map["fault_description"] = faultDescriptionId; @@ -93,17 +97,19 @@ class ServiceReport { _map["endofWorkTime"] = (timer.endAt ?? DateTime.now()).toIso8601String(); _map["workingHours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); } - if (travelingHours != null && travelingHours.toString().isNotEmpty) _map["traveling_hours"] = travelingHours; + if (travelingHours != null && travelingHours.toString().isNotEmpty) _map["travelingHours"] = travelingHours; // if(workPreformed != null && workPreformed.isNotEmpty){ // _map["faultDescription"] = { - // //"id":faultDescriptionId ?? 0, + // "id":faultDescriptionId ?? 0, // "workPerformed":workPreformed // }; // } - if (travelingHours != null) _map["traveling_hours"] = travelingHours; - if (workPreformed != null && workPreformed.isNotEmpty) { - _map["faultDescription"] = faultDescription.toJson(); - } + _map["faultDescription"] = {"id": faultDescription?.id ?? 0, "workPerformed": faultDescription?.workPerformed}; + if (travelingHours != null) _map["travelingHours"] = travelingHours; + // if (workingHours != null) _map["workingHours"] = workingHours; + // if (workPreformed != null && workPreformed.isNotEmpty) { + // _map["faultDescription"] = faultDescription.toJson(); + // } if (jobSheetNumber != null && jobSheetNumber.isNotEmpty) _map["job_sheet_no"] = jobSheetNumber; if (parts != null && parts.isNotEmpty) { _map["sparePartsWorkOrders"] = parts.map((e) => e.toJson()).toList(); @@ -122,6 +128,7 @@ class ServiceReport { if (reason != null) _map["reason"] = reason.toMap(); //if(operatingHours != null && operatingHours.isNotEmpty) _map["operation_hours"] = operatingHours; if (callLastSituation != null) _map["calllastSituation"] = callLastSituation.toMap(); + if (currentSituation != null) _map["currentSituation"] = currentSituation.toMap(); //if(image != null) _map["image"] = image; //if(invoiceCode != null) _map["invoice_no"] = invoiceCode; //if(invoiceNumber != null) _map["invoice_code"] = invoiceNumber; @@ -133,16 +140,27 @@ class ServiceReport { _map["nurseSignature"] = signatureNurse; _map["engSignature"] = signatureEngineer; _map["comment"] = comment; - _map["travelingExpense"] = travelingExpense; - _map["startofWorkTime"] = startDate; - _map["endofWorkTime"] = endDate; - _map["workingHours"] = endDate?.difference(startDate)?.inHours ?? 0; + _map["travelingExpenses"] = travelingExpense; + // _map["startofWorkTime"] = startDate.toIso8601String(); + // _map["endofWorkTime"] = endDate.toIso8601String(); + // _map["workingHours"] = endDate?.difference(startDate)?.inHours ?? 0; + if (timer?.startAt != null) _map["startofWorkTime"] = timer?.startAt?.toIso8601String(); + if (timer?.endAt != null) _map["endofWorkTime"] = timer?.endAt?.toIso8601String(); + _map["workingHours"] = workingHours; _map["reviewComment"] = reviewComment; return _map; } - bool validate() { - if (visitDate == null) return false; + Future validate() async { + print("visitDate:$visitDate"); + print("equipmentStatus:${equipmentStatus?.toMap()}"); + print("callLastSituation:${callLastSituation?.toMap()}"); + print("parts:$parts"); + print("reason:${reason?.toMap()}"); + if (visitDate == null) { + await Fluttertoast.showToast(msg: "Visit Date Required"); + return false; + } //if(serviceType == null) return false; if (equipmentStatus == null) return false; //if (type == null && assetType == null) return false; @@ -174,27 +192,38 @@ class ServiceReport { id: id, assetType: Lookup.fromJson(parsedJson["assetType"]), callLastSituation: Lookup.fromJson(parsedJson["calllastSituation"]), + currentSituation: Lookup.fromJson(parsedJson["currentSituation"]), + repairLocation: Lookup.fromJson(parsedJson["repairLocation"]), reason: Lookup.fromJson(parsedJson["reason"]), - equipmentStatus: Lookup.fromJson(parsedJson["status"]), + equipmentStatus: Lookup.fromJson(parsedJson["equipmentStatus"]), type: Lookup.fromJson(parsedJson["typeOfWO"]), - faultDescriptionId: parsedJson["fault_description"], - endDate: DateTime.tryParse(parsedJson["endofWorkTime"]), + faultDescription: parsedJson['faultDescription'] != null ? FaultDescription.fromJson(parsedJson['faultDescription']) : null, + + // faultDescription: parsedJson["faultDescription"], + // startDate: DateTime.tryParse(parsedJson["startofWorkTime"] ?? ""), + // endDate: DateTime.tryParse(parsedJson["endofWorkTime"] ?? ""), //invoiceCode: parsedJson["invoice_code"], //invoiceNumber: parsedJson["invoice_no"], //jobSheetNumber: parsedJson["job_sheet_no"], - operatingHours: parsedJson["workingHours"], + // workingHours: parsedJson["workingHours"], engineer: Engineer.fromJson(parsedJson["assignedEmployee"]), parts: _parts, //quantity: parsedJson["nid"], - travelingHours: parsedJson["traveling_hours"], + travelingHours: parsedJson["travelingHours"], + travelingExpense: parsedJson["travelingExpenses"], visitDate: DateTime.tryParse(parsedJson["visitDate"]), - //workHours: parsedJson["working_hours"], + workingHours: parsedJson["workingHours"], timer: TimerModel( - startAt: DateTime.tryParse(parsedJson["startofWorkTime"]), endAt: DateTime.tryParse(parsedJson["endofWorkTime"]), durationInSecond: ((parsedJson["workingHours"] ?? 0) * 60 * 60).toInt()), + startAt: DateTime.tryParse(parsedJson["startofWorkTime"] ?? ""), + endAt: DateTime.tryParse(parsedJson["endofWorkTime"] ?? ""), + durationInSecond: ((parsedJson["workingHours"] ?? 0) * 60 * 60).toInt(), + stopped: parsedJson["workingHours"] == null ? null : true, + ), //workPreformed: parsedJson["work_performed"], device: Device.fromJson(parsedJson["callRequest"]["asset"]), signatureNurse: URLs.getFileUrl(parsedJson["nurseSignature"]), signatureEngineer: URLs.getFileUrl(parsedJson["engSignature"]), + comment: parsedJson['comment'], reviewComment: parsedJson['reviewComment'], ); } diff --git a/lib/models/service_request/search_work_order.dart b/lib/models/service_request/search_work_order.dart index 735fedd4..898fa0e9 100644 --- a/lib/models/service_request/search_work_order.dart +++ b/lib/models/service_request/search_work_order.dart @@ -1,4 +1,5 @@ import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/timer_model.dart'; import '../fault_description.dart'; @@ -21,8 +22,8 @@ class SearchWorkOrder { this.currentSituation, this.repairLocation, this.reason, - this.startofWorkTime, - this.endofWorkTime, + // this.startofWorkTime, + // this.endofWorkTime, this.workingHours, this.travelingHours, this.travelingExpenses, @@ -36,6 +37,7 @@ class SearchWorkOrder { this.engSignature, this.nurseSignature, this.woParentDto, + this.timer, }); SearchWorkOrder.fromJson(dynamic json) { @@ -66,8 +68,13 @@ class SearchWorkOrder { currentSituation = json['currentSituation'] != null ? Lookup.fromJson(json['currentSituation']) : null; repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; reason = json['reason'] != null ? Lookup.fromJson(json['reason']) : null; - startofWorkTime = json['startofWorkTime']; - endofWorkTime = json['endofWorkTime']; + // startofWorkTime = json['startofWorkTime']; + // endofWorkTime = json['endofWorkTime']; + if (json['startofWorkTime'] != null || json['endofWorkTime'] != null) { + timer = TimerModel(); + } + if (json['startofWorkTime'] != null) timer.startAt = DateTime.tryParse(json['startofWorkTime']); + if (json['endofWorkTime'] != null) timer.endAt = DateTime.tryParse(json['endofWorkTime']); workingHours = json['workingHours']; travelingHours = json['travelingHours']; travelingExpenses = json['travelingExpenses']; @@ -104,29 +111,36 @@ class SearchWorkOrder { workOrderYear = wo.workOrderYear ?? workOrderYear; workOrderSequennce = wo.workOrderSequennce ?? workOrderSequennce; callRequest = wo.callRequest ?? callRequest; - assetType = wo.assetType ?? assetType; - assignedEmployee = wo.assignedEmployee ?? assignedEmployee; + if (wo.assetType != null) assetType = Lookup.fromJson((wo.assetType)?.toMap() ?? {}); + if (wo.assignedEmployee != null) assignedEmployee = AssignedEmployee.fromJson((wo.assignedEmployee)?.toJson() ?? {}); visitDate = wo.visitDate ?? visitDate; - assistantEmployees = wo.assistantEmployees ?? assistantEmployees; - supplier = wo.supplier ?? supplier; + assistantEmployees = (wo.assistantEmployees ?? assistantEmployees) + ?.map((e) => AssistantEmployees.fromJson({ + "id": e?.id, + "user": {"name": e?.user?.name, "id": (e?.user?.id) ?? "0"} + })) + ?.toList() ?? + []; + if (wo.supplier != null) supplier = SupplierModel.fromJson((wo.supplier)?.toJson() ?? {}); vendorTicketNumber = wo.vendorTicketNumber ?? vendorTicketNumber; - contactPersonWorkOrders = wo.contactPersonWorkOrders ?? contactPersonWorkOrders; - calllastSituation = wo.calllastSituation ?? calllastSituation; - currentSituation = wo.currentSituation ?? currentSituation; - repairLocation = wo.repairLocation ?? repairLocation; - reason = wo.reason ?? reason; - startofWorkTime = wo.startofWorkTime ?? startofWorkTime; - endofWorkTime = wo.endofWorkTime ?? endofWorkTime; + contactPersonWorkOrders = (wo.contactPersonWorkOrders ?? contactPersonWorkOrders)?.map((e) => ContactPersonWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + calllastSituation = Lookup.fromJson((wo.calllastSituation ?? calllastSituation)?.toMap() ?? {}); + if (wo.currentSituation != null) currentSituation = Lookup.fromJson((wo.currentSituation)?.toMap() ?? {}); + repairLocation = Lookup.fromJson((wo.repairLocation ?? repairLocation)?.toMap() ?? {}); + reason = Lookup.fromJson((wo.reason ?? reason)?.toMap() ?? {}); + // startofWorkTime = wo.startofWorkTime ?? startofWorkTime; + // endofWorkTime = wo.endofWorkTime ?? endofWorkTime; + timer = wo.timer ?? timer; workingHours = wo.workingHours ?? workingHours; travelingHours = wo.travelingHours ?? travelingHours; travelingExpenses = wo.travelingExpenses ?? travelingExpenses; - faultDescription = wo.faultDescription ?? faultDescription; - sparePartsWorkOrders = wo.sparePartsWorkOrders ?? sparePartsWorkOrders; + faultDescription = FaultDescription.fromJson((wo.faultDescription ?? faultDescription)?.toJson() ?? {}); + sparePartsWorkOrders = (wo.sparePartsWorkOrders ?? sparePartsWorkOrders)?.map((e) => SparePartsWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; reviewComment = wo.reviewComment ?? reviewComment; comment = wo.comment ?? comment; - attachmentsWorkOrder = wo.attachmentsWorkOrder ?? attachmentsWorkOrder; - equipmentStatus = wo.equipmentStatus ?? equipmentStatus; - suppEngineerWorkOrders = wo.suppEngineerWorkOrders ?? suppEngineerWorkOrders; + attachmentsWorkOrder = (wo.attachmentsWorkOrder ?? attachmentsWorkOrder)?.map((e) => AttachmentsWorkOrder.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + equipmentStatus = Lookup.fromJson((wo.equipmentStatus ?? equipmentStatus)?.toMap() ?? {}); + suppEngineerWorkOrders = (wo.suppEngineerWorkOrders ?? suppEngineerWorkOrders)?.map((e) => SuppEngineerWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; engSignature = wo.engSignature ?? engSignature; nurseSignature = wo.nurseSignature ?? nurseSignature; woParentDto = wo.woParentDto ?? woParentDto; @@ -149,8 +163,8 @@ class SearchWorkOrder { Lookup currentSituation; Lookup repairLocation; Lookup reason; - String startofWorkTime; - String endofWorkTime; + // String startofWorkTime; + // String endofWorkTime; num workingHours; num travelingHours; num travelingExpenses; @@ -164,6 +178,8 @@ class SearchWorkOrder { String engSignature; String nurseSignature; WoParentDto woParentDto; + TimerModel timer; + SearchWorkOrder copyWith({ num id, num parentWOId, @@ -182,8 +198,8 @@ class SearchWorkOrder { Lookup currentSituation, Lookup repairLocation, Lookup reason, - String startofWorkTime, - String endofWorkTime, + // String startofWorkTime, + // String endofWorkTime, num workingHours, num travelingHours, num travelingExpenses, @@ -197,6 +213,7 @@ class SearchWorkOrder { String engSignature, String nurseSignature, WoParentDto woParentDto, + TimerModel timer, }) => SearchWorkOrder( id: id ?? this.id, @@ -216,8 +233,8 @@ class SearchWorkOrder { currentSituation: currentSituation ?? this.currentSituation, repairLocation: repairLocation ?? this.repairLocation, reason: reason ?? this.reason, - startofWorkTime: startofWorkTime ?? this.startofWorkTime, - endofWorkTime: endofWorkTime ?? this.endofWorkTime, + // startofWorkTime: startofWorkTime ?? this.startofWorkTime, + // endofWorkTime: endofWorkTime ?? this.endofWorkTime, workingHours: workingHours ?? this.workingHours, travelingHours: travelingHours ?? this.travelingHours, travelingExpenses: travelingExpenses ?? this.travelingExpenses, @@ -231,6 +248,7 @@ class SearchWorkOrder { engSignature: engSignature ?? this.engSignature, nurseSignature: nurseSignature ?? this.nurseSignature, woParentDto: woParentDto ?? this.woParentDto, + timer: timer ?? this.timer, ); Map toJson() { final map = {}; @@ -262,21 +280,22 @@ class SearchWorkOrder { if (calllastSituation != null) { map['calllastSituation'] = calllastSituation.toMap(); } - if (currentSituation != null) { - map['currentSituation'] = currentSituation.toMap(); - } - if (repairLocation != null) { + map['currentSituation'] = currentSituation?.toMap(); + if (repairLocation?.id != null) { map['repairLocation'] = repairLocation.toMap(); } if (reason != null) { map['reason'] = reason.toMap(); } - map['startofWorkTime'] = startofWorkTime; - map['endofWorkTime'] = endofWorkTime; + // map['startofWorkTime'] = startofWorkTime; + // map['endofWorkTime'] = endofWorkTime; + map['startofWorkTime'] = timer?.startAt?.toIso8601String(); + map['endofWorkTime'] = timer?.endAt?.toIso8601String(); map['workingHours'] = workingHours; map['travelingHours'] = travelingHours; map['travelingExpenses'] = travelingExpenses; - if (faultDescription != null) { + + if (faultDescription?.id != null) { map['faultDescription'] = faultDescription.toJson(); } if (sparePartsWorkOrders != null) { @@ -1722,11 +1741,8 @@ class Asset { if (modelDefinition != null) { map['modelDefinition'] = modelDefinition.toJson(); } - if (supplier != null) { - map['supplier'] = supplier.toJson(); - } else { - map['supplier'] = []; - } + map['supplier'] = supplier?.toJson(); + map['ipAddress'] = ipAddress; map['macAddress'] = macAddress; map['portNumber'] = portNumber; @@ -1742,11 +1758,12 @@ class Asset { if (parentAsset != null) { map['parentAsset'] = parentAsset.toJson(); } - if (assetType != null) { - map['assetType'] = assetType.toMap(); - } else { - map['assetType'] = []; - } + + map['assetType'] = assetType?.toMap(); + print("supplier : ${supplier?.toJson()}"); + print("supplier 2 : ${map['supplier']}"); + print("asset type : ${assetType?.toMap()}"); + print("asset type 2: ${map['assetType']}"); if (site != null) { map['site'] = site.toJson(); } diff --git a/lib/models/service_request/service_request.dart b/lib/models/service_request/service_request.dart index a884da62..58fc2808 100644 --- a/lib/models/service_request/service_request.dart +++ b/lib/models/service_request/service_request.dart @@ -15,6 +15,7 @@ class ServiceRequest { int hospitalId; String departmentName; String engineerName; + String engineerId; String date; String audio; int statusValue; @@ -57,6 +58,7 @@ class ServiceRequest { this.deviceId, this.audio, this.engineerName, + this.engineerId, this.viewReport = false, this.deviceModel, this.engineerMobile, @@ -102,6 +104,7 @@ class ServiceRequest { statusValue: parsedJson["status"] == null ? null : parsedJson["status"]["value"], departmentName: parsedJson["asset"]["department"] != null ? parsedJson["asset"]["department"]["name"] : "", engineerName: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["name"], + engineerId: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["id"], hospitalId: parsedJson["asset"]["site"]["id"], reportID: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workOrderId"] : null, viewReport: parsedJson["workOrder"] != null, diff --git a/lib/models/timer_model.dart b/lib/models/timer_model.dart index c6434f93..907d006d 100644 --- a/lib/models/timer_model.dart +++ b/lib/models/timer_model.dart @@ -2,6 +2,7 @@ class TimerModel { DateTime startAt; DateTime endAt; int durationInSecond; + bool stopped; - TimerModel({this.startAt, this.endAt, this.durationInSecond}); + TimerModel({this.startAt, this.endAt, this.durationInSecond, this.stopped}); } diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index b7726ff6..74ff48e7 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -86,11 +86,15 @@ class _DeviceTransferDetailsState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ RequestInfoRow( - title: _subtitle.title, + title: "Id", + info: widget.model.id?.toString(), + ), + RequestInfoRow( + title: _subtitle.assetName, info: widget.model.title, ), RequestInfoRow( - title: _subtitle.device, + title: _subtitle.assetSN, info: widget.model.device.serialNumber, ), RequestInfoRow( diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 9b2c8033..061b5d21 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -19,8 +19,7 @@ import 'package:test_sa/views/widgets/status/gas_refill/gas_status.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import '../../../../controllers/localization/localization.dart'; -import '../../../controllers/validator/validator.dart'; -import '../../widgets/date_and_time/time_picker.dart'; +import '../../widgets/timer/app_timer.dart'; class UpdateDeviceTransfer extends StatefulWidget { final DeviceTransfer model; @@ -46,6 +45,13 @@ class _UpdateDeviceTransferState extends State { final GlobalKey _scaffoldKey = GlobalKey(); _update() async { + if (_formModel?.workingHours == null || _formModel.workingHours.isEmpty) { + await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started"); + return; + } else if ((_formModel?.timer?.stopped ?? false) == false) { + await Fluttertoast.showToast(msg: "Stop The Timer"); + return; + } _validate = true; if (!_formKey.currentState.validate()) { setState(() {}); @@ -152,96 +158,23 @@ class _UpdateDeviceTransferState extends State { const SizedBox( height: 16, ), + ASubTitle(_subtitle.workingHours), + const SizedBox(height: 8), Row( children: [ Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("Start of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _formModel.startDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _formModel.startDate = date; - _formModel.workingHours = ((_formModel.endDate?.difference(_formModel.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? 0; - setState(() {}); - }, - ), - ], - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("End of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _formModel.endDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _formModel.endDate = date; - _formModel.workingHours = ((_formModel.endDate?.difference(_formModel.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? 0; - setState(() {}); - }, - ), - ], + child: AppTimer( + timer: _formModel.timer, + onChange: (timer) async { + _formModel.timer = timer; + _formModel.workingHours = (((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"; + return true; + }, ), ), ], ), - const SizedBox(height: 4), - ASubTitle(_subtitle.workingHours), - const SizedBox(height: 4), - ATextFormField( - initialValue: null, - textAlign: TextAlign.center, - hintText: _formModel.startDate == null ? "0" : ((_formModel.endDate?.difference(_formModel.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", - enable: false, - style: Theme.of(context).textTheme.subtitle1, - //validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - // _serviceReport.workHours = value; - }, - ), - // ASubTitle(_subtitle.workingHours), - // const SizedBox( - // height: 4, - // ), - // ATextFormField( - // initialValue: _formModel?.workingHours, - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.number, - // onSaved: (value) { - // _formModel.workingHours = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("Sender Department"), - // if(_validate && _formModel.senderDepartment == null) - // ASubTitle(_subtitle.requiredWord,color: Colors.red,), - // const SizedBox(height: 4,), - // DepartmentButton( - // department: _formModel.senderDepartment, - // onDepartmentPick: (department){ - // _formModel.senderDepartment = department; - // setState(() {}); - // }, - // ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 16), ASubTitle(_subtitle.status), const SizedBox( height: 4, @@ -249,6 +182,7 @@ class _UpdateDeviceTransferState extends State { GasStatusMenu( initialValue: _formModel.status, onSelect: (status) { + if (status == null) return; _formModel.status = status; setState(() {}); }, diff --git a/lib/views/pages/login.dart b/lib/views/pages/login.dart index 65585b85..e77b67da 100644 --- a/lib/views/pages/login.dart +++ b/lib/views/pages/login.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.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/localization/localization.dart'; @@ -114,9 +115,16 @@ class _LoginState extends State { host: _settingProvider.host, ); if (status >= 200 && status < 300) { - _settingProvider.setUser(_userProvider.user); + if(_userProvider.user.isAuthenticated ?? false) { + _settingProvider.setUser(_userProvider.user); + Navigator.of(context).pushNamed(LandPage.id); + } else { + Fluttertoast.showToast(msg: _userProvider.user.message); + } + + // if (_userProvider.user.isActive) - Navigator.of(context).pushNamed(LandPage.id); + // else // Fluttertoast.showToast(msg: _subtitle.activationAlert); } else { diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart index 79fcbef0..fdfd67e5 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -6,6 +6,9 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; @@ -13,16 +16,18 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart'; import 'package:test_sa/views/pages/sub_workorder/work_order_details_bottom_sheet.dart'; import 'package:test_sa/views/pages/sub_workorder/workorder_details.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; +import 'package:test_sa/views/widgets/status/service_request/service_request_defect_types_mune.dart'; import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart'; import '../../../models/subtitle.dart'; import '../../widgets/app_text_form_field.dart'; import '../../widgets/buttons/app_back_button.dart'; import '../../widgets/buttons/app_button.dart'; import '../../widgets/date_and_time/date_picker.dart'; import '../../widgets/images/mini_one_image_picker.dart'; -import '../../widgets/status/report/service_report_equipment_status.dart'; import '../../widgets/status/report/service_report_fault_description.dart'; import '../../widgets/status/report/service_report_reasons.dart'; import '../../widgets/titles/app_sub_title.dart'; @@ -30,6 +35,7 @@ import '../../widgets/titles/app_sub_title.dart'; class CreateSubWorkOrderPage extends StatefulWidget { static const id = "/CreateSubWorkOrder"; final SearchWorkOrder workOrder; + const CreateSubWorkOrderPage({this.workOrder, Key key}) : super(key: key); @override @@ -47,274 +53,302 @@ class _CreateSubWorkOrderPageState extends State { @override void initState() { - _subWorkOrders = SearchWorkOrder(assignedEmployee: widget.workOrder.assignedEmployee, callRequest: CallRequest()); + _subWorkOrders = SearchWorkOrder( + assignedEmployee: widget?.workOrder?.callRequest?.assignedEmployee, + callRequest: CallRequest(id: widget?.workOrder?.callRequest?.id), + currentSituation: null, + supplier: null, + ); _serviceReport = ServiceReport(id: widget.workOrder.id, type: widget.workOrder.assetType, equipmentStatus: widget.workOrder.equipmentStatus); + _isLoading = true; super.initState(); } + var assetTypesProvider; + CallRequestForWorkOrder _callRequestForWorkOrder; + + Future getAssetType() async { + //if (assetTypesProvider == null) { + Provider.of(context, listen: false).reset(); + assetTypesProvider = Provider.of(context, listen: false); + _callRequestForWorkOrder = await Provider.of(context).getCallRequestForWorkOrder(callId: widget.workOrder.callRequest.id.toString()); + await assetTypesProvider.getTypes(); + _subWorkOrders?.assetType = assetTypesProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder?.assetType, + orElse: () => null, + ); + setState(() { + _isLoading = false; + }); + //} + } + @override Widget build(BuildContext context) { + if (_callRequestForWorkOrder == null) { + getAssetType(); + } final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Scaffold( body: SafeArea( - child: SingleChildScrollView( - child: Form( - key: _formKey, - child: Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Column( - children: [ - Row( - children: [ - const ABackButton(), - Expanded( - child: Center( - child: Text( - "New Work Order", - style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - const SizedBox( - width: 48, - ) - ], - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), - child: Column( - children: [ - WorkOrderDetails( - item: widget.workOrder, - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Equipment status"), - if (_validate && _subWorkOrders?.equipmentStatus == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ServiceReportEquipmentStatusMenu( - report: _serviceReport, - onSelect: (status) { - _subWorkOrders.equipmentStatus = status; - _serviceReport.equipmentStatus = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Return to Service"), - if (_validate && _subWorkOrders.visitDate == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: ADatePicker( - date: DateTime.tryParse(_subWorkOrders.visitDate ?? ""), - from: DateTime(1950), - onDatePicker: (date) { - _subWorkOrders.visitDate = date?.toIso8601String(); - setState(() {}); - }, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: _isLoading + ? const ALoading() + : Column( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( children: [ - ASubTitle("Failure ${subtitle.reasons}"), - if (_validate && _subWorkOrders.reason == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ServiceReportReasonsMenu( - initialValue: _serviceReportReason, - onSelect: (status) { - _serviceReportReason = status; - _subWorkOrders.reason = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(subtitle.faultDescription), - if (_validate && _subWorkOrders.faultDescription == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ServiceReportFaultDescription( - requestId: widget.workOrder?.id?.toString(), - initialValue: _subWorkOrders.faultDescription, - onSelect: (status) { - _subWorkOrders.faultDescription = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Solution"), - const SizedBox( - height: 4, - ), - ATextFormField(labelText: _subWorkOrders.faultDescription?.workPerformed ?? "", textInputType: TextInputType.multiline, enable: false), - ], - ), - const SizedBox(height: 8), - InkWell( - onTap: () async { - await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => WorkOrderDetailsBottomSheet(subWorkOrder: _subWorkOrders), - ); - log(_subWorkOrders?.toJson()?.toString()); - }, - child: Card( - child: ListTile( - title: Row( + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( children: [ - Text( - "WO Details", - style: Theme.of(context).textTheme.bodyMedium, + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "New Work Order", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox( + width: 48, + ) + ], ), - const Text("*", style: TextStyle(color: Colors.red)), ], ), - trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), ), - ), - ), - const SizedBox(height: 8), - InkWell( - onTap: () async { - await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => SparePartsBottomSheet(subWorkOrder: _subWorkOrders), - ); - log(_subWorkOrders?.toJson()?.toString()); - }, - child: Card( - child: ListTile( - title: Row( + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: Column( children: [ - Text( - "Spare Parts", - style: Theme.of(context).textTheme.bodyMedium, + WorkOrderDetails(item: widget.workOrder, assetType: _subWorkOrders?.assetType), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Equipment status"), + if (_validate && _subWorkOrders?.equipmentStatus == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceRequestDefectTypesMenu( + initialValue: _serviceReport.equipmentStatus, + onSelect: (status) { + _subWorkOrders.equipmentStatus = status; + _serviceReport.equipmentStatus = status; + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Return to Service"), + if (_validate && _subWorkOrders.visitDate == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + Row( + children: [ + Expanded( + child: ADatePicker( + date: DateTime.tryParse(_subWorkOrders.visitDate ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _subWorkOrders.visitDate = date?.toIso8601String(); + setState(() {}); + }, + ), + ), + ], + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Failure ${subtitle.reasons}"), + if (_validate && _subWorkOrders.reason == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportReasonsMenu( + initialValue: _serviceReportReason, + onSelect: (status) { + _serviceReportReason = status; + _subWorkOrders.reason = status; + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.faultDescription), + if (_validate && _subWorkOrders.faultDescription == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportFaultDescription( + requestId: widget.workOrder?.callRequest?.id?.toString(), + initialValue: _subWorkOrders?.faultDescription, + onSelect: (status) { + _subWorkOrders.faultDescription = status; + if (mounted) setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Solution"), + const SizedBox(height: 4), + ATextFormField(labelText: _subWorkOrders?.faultDescription?.workPerformed ?? "", textInputType: TextInputType.multiline, enable: false), + ], + ), + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => WorkOrderDetailsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "WO Details", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), ), - const Text("*", style: TextStyle(color: Colors.red)), + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => SparePartsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "Spare Parts", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), + ), + const SizedBox(height: 8), + AMiniOneImagePicker( + image: _image, + onPick: (image) { + _image = image; + _subWorkOrders.attachmentsWorkOrder ??= []; + _subWorkOrders.attachmentsWorkOrder.add(AttachmentsWorkOrder(name: "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}")); + }, + ), + const SizedBox(height: 50), ], ), - trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), ), - ), - ), - const SizedBox(height: 8), - AMiniOneImagePicker( - image: _image, - onPick: (image) { - _image = image; - _subWorkOrders.attachmentsWorkOrder.add(AttachmentsWorkOrder(name: "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}")); - }, + ], ), - const SizedBox(height: 50), - ], + ), + ).expanded, + Padding( + padding: const EdgeInsets.all(16.0), + child: AButton( + text: subtitle.create, + onPressed: () async { + _subWorkOrders.parentWOId = widget.workOrder.id; + _validate = true; + setState(() {}); + if (validate()) { + if (_subWorkOrders.timer?.startAt == null || _subWorkOrders.timer?.endAt == null) { + Fluttertoast.showToast(msg: "Working hours required"); + return; + } else if (_subWorkOrders.calllastSituation == null) { + Fluttertoast.showToast(msg: "${subtitle.callLastSituation} required"); + return; + } + _validate = false; + _isLoading = true; + setState(() {}); + if (_formKey.currentState?.validate() ?? false) {} + _formKey.currentState?.save(); + final serviceRequestsProvider = Provider.of(context, listen: false); + final status = await serviceRequestsProvider.createSubWorkOrder(workOrder: _subWorkOrders); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + } + }, + ), ), - ), - ], - ), - ), - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: Padding( - padding: const EdgeInsets.all(16.0), - child: AButton( - text: subtitle.create, - onPressed: () async { - _subWorkOrders.parentWOId = widget.workOrder.id; - _validate = true; - setState(() {}); - if (validate()) { - if (_subWorkOrders.startofWorkTime == null) { - Fluttertoast.showToast(msg: "${subtitle.startDate} required"); - return; - } else if (_subWorkOrders.endofWorkTime == null) { - Fluttertoast.showToast(msg: "${subtitle.endDate} required"); - return; - } else if (_subWorkOrders.calllastSituation == null) { - Fluttertoast.showToast(msg: "${subtitle.callLastSituation} required"); - return; - } - _validate = false; - _isLoading = true; - setState(() {}); - if (_formKey.currentState?.validate() ?? false) {} - _formKey.currentState?.save(); - final serviceRequestsProvider = Provider.of(context, listen: false); - final status = await serviceRequestsProvider.createSubWorkOrder(workOrder: _subWorkOrders); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: subtitle); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - } - }, - ), + ], + ), ), ); } diff --git a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart index 78e0bfce..73d4618f 100644 --- a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart @@ -9,9 +9,11 @@ import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/pages/sub_workorder/workorder_list.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field_new.dart'; import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; import '../../app_style/colors.dart'; import '../../widgets/buttons/app_back_button.dart'; import '../../widgets/buttons/app_button.dart'; @@ -35,6 +37,15 @@ class _SearchSubWorkOrderPageState extends State { bool _isLoading = false; String _callerId = "", _site = ""; Lookup _dateOperator; + + @override + void initState() { + super.initState(); + if (context.mounted) { + Provider.of(context, listen: false).reset(); + } + } + @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context).subtitle; @@ -120,12 +131,16 @@ class _SearchSubWorkOrderPageState extends State { _searchWorkOrders.calllastSituation = status; } }, + woId: _searchWorkOrders.id?.toString(), ), const SizedBox(height: 16), - ATextFormField( - labelText: "Site", - onSaved: (value) { - _site = value; + HospitalAutoCompleteField( + initialValue:_site, + onSearch: (value) { + _site = value.name; + setState(() { + + }); }, ), const SizedBox(height: 16), @@ -183,7 +198,6 @@ class _SearchSubWorkOrderPageState extends State { _isLoading = false; setState(() {}); if (serviceRequestsProvider.stateCode >= 200 && serviceRequestsProvider.stateCode < 300) { - Fluttertoast.showToast(msg: _subtitle.requestCompleteSuccessfully); Navigator.push( context, MaterialPageRoute( diff --git a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart index bf022cc0..e7d5fc93 100644 --- a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/models/part.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/views/app_style/colors.dart'; import '../../../controllers/localization/localization.dart'; import '../../../models/subtitle.dart'; -import '../../widgets/app_text_form_field.dart'; +import '../../app_style/sizing.dart'; import '../../widgets/buttons/app_button.dart'; +import '../../widgets/parts/auto_complete_parts_field.dart'; +import '../../widgets/parts/part_item.dart'; import '../../widgets/titles/app_sub_title.dart'; class SparePartsBottomSheet extends StatefulWidget { @@ -19,6 +22,7 @@ class SparePartsBottomSheet extends StatefulWidget { class _SparePartsBottomSheetState extends State { final GlobalKey _formKey = GlobalKey(); final SearchWorkOrder _workOrder = SearchWorkOrder(); + bool _validate = false; @override void initState() { @@ -26,6 +30,12 @@ class _SparePartsBottomSheetState extends State { _workOrder.copyFrom(widget.subWorkOrder); } + @override + void dispose() { + _workOrder.sparePartsWorkOrders = widget.subWorkOrder.sparePartsWorkOrders; + super.dispose(); + } + @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; @@ -53,97 +63,94 @@ class _SparePartsBottomSheetState extends State { child: Padding( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView( - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 8), - if (_workOrder.sparePartsWorkOrders?.length != null) - ListView.builder( - itemCount: _workOrder.sparePartsWorkOrders?.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - final wo = _workOrder.sparePartsWorkOrders[index]; - return Column( - children: [ - ATextFormField( - labelText: _workOrder?.sparePartsWorkOrders[index]?.sparePart?.partNo ?? "Part No.", - onChange: (value) { - _workOrder.sparePartsWorkOrders[index].sparePart = SparePart(partNo: value); - }, - ), - // const SizedBox(height: 8), - // ATextFormField( - // labelText: "Description", - // hintText: "Add Some Text", - // textInputType: TextInputType.multiline, - // onSaved: (value) { - // _workOrder.sparePartsWorkOrders[index].sparePart = value; - // }, - // ), - const SizedBox(height: 8), - ATextFormField( - labelText: _workOrder?.sparePartsWorkOrders[index]?.qty?.toString() ?? "Quantity", - textInputType: TextInputType.number, - onSaved: (value) { - _workOrder.sparePartsWorkOrders[index].qty = double.tryParse(value ?? ""); - }, - ), - const SizedBox(height: 8), - InkWell( - onTap: () { - _workOrder.sparePartsWorkOrders.removeWhere( - (element) => (element.sparePart?.partNo == wo.sparePart?.partNo && element.id == wo.id), - ); - setState(() {}); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const Icon(Icons.delete, color: Colors.red), - Text( - "Remove this part", - style: Theme.of(context).textTheme.bodySmall, - ), - ], - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.partNumber), + _validate && _workOrder.sparePartsWorkOrders == null + ? ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox(height: 4), + AutoCompletePartsField( + onPick: (part) { + _workOrder.sparePartsWorkOrders ??= []; + _workOrder.sparePartsWorkOrders.add(SparePartsWorkOrders( + id: part.reportPartID, + qty: part.quantity, + sparePart: SparePart(id: part.id, partName: part.name, partNo: part.code), + )); + }, + ), + ], ), - const SizedBox(height: 8), - ], - ); - }, - ), - const Divider(), - const SizedBox(height: 8), - InkWell( - onTap: () { - _workOrder.sparePartsWorkOrders ??= []; - _workOrder.sparePartsWorkOrders.add(SparePartsWorkOrders()); - setState(() {}); - }, - child: Container( - decoration: BoxDecoration( - color: AColors.primaryColor.withOpacity(0.15), - borderRadius: BorderRadius.circular(10), - border: Border.all(color: AColors.primaryColor), + ), + ], + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - child: ListTile( - title: Text( - "Add Part", - style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: AColors.primaryColor), + if (_workOrder.sparePartsWorkOrders?.isNotEmpty ?? false) + Row( + children: [ + Expanded(flex: 3, child: Text(subtitle.number)), + Expanded(flex: 1, child: Text(subtitle.quantity)), + ], ), - trailing: const Icon( - Icons.add_circle, - color: AColors.primaryColor, - size: 20, + if (_workOrder.sparePartsWorkOrders?.isNotEmpty ?? false) + Column( + children: List.generate( + _workOrder.sparePartsWorkOrders?.length, + (index) { + final spare = _workOrder.sparePartsWorkOrders[index]; + Part part = Part( + id: spare.sparePart?.id, + reportPartID: spare.id, + code: spare.sparePart?.partNo, + name: spare.sparePart?.partName, + quantity: spare.qty, + ); + return PartItem( + part: part, + onEdit: (qty) { + spare.qty = qty; + }, + onDelete: (part) { + _workOrder.sparePartsWorkOrders.remove(spare); + setState(() {}); + }, + ); + }, + ), ), - ), - ), + const SizedBox(height: 16), + ], ), - const SizedBox(height: 24), - ], - ), + ), + const SizedBox(height: 24), + ], ), ), ), diff --git a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart index bb08dc43..df6e58f0 100644 --- a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart +++ b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; @@ -8,8 +10,8 @@ import 'package:test_sa/views/widgets/status/report/service_report_maintenance_s import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; import '../../../controllers/localization/localization.dart'; -import '../../app_style/sizing.dart'; -import '../../widgets/date_and_time/time_picker.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; +import '../../widgets/timer/app_timer.dart'; import '../../widgets/titles/app_sub_title.dart'; class WorkOrderDetailsBottomSheet extends StatefulWidget { @@ -27,7 +29,11 @@ class _WorkOrderDetailsBottomSheetState extends State(context, listen: false).reset(); + } } @override @@ -66,81 +72,29 @@ class _WorkOrderDetailsBottomSheetState extends State Validator.isNumeric(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - _workOrder.workingHours = double.tryParse( - ((DateTime.tryParse(_workOrder.endofWorkTime ?? "")?.difference(DateTime.tryParse(_workOrder.startofWorkTime ?? ""))?.inMinutes ?? 0) / 60) - ?.toStringAsFixed(2) - ?.toString() ?? - "0"); - }, - ), - const SizedBox(height: 8), + const SizedBox(height: 16), ATextFormField( labelText: "Travel Hours", initialValue: _workOrder.travelingHours?.toString(), @@ -171,6 +125,7 @@ class _WorkOrderDetailsBottomSheetState extends State { } if (widget.gasRefillModel != null && _firstTime) { _formModel = widget.gasRefillModel; + _formModel.status = const Lookup(value: 0); HospitalsProvider().getHospitalsListByVal(searchVal: widget.gasRefillModel.clientName).then((value) { _gasRefillProvider.hospital = value?.firstWhere((element) => element.name == widget.gasRefillModel.clientName, orElse: () => null); print(_gasRefillProvider.hospital?.buildings?.length); @@ -212,7 +216,8 @@ class _RequestGasRefillState extends State { height: 4, ), GasStatusMenu( - initialValue: _formModel.status ?? const Lookup(value: 1), + initialValue: _formModel.status ?? const Lookup(value: 0), + enabled: false, onSelect: (status) { _formModel.status = status; }, @@ -288,73 +293,73 @@ class _RequestGasRefillState extends State { ), ], ), - if (_userProvider.user?.type == UsersTypes.engineer) - Column( - children: [ - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("Start of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _gasRefillProvider.startDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _gasRefillProvider.startDate = date; - setState(() {}); - }, - ), - ], - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("End of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _gasRefillProvider.endDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _gasRefillProvider.endDate = date; - setState(() {}); - }, - ), - ], - ), - ), - ], - ), - const SizedBox(height: 8), - ASubTitle(_subtitle.workingHours), - const SizedBox(height: 4), - ATextFormField( - initialValue: null, - textAlign: TextAlign.center, - hintText: _gasRefillProvider.startDate == null - ? "0" - : ((_gasRefillProvider.endDate?.difference(_gasRefillProvider.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", - enable: false, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - // _serviceReport.workHours = value; - }, - ), - ], - ), + // if (_userProvider.user?.type == UsersTypes.engineer) + // Column( + // children: [ + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.stretch, + // children: [ + // const ASubTitle("Start of Work"), + // SizedBox( + // height: 8 * AppStyle.getScaleFactor(context), + // ), + // ADateTimePicker( + // date: _gasRefillProvider.startDate, + // from: DateTime.now().subtract(const Duration(days: 365)), + // to: DateTime.now().add(const Duration(days: 365)), + // onDateTimePicker: (date) { + // _gasRefillProvider.startDate = date; + // setState(() {}); + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.stretch, + // children: [ + // const ASubTitle("End of Work"), + // SizedBox( + // height: 8 * AppStyle.getScaleFactor(context), + // ), + // ADateTimePicker( + // date: _gasRefillProvider.endDate, + // from: DateTime.now().subtract(const Duration(days: 365)), + // to: DateTime.now().add(const Duration(days: 365)), + // onDateTimePicker: (date) { + // _gasRefillProvider.endDate = date; + // setState(() {}); + // }, + // ), + // ], + // ), + // ), + // ], + // ), + // const SizedBox(height: 8), + // ASubTitle(_subtitle.workingHours), + // const SizedBox(height: 4), + // ATextFormField( + // initialValue: null, + // textAlign: TextAlign.center, + // hintText: _gasRefillProvider.startDate == null + // ? "0" + // : ((_gasRefillProvider.endDate?.difference(_gasRefillProvider.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", + // enable: false, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, + // textInputType: TextInputType.number, + // onSaved: (value) { + // // _serviceReport.workHours = value; + // }, + // ), + // ], + // ), if (widget.gasRefillModel == null) Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -481,14 +486,43 @@ class _RequestGasRefillState extends State { }, ); }), + if (widget.gasRefillModel != null) const SizedBox(height: 16), + if (widget.gasRefillModel != null) const ASubTitle("Nurse Signature"), + if (widget.gasRefillModel != null) + ESignature( + oldSignature: _formModel.signatureNurse, + newSignature: _formModel.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _formModel.localNurseSignature = signature; + _formModel.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + if (widget.gasRefillModel != null) + const SizedBox( + height: 8, + ), + if (widget.gasRefillModel != null) const ASubTitle("Engineer Signature"), + if (widget.gasRefillModel != null) + ESignature( + oldSignature: _formModel.signatureEngineer, + newSignature: _formModel.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _formModel.localNurseSignature = signature; + _formModel.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), const SizedBox(height: 16), AButton( text: widget.gasRefillModel == null ? _subtitle.submit : _subtitle.update, onPressed: _onSubmit, ), - const SizedBox( - height: 100, - ) + const SizedBox(height: 100) ], ), ), diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 1e90af98..e6e9d608 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -212,7 +212,7 @@ class _LandPageState extends State { Navigator.of(context).pushNamed(TrackDeviceTransferPage.id); }, ), - // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) LandPageItem( text: "Search Work Order", svgPath: "assets/images/sub_workorder_icon.svg", diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index 91b87bed..bcd45204 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -306,7 +306,7 @@ class CreateRequestPageState extends State { Fluttertoast.showToast(msg: _subtitle.pickDevice); return; } - if (_serviceRequest.firstAction != null && _dateTime == null) { + if (_serviceRequest.firstAction.name == "Need a visit" && _dateTime == null) { Fluttertoast.showToast(msg: _subtitle.noDateFound); return; } diff --git a/lib/views/pages/user/requests/report/create_service_report.dart b/lib/views/pages/user/requests/report/create_service_report.dart index 7f1b31bd..b8fa12e9 100644 --- a/lib/views/pages/user/requests/report/create_service_report.dart +++ b/lib/views/pages/user/requests/report/create_service_report.dart @@ -23,24 +23,21 @@ import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; -import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; import 'package:test_sa/views/widgets/equipment/auto_complete_devices_field.dart'; import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/parts/part_item.dart'; -import 'package:test_sa/views/widgets/status/employee/engineers_mune.dart'; import 'package:test_sa/views/widgets/status/report/service_report_equipment_status.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_status.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; -import '../../../../widgets/speech_to_text/speech_to_text.dart'; import '../../../../widgets/status/report/service_report_fault_description.dart'; import '../../../../widgets/status/report/service_report_repair_location.dart'; +import '../../../../widgets/timer/app_timer.dart'; class CreateServiceReport extends StatefulWidget { static final String id = "/create-service-report"; @@ -331,7 +328,7 @@ class _CreateServiceReportState extends State with TickerPr child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // ASubTitle(_subtitle.reportStatus), + // ASubTitle(_subtitle.reportStatus), ASubTitle("Equipment Status"), _validate && _serviceReport.equipmentStatus == null ? ASubTitle( @@ -418,71 +415,23 @@ class _CreateServiceReportState extends State with TickerPr SizedBox( height: 8 * AppStyle.getScaleFactor(context), ), + ASubTitle(_subtitle.workingHours), + const SizedBox(height: 8), Row( children: [ Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("Start of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _serviceReport.startDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _serviceReport.startDate = date; - setState(() {}); - }, - ), - ], - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ASubTitle("End of Work"), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - ADateTimePicker( - date: _serviceReport.endDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDateTimePicker: (date) { - _serviceReport.endDate = date; - setState(() {}); - }, - ), - ], + child: AppTimer( + timer: _serviceReport.timer, + onChange: (timer) async { + _serviceReport.timer = timer; + _serviceReport.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); + return true; + }, ), ), ], ), - const SizedBox(height: 8), - ASubTitle(_subtitle.workingHours), - const SizedBox(height: 4), - ATextFormField( - initialValue: null, - textAlign: TextAlign.center, - hintText: _serviceReport.startDate == null - ? "0" - : ((_serviceReport?.endDate?.difference(_serviceReport?.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", - enable: false, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - // _serviceReport.workHours = value; - }, - ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 16), // device sn Visibility( visible: widget.request.deviceSerialNumber == null, @@ -636,7 +585,7 @@ class _CreateServiceReportState extends State with TickerPr enable: false, hintText: _serviceReport.faultDescription?.workPerformed ?? "", controller: _workPreformedController, - style: Theme.of(context).textTheme.subtitle1, + style: Theme.of(context).textTheme.titleMedium, validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, textInputType: TextInputType.multiline, onSaved: (value) { @@ -656,6 +605,12 @@ class _CreateServiceReportState extends State with TickerPr crossAxisAlignment: CrossAxisAlignment.start, children: [ ASubTitle(_subtitle.reasons), + _validate && _serviceReport.reason?.id == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), const SizedBox(height: 4), ServiceReportReasonsMenu( initialValue: _serviceReport.reason, @@ -701,7 +656,7 @@ class _CreateServiceReportState extends State with TickerPr ), ATextFormField( initialValue: _serviceReport?.travelingExpense?.toString(), - hintText: _subtitle.travelingExpense, + hintText: "i.e 3, 3.5, 4", textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleMedium, textInputType: TextInputType.number, @@ -929,9 +884,9 @@ class _CreateServiceReportState extends State with TickerPr ), Column( children: List.generate(_serviceReport.parts.length, (index) { - Part _part = _serviceReport.parts[index]; + Part part = _serviceReport.parts[index]; return PartItem( - part: _part, + part: part, onDelete: (part) { _serviceReport.parts.remove(part); setState(() {}); @@ -955,7 +910,10 @@ class _CreateServiceReportState extends State with TickerPr // setState(() {}); // return; // } - if (!_serviceReport.validate()) return; + if (!(await _serviceReport.validate())) { + setState(() {}); + return; + } _formKey.currentState.save(); _isLoading = true; diff --git a/lib/views/pages/user/requests/report/edit_service_report.dart b/lib/views/pages/user/requests/report/edit_service_report.dart index 7c4429c5..b0cc2bc4 100644 --- a/lib/views/pages/user/requests/report/edit_service_report.dart +++ b/lib/views/pages/user/requests/report/edit_service_report.dart @@ -8,9 +8,12 @@ import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_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/models/call_request_for_work_order_model.dart'; +import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/part.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; @@ -27,12 +30,11 @@ import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/parts/part_item.dart'; -import 'package:test_sa/views/widgets/status/employee/engineers_mune.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_equipment_status.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_fault_description.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_status.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_type.dart'; -import 'package:test_sa/views/widgets/status/report/service_status.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; @@ -42,6 +44,7 @@ class EditServiceReport extends StatefulWidget { final ServiceReport report; const EditServiceReport({Key key, this.request, this.report}) : super(key: key); + @override _EditServiceReportState createState() => _EditServiceReportState(); } @@ -54,6 +57,7 @@ class _EditServiceReportState extends State with TickerProvid bool _validate = false; ServiceReport _serviceReport; bool _isLoading = false; + bool _showCommentField = false; Subtitle _subtitle; File _image; @@ -62,12 +66,26 @@ class _EditServiceReportState extends State with TickerProvid TextEditingController _faultController = TextEditingController(); TextEditingController _workPreformedController = TextEditingController(); + ServiceStatusProvider _assetTypeProvider; + + CallRequestForWorkOrder _callRequestForWorkOrder; + @override void initState() { _serviceReport = widget.report; super.initState(); } + void getRequestForWorkOrder() async { + _isLoading = true; + setState(() {}); + _callRequestForWorkOrder = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id); + _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson()); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _isLoading = false; + setState(() {}); + } + @override void dispose() { _faultController.dispose(); @@ -80,6 +98,15 @@ class _EditServiceReportState extends State with TickerProvid _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _serviceRequestsProvider = Provider.of(context); + + _assetTypeProvider = Provider.of(context); + if (_callRequestForWorkOrder == null) { + getRequestForWorkOrder(); + } + _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder?.assetType, + orElse: () => null, + ); _subtitle = AppLocalization.of(context).subtitle; return Scaffold( key: _scaffoldKey, @@ -94,11 +121,9 @@ class _EditServiceReportState extends State with TickerProvid child: Stack( children: [ ListView( + padding: const EdgeInsets.all(16), children: [ - //AppNameBar(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Center( child: Padding( padding: const EdgeInsets.all(8.0), @@ -108,22 +133,22 @@ class _EditServiceReportState extends State with TickerProvid ), ), ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ - const BoxShadow( - color: AColors.grey, - offset: Offset(0, -1), - ) - ]), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 8, - ), - Wrap( + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Caller Info"), + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Wrap( spacing: 10, children: [ ASubTitle( @@ -133,537 +158,796 @@ class _EditServiceReportState extends State with TickerProvid widget.request.deviceSerialNumber == null ? const SizedBox() : ASubTitle( - "${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}", - font: 14, - ), + "${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}", + font: 14, + ), Text( "${_subtitle.customer}: ${widget.request.hospitalName}", style: Theme.of(context).textTheme.subtitle1.copyWith( - fontWeight: FontWeight.bold, - fontSize: 12, - ), + fontWeight: FontWeight.bold, + fontSize: 12, + ), textScaleFactor: AppStyle.getScaleFactor(context), ) ], ), - const Divider(), - - // Report type and Reasons - Row( + ), + const SizedBox(height: 8), + ASubTitle("Work Order Details"), + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + const BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Report Status - Expanded( + // Report type and Reasons + Row( + children: [ + // Report Status + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.reportType), + // _validate && _serviceReport.type == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // ServiceReportTypeMenu( + // initialValue: _serviceReport.type, + // onSelect: (status) { + // _serviceReport.type = status; + // }, + // ), + // ], + // ), + // ), + // const SizedBox( + // width: 8, + // ), + // visit date + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.visitDate), + _validate && _serviceReport.visitDate == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + Row( + children: [ + Expanded( + child: ADatePicker( + date: _serviceReport.visitDate, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDatePicker: (date) { + _serviceReport.visitDate = date; + setState(() {}); + }, + ), + ), + ], + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 8, + ), + // device sn + Visibility( + visible: widget.request.deviceSerialNumber == null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.reportType), - _validate && _serviceReport.type == null + ASubTitle(_subtitle.deviceSN), + _validate && _serviceReport.device?.id == null ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) + _subtitle.requiredWord, + color: Colors.red, + ) : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - ServiceReportTypeMenu( - initialValue: _serviceReport.type, - onSelect: (status) { - _serviceReport.type = status; + AutoCompleteDeviceField( + hospitalId: widget.request.hospitalId, + initialValue: _serviceReport.device, + onPick: (id) { + _serviceReport.device.id = id; }, ), + const SizedBox(height: 8), ], ), ), + const SizedBox(height: 8), + ASubTitle(_subtitle.AssetType), + _validate && _serviceReport.assetType == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), const SizedBox( - width: 8, + height: 4, ), - // visit date - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.visitDate), - _validate && _serviceReport.visitDate == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - Row( + LoadingManager( + isLoading: _assetTypeProvider.isLoading, + isFailedLoading: _assetTypeProvider.statuses == null, + stateCode: _assetTypeProvider.stateCode, + onRefresh: () async { + _assetTypeProvider.reset(); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _serviceReport?.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder.assetType, + orElse: () => null, + ); + }, + child: ATextFormField( + initialValue: _serviceReport?.assetType?.name ?? "NULL", + textAlign: TextAlign.center, + enable: false, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + // ServiceAssetTypeMenu( + // initialValue: _serviceReport.assetType, + // onSelect: (status) { + // _serviceReport.assetType = status; + // }, + // ), + const SizedBox( + height: 8, + ), + Row( + children: [ + // report status + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: ADatePicker( - date: _serviceReport.visitDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDatePicker: (date) { - _serviceReport.visitDate = date; - setState(() {}); - }, - ), + // ASubTitle(_subtitle.reportStatus), + ASubTitle("Equipment Status"), + _validate && _serviceReport.equipmentStatus == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, ), + // ServiceReportStatusMenu( + // report: _serviceReport, + // request: widget.request, + // onSelect: (status) { + // _serviceReport.status = status; + // }, + // ), + ServiceReportEquipmentStatusMenu( + report: _serviceReport, + request: widget.request, + onSelect: (status) { + _serviceReport.equipmentStatus = status; + }, + ) ], ), - ], - ), + ), + const SizedBox( + width: 8, + ), + // Provider.of(context).isLoading == null + // ? const SizedBox.shrink(): + // Call's last Situation + Consumer( + builder: (_, provider, __) { + if (provider.isLoading == null) return const SizedBox.shrink(); + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.callLastSituation), + _validate && _serviceReport.callLastSituation == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox(height: 4), + ServiceReportLastCallsMenu( + report: _serviceReport, + onSelect: (status) { + if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { + _serviceReport.callLastSituation = status; + setState(() {}); + } else { + _serviceReport.callLastSituation = status; + } + }, + ), + ], + ), + ); + }, + ), + ], ), - ], - ), - const SizedBox( - height: 8, - ), - // device sn - Visibility( - visible: true, //widget.report.device == null, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.deviceSN), - _validate && _serviceReport.device?.id == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - AutoCompleteDeviceField( - hospitalId: widget.request.hospitalId, - initialValue: _serviceReport.device, - onPick: (id) { - _serviceReport.device.id = id; - }, - ), + if (_showCommentField) const SizedBox( height: 8, ), - ], - ), - ), - const SizedBox( - height: 8, - ), - ASubTitle(_subtitle.AssetType), - _validate && _serviceReport.assetType == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - ServiceAssetTypeMenu( - initialValue: _serviceReport.assetType, - onSelect: (status) { - _serviceReport.assetType = status; - }, - ), - const SizedBox( - height: 8, - ), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - const ASubTitle("Assign Employee"), - const SizedBox( - height: 8, - ), - _validate && _serviceReport.engineer == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - EngineersMenu( - initialValue: _serviceReport.engineer, - onSelect: (engineer) { - _serviceReport.engineer = engineer; - }, - ), - const SizedBox( - height: 8, - ), - // Report status and Asset Type - Row( - children: [ - // report status - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.reportStatus), - _validate && _serviceReport.equipmentStatus == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - ServiceReportStatusMenu( - report: _serviceReport, - request: widget.request, - onSelect: (status) { - _serviceReport.equipmentStatus = status; - }, - ), - ], + if (_showCommentField) + ATextFormField( + initialValue: _serviceReport?.reviewComment, + hintText: "Review Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; + }, ), + + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), + // const ASubTitle("Assign Employee"), + // const SizedBox( + // height: 8, + // ), + // _validate && _serviceReport.engineer == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // EngineersMenu( + // initialValue: _serviceReport.engineer, + // onSelect: (engineer) { + // _serviceReport.engineer = engineer; + // }, + // ), + // const SizedBox( + // height: 8, + // ), + // Report status and Service Type + // Row( + // children: [ + // // report status + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.reportStatus), + // _validate && _serviceReport.equipmentStatus == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // ServiceReportStatusMenu( + // report: _serviceReport, + // request: widget.request, + // onSelect: (status) { + // _serviceReport.equipmentStatus = status; + // }, + // ), + // ], + // ), + // ), + // const SizedBox( + // width: 8, + // ), + // Consumer( + // builder: (_, provider, __) { + // if (provider.isLoading == null) return const SizedBox.shrink(); + // return Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.callLastSituation), + // _validate && _serviceReport.callLastSituation == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // ServiceReportLastCallsMenu( + // report: _serviceReport, + // onSelect: (status) { + // if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { + // _serviceReport.callLastSituation = status; + // setState(() {}); + // } else { + // _serviceReport.callLastSituation = status; + // } + // }, + // ), + // ], + // ), + // ); + // }, + // ), + // ], + // ), const SizedBox( - width: 8, + height: 8, ), - Consumer( - builder: (_, provider, __) { - if (provider.isLoading == null) return const SizedBox.shrink(); - return Expanded( + // invoice number & code + _serviceReport.callLastSituation?.value != 12 + ? const SizedBox.shrink() + : Row( + children: [ + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.callLastSituation), - _validate && _serviceReport.callLastSituation == null - ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), + ASubTitle(_subtitle.invoiceNumber), + const SizedBox( + height: 8, + ), + ATextFormField( + initialValue: _serviceReport?.invoiceNumber, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.invoiceNumber = value; + }, + ), + ], + ), + ), + const SizedBox( + width: 8, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.invoiceCode), const SizedBox( height: 4, ), - ServiceReportLastCallsMenu( - report: _serviceReport, - onSelect: (status) { - if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { - _serviceReport.callLastSituation = status; - setState(() {}); - } else { - _serviceReport.callLastSituation = status; - } + ATextFormField( + initialValue: _serviceReport?.invoiceCode, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.text, + onSaved: (value) { + _serviceReport.invoiceCode = value; }, ), ], ), - ); - }, + ), + ], ), - ], - ), - const SizedBox( - height: 8, - ), - // invoice number & code - _serviceReport.callLastSituation?.value != 12 - ? const SizedBox.shrink() - : Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.invoiceNumber), - const SizedBox( - height: 8, - ), - ATextFormField( - initialValue: _serviceReport?.invoiceNumber, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - _serviceReport.invoiceNumber = value; - }, - ), - ], - ), - ), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.invoiceCode), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: _serviceReport?.invoiceCode, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, - textInputType: TextInputType.text, - onSaved: (value) { - _serviceReport.invoiceCode = value; - }, - ), - ], - ), - ), - ], - ), - // const SizedBox(height: 8,), - // Row( - // children: [ - // ASubTitle(_subtitle.faultDescription), - // Expanded( - // child: SizedBox( - // height: 32 * AppStyle.getScaleFactor(context), - // child: SpeechToTextButton( - // controller: _faultController, - // mini: true, - // ), - // ), - // ), - // ], - // ), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.faultDescriptionId, - // textAlign: TextAlign.center, - // controller: _faultController, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.hasValue(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.multiline, - // onSaved: (value){ - // _serviceReport.faultDescriptionId = value; - // }, - // ), - // const SizedBox(height: 8,), - // Row( - // children: [ - // ASubTitle(_subtitle.workPreformed), - // Expanded( - // child: SizedBox( - // height: 32 * AppStyle.getScaleFactor(context), - // child: SpeechToTextButton( - // controller: _workPreformedController, - // mini: true, - // ), - // ), - // ), - // ], - // ), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.workPreformed, - // textAlign: TextAlign.center, - // controller: _workPreformedController, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.hasValue(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.multiline, - // onSaved: (value){ - // _serviceReport.workPreformed = value; - // }, - // ), - // const SizedBox(height: 8,), - - const SizedBox( - height: 8, - ), - Row( - children: [ - // reasons - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.reasons), - const SizedBox( - height: 4, - ), - ServiceReportReasonsMenu( - initialValue: _serviceReport.reason, - onSelect: (status) { - _serviceReport.reason = status; - }, + // const SizedBox(height: 8,), + // Row( + // children: [ + // ASubTitle(_subtitle.faultDescription), + // Expanded( + // child: SizedBox( + // height: 32 * AppStyle.getScaleFactor(context), + // child: SpeechToTextButton( + // controller: _faultController, + // mini: true, + // ), + // ), + // ), + // ], + // ), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.faultDescriptionId, + // textAlign: TextAlign.center, + // controller: _faultController, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.hasValue(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.multiline, + // onSaved: (value){ + // _serviceReport.faultDescriptionId = value; + // }, + // ), + // const SizedBox(height: 8,), + // Row( + // children: [ + // ASubTitle(_subtitle.workPreformed), + // Expanded( + // child: SizedBox( + // height: 32 * AppStyle.getScaleFactor(context), + // child: SpeechToTextButton( + // controller: _workPreformedController, + // mini: true, + // ), + // ), + // ), + // ], + // ), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.workPreformed, + // textAlign: TextAlign.center, + // controller: _workPreformedController, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.hasValue(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.multiline, + // onSaved: (value){ + // _serviceReport.workPreformed = value; + // }, + // ), + // const SizedBox(height: 8,), + const SizedBox(height: 8), + ASubTitle(_subtitle.workingHours), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: AppTimer( + timer: _serviceReport.timer, + enabled: false, + // onChange: (timer) async { + // _serviceReport.timer = timer; + // _serviceReport.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); + // return true; + // }, ), - ], + ), + ], + ), + const SizedBox(height: 16), + if (_showCommentField) + const SizedBox( + height: 8, + ), + if (_showCommentField) + ATextFormField( + initialValue: _serviceReport?.reviewComment, + hintText: "Review Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; + }, ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), + const SizedBox(height: 8), + ASubTitle(_subtitle.faultDescription), const SizedBox( - width: 8, + height: 4, ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.attachImage), - AMiniOneImagePicker( - //error: _validate && _serviceReport.image == null, - image: _image, - onPick: (image) { - _image = image; - _serviceReport.image = base64Encode(image.readAsBytesSync()); - }, - ), - ], - ), + ServiceReportFaultDescription( + requestId: widget.request?.id, + initialValue: _serviceReport.faultDescription, + onSelect: (status) { + print("faluttt:${status?.toJson()}"); + _serviceReport.faultDescription = status; + if (mounted) setState(() {}); + }, ), - ], - ), - const SizedBox( - height: 8, - ), - // Traveling Hours & Working Hours - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.workingHours), - const SizedBox( - height: 8, + const SizedBox(height: 8), + ASubTitle(_subtitle.workPreformed), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.workPreformed, + textAlign: TextAlign.center, + enable: false, + hintText: _serviceReport.faultDescription?.workPerformed ?? "", + controller: _workPreformedController, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.multiline, + onSaved: (value) { + // _serviceReport.workPreformed = value; + }, + ), + const SizedBox(height: 4), + Row( + children: [ + // reasons + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.reasons), + const SizedBox( + height: 4, + ), + ServiceReportReasonsMenu( + initialValue: _serviceReport.reason, + onSelect: (status) { + _serviceReport.reason = status; + }, + ), + ], ), - Row( + ), + const SizedBox( + width: 8, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: AppTimer( - timer: _serviceReport.timer, - onChange: (timer) async { - _serviceReport.timer = timer; - return true; - }, - ), + ASubTitle(_subtitle.attachImage), + AMiniOneImagePicker( + //error: _validate && _serviceReport.image == null, + image: _image, + onPick: (image) { + _image = image; + _serviceReport.image = base64Encode(image.readAsBytesSync()); + }, ), ], ), - // ATextFormField( - // initialValue: _serviceReport?.workHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.workHours = value; - // }, - // ), - ], - ), + ), + ], + ), + const SizedBox( + height: 8, ), - // const SizedBox(width: 8,), - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(_subtitle.travelingHours), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.travelingHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.travelingHours = value; - // }, + const SizedBox(height: 8), + ASubTitle(_subtitle.repairLocation), + const SizedBox(height: 4), + ServiceReportRepairLocation( + initialValue: _serviceReport.repairLocation, + onSelect: (status) { + _serviceReport.repairLocation = status; + }, + ), + const SizedBox(height: 16), + ASubTitle(_subtitle.travelingExpense), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.travelingExpense?.toString(), + hintText: _subtitle.travelingExpense, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.number, + onSaved: (value) { + if (value != null && value.isEmpty) { + _serviceReport.travelingExpense = int.tryParse(_serviceReport?.travelingExpense?.toString() ?? "") ?? 0; + } else + _serviceReport.travelingExpense = int.tryParse(value) ?? 0; + }, + ), + + const SizedBox(height: 8), + ASubTitle(_subtitle.travelingHours), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.travelingHours?.toString(), + textAlign: TextAlign.center, + hintText: "i.e 3, 3.5, 4", + style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.travelingHours = double.tryParse(value) ?? 0.0; + }, + ), + // Traveling Hours & Working Hours + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.workingHours), + // const SizedBox( + // height: 8, + // ), + // Row( + // children: [ + // Expanded( + // child: AppTimer( + // timer: _serviceReport.timer, + // onChange: (timer) async { + // _serviceReport.timer = timer; + // return true; + // }, + // ), + // ), + // ], + // ), + // // ATextFormField( + // // initialValue: _serviceReport?.workHours, + // // textAlign: TextAlign.center, + // // hintText: "i.e 3, 3.5, 4", + // // style: Theme.of(context).textTheme.subtitle1, + // // validator: (value) => + // // Validator.isNumeric(value) + // // ? null : _subtitle.requiredWord, + // // textInputType: TextInputType.number, + // // onSaved: (value){ + // // _serviceReport.workHours = value; + // // }, + // // ), + // ], // ), - // ], - // ), + // ), + // // const SizedBox(width: 8,), + // // Expanded( + // // child: Column( + // // crossAxisAlignment: CrossAxisAlignment.start, + // // children: [ + // // ASubTitle(_subtitle.travelingHours), + // // const SizedBox(height: 4,), + // // ATextFormField( + // // initialValue: _serviceReport?.travelingHours, + // // textAlign: TextAlign.center, + // // hintText: "i.e 3, 3.5, 4", + // // style: Theme.of(context).textTheme.subtitle1, + // // validator: (value) => + // // Validator.isNumeric(value) + // // ? null : _subtitle.requiredWord, + // // textInputType: TextInputType.number, + // // onSaved: (value){ + // // _serviceReport.travelingHours = value; + // // }, + // // ), + // // ], + // // ), + // // ), + // ], + // ), + // const SizedBox( + // height: 8, // ), + // Operating Hours and Job Sheet Number + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.operatingHours), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.operatingHours, + // textAlign: TextAlign.center, + // hintText: "i.e 3, 3.5, 4", + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.number, + // onSaved: (value){ + // _serviceReport.operatingHours = value; + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8,), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.jobSheetNumber), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.jobSheetNumber, + // textAlign: TextAlign.center, + // style: Theme.of(context).textTheme.subtitle1, + // textInputType: TextInputType.name, + // onSaved: (value){ + // _serviceReport.jobSheetNumber = value; + // }, + // ), + // ], + // ), + // ), + // ], + // ), + //const SizedBox(height: 8,), + + const SizedBox(height: 8), + ASubTitle(_subtitle.comment), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.comment, + hintText: "Technical Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.comment = value; + }, + ), + const SizedBox(height: 8), + const ASubTitle("Nurse Signature"), + ESignature( + oldSignature: _serviceReport.signatureNurse, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Engineer Signature"), + ESignature( + oldSignature: _serviceReport.signatureEngineer, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox( + height: 8, + ), + // Part Number and Quantity ], ), - const SizedBox( - height: 8, - ), - // Operating Hours and Job Sheet Number - // Row( - // children: [ - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(_subtitle.operatingHours), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.operatingHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.operatingHours = value; - // }, - // ), - // ], - // ), - // ), - // const SizedBox(width: 8,), - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(_subtitle.jobSheetNumber), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.jobSheetNumber, - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.name, - // onSaved: (value){ - // _serviceReport.jobSheetNumber = value; - // }, - // ), - // ], - // ), - // ), - // ], - // ), - //const SizedBox(height: 8,), - const SizedBox( - height: 8, - ), - const ASubTitle("Nurse Signature"), - ESignature( - oldSignature: _serviceReport.signatureNurse, - newSignature: _serviceReport.localNurseSignature, - onChange: (signature) { - if (signature == null || signature.isEmpty) { - return; - } - _serviceReport.localNurseSignature = signature; - _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Engineer Signature"), - ESignature( - oldSignature: _serviceReport.signatureEngineer, - newSignature: _serviceReport.localNurseSignature, - onChange: (signature) { - if (signature == null || signature.isEmpty) { - return; - } - _serviceReport.localNurseSignature = signature; - _serviceReport.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), - const SizedBox( - height: 8, - ), - // Part Number and Quantity + ), + ], + ), + ASubTitle("Spare Parts"), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ Row( children: [ Expanded( @@ -674,9 +958,9 @@ class _EditServiceReportState extends State with TickerProvid ASubTitle(_subtitle.partNumber), _validate && _serviceReport.parts == null ? ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ) + _subtitle.requiredWord, + color: Colors.red, + ) : const SizedBox.shrink(), const SizedBox( height: 4, @@ -713,53 +997,56 @@ class _EditServiceReportState extends State with TickerProvid ); }), ), - const SizedBox( height: 16, ), ], ), ), - Padding( - padding: const EdgeInsets.all(16.0), - child: AButton( - text: _subtitle.update, - onPressed: () async { - _validate = true; - if (!_formKey.currentState.validate()) { - setState(() {}); - return; - } - if (!_serviceReport.validate()) { - setState(() {}); - return; - } - _formKey.currentState.save(); + AButton( + text: _subtitle.update, + onPressed: () async { + if (_serviceReport?.workingHours == null) { + await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started"); + return; + } else if ((_serviceReport?.timer?.stopped ?? false) == false) { + await Fluttertoast.showToast(msg: "Stop The Timer"); + return; + } + _validate = true; + print("jere1245"); + // if (!_formKey.currentState.validate()) { + // setState(() {}); + // return; + // } + // print("jere124"); + // if (!_serviceReport.validate()) { + // setState(() {}); + // return; + // } + // print("jere14"); + _formKey.currentState.save(); - _isLoading = true; - setState(() {}); + _isLoading = true; + setState(() {}); - int status = await _serviceRequestsProvider.updateServiceReport(user: _userProvider.user, host: _settingProvider.host, report: _serviceReport, request: widget.request); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: _subtitle.requestCompleteSuccessfully, - ); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - }, - ), + int status = await _serviceRequestsProvider.updateServiceReport(user: _userProvider.user, host: _settingProvider.host, report: _serviceReport, request: widget.request); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast( + msg: _subtitle.requestCompleteSuccessfully, + ); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + }, ), - const SizedBox( - height: 300, - ) ], ), const ABackButton(), diff --git a/lib/views/pages/user/requests/report/future_service_report.dart b/lib/views/pages/user/requests/report/future_service_report.dart index 466ab8f2..c391b669 100644 --- a/lib/views/pages/user/requests/report/future_service_report.dart +++ b/lib/views/pages/user/requests/report/future_service_report.dart @@ -31,6 +31,8 @@ class _FutureServiceReportState extends State { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); Subtitle _subtitle = AppLocalization.of(context).subtitle; + ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: _subtitle) + ; return Scaffold( body: FutureBuilder( future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: _subtitle), diff --git a/lib/views/pages/user/requests/request_details.dart b/lib/views/pages/user/requests/request_details.dart index d0b6de53..cfe8ec93 100644 --- a/lib/views/pages/user/requests/request_details.dart +++ b/lib/views/pages/user/requests/request_details.dart @@ -345,7 +345,7 @@ class RequestDetailsPage extends StatelessWidget { title: _subtitle.visitDate, info: workOrders[index].visitDate, ), - RequestInfoRow(title: _subtitle.assignedEmployee, info: workOrders[index].assignedEmployee.name), + RequestInfoRow(title: _subtitle.assignedEmployee, info: workOrders[index].assignedEmployee?.name??""), RequestInfoRow( title: _subtitle.assetSN, info: workOrders[index].callRequest.asset.assetSerialNo, diff --git a/lib/views/pages/user/visits/pantry/edit_pentry.dart b/lib/views/pages/user/visits/pantry/edit_pentry.dart index 55d356b9..d2d52054 100644 --- a/lib/views/pages/user/visits/pantry/edit_pentry.dart +++ b/lib/views/pages/user/visits/pantry/edit_pentry.dart @@ -14,10 +14,11 @@ import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/pentry/pentry_calibration_tool_form.dart'; -import 'package:test_sa/views/widgets/pentry/pentry_info_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_pm_kit_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_ppm_check_list_form.dart'; +import '../../../../widgets/pentry/pentry_info_form.dart'; + class EditPentry extends StatefulWidget { final Pentry pentry; final Visit visit; @@ -73,7 +74,7 @@ class _EditPentryState extends State with SingleTickerProviderStateM if (_pentry.pmKits.isEmpty) _pentry.pmKits.add(PMKit()); if (_pentry.calibrationTools.isEmpty) _pentry.calibrationTools.add(CalibrationTool()); if (_pentry.ppmCheckLists.isEmpty) _pentry.ppmCheckLists.add(PPMCheckList()); - _tabController = TabController(length: 3, vsync: this); + _tabController = TabController(length: 4, vsync: this); super.initState(); } @@ -104,25 +105,26 @@ class _EditPentryState extends State with SingleTickerProviderStateM child: Padding( padding: const EdgeInsets.all(2.0), child: TabBar( - controller: _tabController, - isScrollable: true, - onTap: (index) { - setState(() {}); - }, - tabs: const [ - Tab( - text: "PPM Check List", - ), - // Tab( - // text: "Calibration Tools", - // ), - Tab( - text: "PK Kits", - ), - Tab( - text: "Pentry", - ), - ]), + controller: _tabController, + isScrollable: true, + onTap: (index) { + setState(() {}); + }, + tabs: const [ + Tab( + text: "PPM Check List", + ), + Tab( + text: "Calibration Tools", + ), + Tab( + text: "PM Kits", + ), + Tab( + text: "PM Entry", + ), + ], + ), ), ), Expanded( @@ -147,7 +149,7 @@ class _EditPentryState extends State with SingleTickerProviderStateM PentryInfoForm( model: _pentry, enableValidate: _validate, - ) + ), ], ), Align( diff --git a/lib/views/widgets/device_trancfer/device_transfer_info_section.dart b/lib/views/widgets/device_trancfer/device_transfer_info_section.dart index a311cb14..1a8da07b 100644 --- a/lib/views/widgets/device_trancfer/device_transfer_info_section.dart +++ b/lib/views/widgets/device_trancfer/device_transfer_info_section.dart @@ -21,7 +21,7 @@ class DeviceTransferInfoSection extends StatelessWidget { info: info.client.name, ), RequestInfoRow( - title: subtitle.unite, + title: subtitle.department, info: info.department.name, ), RequestInfoRow( diff --git a/lib/views/widgets/device_trancfer/device_transfer_item.dart b/lib/views/widgets/device_trancfer/device_transfer_item.dart index 9da46fad..20399463 100644 --- a/lib/views/widgets/device_trancfer/device_transfer_item.dart +++ b/lib/views/widgets/device_trancfer/device_transfer_item.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; @@ -53,6 +52,13 @@ class DeviceTransferItem extends StatelessWidget { Divider( color: onItemColor, ), + Text( + item.device?.number ?? "-----", + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), + Divider( + color: onItemColor, + ), Row( children: [ Expanded( diff --git a/lib/views/widgets/equipment/device_item.dart b/lib/views/widgets/equipment/device_item.dart index e9fb9043..0dd41e75 100644 --- a/lib/views/widgets/equipment/device_item.dart +++ b/lib/views/widgets/equipment/device_item.dart @@ -27,12 +27,19 @@ class DeviceItem extends StatelessWidget { }, child: ListTile( title: Text( - "${_subtitle.sn} : ${device.serialNumber}", + "${_subtitle.assetName} : \n${device.modelDefinition.assetName}", style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Divider( + color: Theme.of(context).scaffoldBackgroundColor, + ), + Text( + "${_subtitle.assetNumber} : ${device.number}", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), + ), Divider( color: Theme.of(context).scaffoldBackgroundColor, ), diff --git a/lib/views/widgets/equipment/single_device_picker.dart b/lib/views/widgets/equipment/single_device_picker.dart index cd540cda..2fdecf87 100644 --- a/lib/views/widgets/equipment/single_device_picker.dart +++ b/lib/views/widgets/equipment/single_device_picker.dart @@ -33,20 +33,20 @@ class _SingleDevicePickerState extends State { TextEditingController numberController = TextEditingController(); TextEditingController snController = TextEditingController(); _getDevice(String result) async { + print(result); if (result == null) return; - showDialog( - barrierDismissible: false, - context: context, - builder: (dialogContext) { - return const Center(child: CircularProgressIndicator()); - }); - List devices = await _devicesProvider.getDevicesListBySN(host: _settingProvider.host, user: _userProvider.user, hospitalId: _userProvider.user.clientId, sn: result); - Navigator.of(context).pop(); - if (devices.isEmpty) { - Fluttertoast.showToast(msg: _subtitle.noDeviceFound); - return; - } - Navigator.of(context).pop(devices.first); + // List devices = await _devicesProvider.getDevicesListBySN(host: _settingProvider.host, user: _userProvider.user, hospitalId: _userProvider.user.clientId, sn: result); + _devicesProvider.reset(); + await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: "", number: result); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); + // if (devices.isEmpty) { + // Fluttertoast.showToast(msg: _subtitle.noDeviceFound); + // return; + // } + // Navigator.of(context).pop(devices.first); } @override @@ -74,81 +74,83 @@ class _SingleDevicePickerState extends State { _subtitle = AppLocalization.of(context).subtitle; return Scaffold( resizeToAvoidBottomInset: false, - body: LoadingManager( - isLoading: _devicesProvider.isLoading, - stateCode: _devicesProvider.stateCode, - isFailedLoading: _devicesProvider.devices == null, - onRefresh: () async { - _devicesProvider.reset(); - await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId); - }, - child: Column( - children: [ - const SizedBox(height: 48), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), - child: Column( - children: [ - ATextFormField( - hintText: "Search by Asset Number", - controller: numberController, - style: Theme.of(context).textTheme.subtitle1, - suffixIcon: const Icon(Icons.search_rounded), - textInputAction: TextInputAction.search, - onAction: () async { - _devicesProvider.reset(); - await _devicesProvider.getEquipment( - user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); - _searchableList.clear(); - _searchableList.addAll(_devicesProvider.devices); - }, - ), - const SizedBox( - height: 8, - ), - ATextFormField( - hintText: _subtitle.searchBySn, - controller: snController, - style: Theme.of(context).textTheme.subtitle1, - suffixIcon: const Icon(Icons.search_rounded), - textInputAction: TextInputAction.search, - onAction: () async { - _devicesProvider.reset(); - await _devicesProvider.getEquipment( - user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); - _searchableList.clear(); - _searchableList.addAll(_devicesProvider.devices); - }, - ), - ], + body: SafeArea( + child: LoadingManager( + isLoading: _devicesProvider.isLoading, + stateCode: _devicesProvider.stateCode, + isFailedLoading: _devicesProvider.devices == null, + onRefresh: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId); + }, + child: Column( + children: [ + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: Column( + children: [ + ATextFormField( + hintText: "Search by Asset Number", + controller: numberController, + style: Theme.of(context).textTheme.subtitle1, + suffixIcon: const Icon(Icons.search_rounded), + textInputAction: TextInputAction.search, + onAction: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + }, + ), + const SizedBox( + height: 8, + ),ATextFormField( + hintText: _subtitle.searchBySn, + controller: snController, + style: Theme.of(context).textTheme.subtitle1, + suffixIcon: const Icon(Icons.search_rounded), + textInputAction: TextInputAction.search, + onAction: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + }, + ), + + ], + ), ), - ), - Expanded( - child: _searchableList.isEmpty - ? NoItemFound( - message: _subtitle.noDeviceFound, - ) - : LazyLoading( - nextPage: _devicesProvider.nextPage, - onLazyLoad: () async { - await _devicesProvider.getDevicesList( - user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); - }, - child: ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: _searchableList.length, - itemBuilder: (listContext, itemIndex) { - return DeviceItem( - device: _searchableList[itemIndex], - onPressed: (device) { - Navigator.of(context).pop(device); - }, - ); + Expanded( + child: _searchableList.isEmpty + ? NoItemFound( + message: _subtitle.noDeviceFound, + ) + : LazyLoading( + nextPage: _devicesProvider.nextPage, + onLazyLoad: () async { + await _devicesProvider.getDevicesList( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); }, - ), - )), - ], + child: ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: _searchableList.length, + itemBuilder: (listContext, itemIndex) { + return DeviceItem( + device: _searchableList[itemIndex], + onPressed: (device) { + Navigator.of(context).pop(device); + }, + ); + }, + ), + )), + ], + ), ), ), floatingActionButton: FloatingActionButton( diff --git a/lib/views/widgets/parts/part_item.dart b/lib/views/widgets/parts/part_item.dart index 63d411e4..c108d07e 100644 --- a/lib/views/widgets/parts/part_item.dart +++ b/lib/views/widgets/parts/part_item.dart @@ -6,8 +6,9 @@ import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart'; class PartItem extends StatefulWidget { final Part part; final Function(Part) onDelete; + final Function(int qty) onEdit; - const PartItem({Key key, this.part, this.onDelete}) : super(key: key); + const PartItem({Key key, this.part, this.onEdit, this.onDelete}) : super(key: key); @override _PartItemState createState() => _PartItemState(); @@ -19,64 +20,73 @@ class _PartItemState extends State { //final _subtitle = AppLocalization.of(context).subtitle; return Column( children: [ - Divider(), + const Divider(), Row( children: [ Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - widget.part.code, - style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 12, fontWeight: FontWeight.bold), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + widget?.part?.code ?? "", + style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 12, fontWeight: FontWeight.bold), + ), ), - ), - AIconButton2( - iconData: Icons.add, - color: Theme.of(context).primaryColor, - onPressed: () { - widget.part.quantity++; - setState(() {}); - }, - ), - AIconButton2( - iconData: Icons.remove, - color: Theme.of(context).primaryColor, - onPressed: widget.part.quantity < 2 - ? null - : () { - widget.part.quantity--; - setState(() {}); - }, - ), - SizedBox( - width: 8 * AppStyle.getScaleFactor(context), - ), - Text( - widget.part.quantity.toString(), - style: Theme.of(context).textTheme.headline6.copyWith( - //fontSize: 12, - //fontWeight: FontWeight.bold - ), - ), - SizedBox( - width: 8 * AppStyle.getScaleFactor(context), - ), - ], - ), - widget.part.name == null - ? SizedBox.shrink() - : Text( - widget.part.name, - style: Theme.of(context).textTheme.caption.copyWith(fontSize: 11, fontWeight: FontWeight.bold), - maxLines: 1, - overflow: TextOverflow.ellipsis, + AIconButton2( + iconData: Icons.add, + color: Theme.of(context).primaryColor, + onPressed: () { + if (widget.onEdit == null) { + ++widget.part.quantity; + } else { + widget.onEdit(++widget.part.quantity); + } + setState(() {}); + }, ), - ], - )), + AIconButton2( + iconData: Icons.remove, + color: Theme.of(context).primaryColor, + onPressed: widget.part.quantity < 2 + ? null + : () { + if (widget.onEdit == null) { + --widget.part.quantity; + } else { + widget.onEdit(--widget.part.quantity); + } + setState(() {}); + }, + ), + SizedBox( + width: 8 * AppStyle.getScaleFactor(context), + ), + Text( + widget.part.quantity.toString(), + style: Theme.of(context).textTheme.headline6.copyWith( + //fontSize: 12, + //fontWeight: FontWeight.bold + ), + ), + SizedBox( + width: 8 * AppStyle.getScaleFactor(context), + ), + ], + ), + widget.part.name == null + ? const SizedBox.shrink() + : Text( + widget.part.name, + style: Theme.of(context).textTheme.caption.copyWith(fontSize: 11, fontWeight: FontWeight.bold), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), AIconButton2( iconData: Icons.close, color: Colors.red, diff --git a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart index 048e113c..27033ba2 100644 --- a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart +++ b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart @@ -43,9 +43,8 @@ class _PentryCalibrationToolFormState extends State { ); } final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/views/widgets/pentry/pentry_info_form.dart b/lib/views/widgets/pentry/pentry_info_form.dart index 290b873d..33ccd2ed 100644 --- a/lib/views/widgets/pentry/pentry_info_form.dart +++ b/lib/views/widgets/pentry/pentry_info_form.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -15,6 +14,8 @@ import 'package:test_sa/views/widgets/status/pentry/pentry_visit_status_mune.dar import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../status/pentry/pentry_status_mune.dart'; + class PentryInfoForm extends StatefulWidget { final Pentry model; final bool enableValidate; @@ -79,16 +80,21 @@ class _PentryInfoFormState extends State { const SizedBox( height: 8, ), - // const ASubTitle("Status"), - // // if(widget.enableValidate && widget.model.status == null) - // // ASubTitle(subtitle.requiredWord,color: Colors.red,), - // const SizedBox(height: 4,), - // PentryStatusMenu( - // initialValue: widget.model.status, - // onSelect: (status){ - // widget.model.status = status; - // }, - // ), + const ASubTitle("Status"), + if (widget.enableValidate && widget.model.status == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + PentryStatusMenu( + initialValue: widget.model.status, + onSelect: (status) { + widget.model.status = status; + }, + ), const SizedBox( height: 8, ), diff --git a/lib/views/widgets/pentry/pentry_pm_kit_form.dart b/lib/views/widgets/pentry/pentry_pm_kit_form.dart index f6ac9b18..3fb154d7 100644 --- a/lib/views/widgets/pentry/pentry_pm_kit_form.dart +++ b/lib/views/widgets/pentry/pentry_pm_kit_form.dart @@ -26,133 +26,66 @@ class _PentryPMKitFormState extends State { Widget build(BuildContext context) { final subtitle = AppLocalization.of(context).subtitle; return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), - itemCount: widget.models.length + 1, - itemBuilder: (context, index) { - if (index == widget.models.length) { - return AButton( - text: subtitle.add, - onPressed: () { - widget.models.add(PMKit()); - setState(() {}); - }, - ); - } - final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ASubTitle("#${index + 1}"), - if (index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: subtitle.delete, - onPressed: () { - widget.models.remove(model); - setState(() {}); - }, - ), - ], - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Item Code"), - const SizedBox( - height: 4, - ), - AutoCompletePartsField( - clearAfterPick: false, - initialValue: (model.itemCode?.name ?? "").toString(), - onPick: (part) { - model.itemCode = Lookup(id: part.id, name: part.code); - }, - ), - const SizedBox( - height: 8, - ), - // const ASubTitle("Item Name"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.itemName ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.text, - // onChange: (value){ - // model.itemName = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("Preparation Time Frame"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.preparationTimeFrame ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.text, - // onChange: (value){ - // model.preparationTimeFrame = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("kit Frequency Demand"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.kitFrequencyDemand ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.text, - // onChange: (value){ - // model.kitFrequencyDemand = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("Availability"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.availability ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.text, - // onChange: (value){ - // model.availability = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("Quantity Needed"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.quantityNeeded ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.number, - // onChange: (value){ - // model.quantityNeeded = value; - // }, - // ), - // const SizedBox(height: 8,), - // const ASubTitle("Quantity Reserved"), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: (model.quantityReserved ?? "").toString(), - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.number, - // onChange: (value){ - // model.quantityReserved = value; - // }, - // ), - // const SizedBox(height: 8,), - Divider( - color: Theme.of(context).textTheme.titleMedium.color, - ), - ], + padding: EdgeInsets.only( + top: 12 * AppStyle.getScaleFactor(context), + left: 12 * AppStyle.getScaleFactor(context), + right: 12 * AppStyle.getScaleFactor(context), + bottom: 100 * AppStyle.getScaleFactor(context) + MediaQuery.of(context).padding.bottom, + ), + itemCount: widget.models.length + 1, + shrinkWrap: true, + itemBuilder: (context, index) { + if (index == widget.models.length) { + return AButton( + text: subtitle.add, + onPressed: () { + widget.models.add(PMKit()); + setState(() {}); + }, ); - }); + } + final model = widget.models[index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ASubTitle("#${index + 1}"), + if (index != 0) + ASmallButton( + color: Theme.of(context).colorScheme.error, + text: subtitle.delete, + onPressed: () { + widget.models.remove(model); + setState(() {}); + }, + ), + ], + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Item Code"), + const SizedBox( + height: 4, + ), + AutoCompletePartsField( + clearAfterPick: false, + initialValue: (model.itemCode?.name ?? "").toString(), + onPick: (part) { + model.itemCode = Lookup(id: part.id, name: part.code); + }, + ), + const SizedBox( + height: 8, + ), + Divider( + color: Theme.of(context).textTheme.titleMedium.color, + ), + ], + ); + }, + ); } } diff --git a/lib/views/widgets/status/assistant_employee_menu.dart b/lib/views/widgets/status/assistant_employee_menu.dart index fa7d9ed8..45f2177b 100644 --- a/lib/views/widgets/status/assistant_employee_menu.dart +++ b/lib/views/widgets/status/assistant_employee_menu.dart @@ -27,7 +27,7 @@ class _SingleAssistantEmployeeMenuState extends State { void didUpdateWidget(covariant AssistantEmployeeMenu oldWidget) { if (widget.initialStatus != null) { final result = widget.statuses?.where((element) { - return element == widget.initialStatus; + return element?.user?.id == widget.initialStatus?.user?.id; }); if (result.isNotEmpty) { _selectedStatus = result.first; @@ -47,7 +47,7 @@ class _SingleAssistantEmployeeMenuState extends State { void initState() { if (widget.initialStatus != null) { final result = widget.statuses?.where((element) { - return element == widget.initialStatus; + return element?.user?.id == widget.initialStatus?.user?.id; }); if (result.isNotEmpty) _selectedStatus = result.first; if (widget.initialStatus?.user?.id != _selectedStatus?.user?.id) { diff --git a/lib/views/widgets/status/gas_refill/gas_status.dart b/lib/views/widgets/status/gas_refill/gas_status.dart index c46e6508..7e7cbac6 100644 --- a/lib/views/widgets/status/gas_refill/gas_status.dart +++ b/lib/views/widgets/status/gas_refill/gas_status.dart @@ -10,8 +10,9 @@ import 'package:test_sa/views/widgets/status/single_status_menu.dart'; class GasStatusMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final bool enabled; - const GasStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + const GasStatusMenu({Key key, this.enabled = true, this.onSelect, this.initialValue}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); @@ -29,6 +30,7 @@ class GasStatusMenu extends StatelessWidget { initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, + enabled: enabled, )); } } diff --git a/lib/views/widgets/status/report/fault_desc_menu.dart b/lib/views/widgets/status/report/fault_desc_menu.dart index 9250c7dd..5229aff5 100644 --- a/lib/views/widgets/status/report/fault_desc_menu.dart +++ b/lib/views/widgets/status/report/fault_desc_menu.dart @@ -26,7 +26,7 @@ class _SingleStatusMenuState extends State { void didUpdateWidget(covariant FaultDescriptionMenu oldWidget) { if (widget.initialStatus != null) { final result = widget.statuses?.where((element) { - return element == widget.initialStatus; + return element.id == widget.initialStatus.id; }); if (result.isNotEmpty) { _selectedStatus = result.first; @@ -44,9 +44,11 @@ class _SingleStatusMenuState extends State { @override void initState() { + if (widget.initialStatus != null) { final result = widget.statuses?.where((element) { - return element == widget.initialStatus; + + return element.id == widget.initialStatus.id; }); if (result.isNotEmpty) _selectedStatus = result.first; if (widget.initialStatus.id != _selectedStatus?.id) { diff --git a/lib/views/widgets/status/report/service_report_equipment_status.dart b/lib/views/widgets/status/report/service_report_equipment_status.dart index 1af9ac9c..95182977 100644 --- a/lib/views/widgets/status/report/service_report_equipment_status.dart +++ b/lib/views/widgets/status/report/service_report_equipment_status.dart @@ -63,7 +63,7 @@ class _ServiceReportEquipmentStatusMenuState extends State(context); + print("report?.callLastSituation:${report?.callLastSituation?.toMap()}"); return LoadingManager( isLoading: _menuProvider.isLoading, isFailedLoading: _menuProvider.calls == null, diff --git a/lib/views/widgets/status/report/service_report_maintenance_situation.dart b/lib/views/widgets/status/report/service_report_maintenance_situation.dart index 936a2284..311581a0 100644 --- a/lib/views/widgets/status/report/service_report_maintenance_situation.dart +++ b/lib/views/widgets/status/report/service_report_maintenance_situation.dart @@ -8,8 +8,14 @@ import 'package:test_sa/views/widgets/status/single_status_menu.dart'; class ServiceReportMaintenanceSituation extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final String woId; - const ServiceReportMaintenanceSituation({Key key, @required this.onSelect, @required this.initialValue}) : super(key: key); + const ServiceReportMaintenanceSituation({ + Key key, + @required this.onSelect, + @required this.initialValue, + @required this.woId, + }) : super(key: key); @override Widget build(BuildContext context) { ServiceReportMaintenanceSituationProvider menuProvider = Provider.of(context); @@ -18,7 +24,7 @@ class ServiceReportMaintenanceSituation extends StatelessWidget { isFailedLoading: menuProvider.operators == null, stateCode: menuProvider.stateCode, onRefresh: () async { - menuProvider.getOperators(); + menuProvider.getOperators(woId); }, child: SingleStatusMenu( initialStatus: initialValue, diff --git a/lib/views/widgets/status/single_status_menu.dart b/lib/views/widgets/status/single_status_menu.dart index dbd2eb70..6a9a9908 100644 --- a/lib/views/widgets/status/single_status_menu.dart +++ b/lib/views/widgets/status/single_status_menu.dart @@ -7,8 +7,9 @@ class SingleStatusMenu extends StatefulWidget { final List statuses; final Lookup initialStatus; final Function(Lookup) onSelect; + final bool enabled; - const SingleStatusMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); + const SingleStatusMenu({Key key, this.enabled = true, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); @override _SingleStatusMenuState createState() => _SingleStatusMenuState(); @@ -82,20 +83,22 @@ class _SingleStatusMenuState extends State { style: Theme.of(context).textTheme.subtitle1, ), style: TextStyle(color: Theme.of(context).primaryColor), - underline: SizedBox.shrink(), - onChanged: (Lookup newValue) { - setState(() { - _selectedStatus = newValue; - }); - widget.onSelect(newValue); - }, + underline: const SizedBox.shrink(), + onChanged: widget.enabled == false + ? null + : (Lookup newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, items: widget.statuses.map>((Lookup value) { return DropdownMenuItem( value: value, child: Text( value.name, style: Theme.of(context).textTheme.subtitle1.copyWith( - color: Theme.of(context).primaryColor, + color: widget.enabled ? Theme.of(context).primaryColor : Colors.grey, fontSize: 11, //fontWeight: FontWeight.bold ), diff --git a/lib/views/widgets/timer/app_timer.dart b/lib/views/widgets/timer/app_timer.dart index 84c5e4e1..9e887905 100644 --- a/lib/views/widgets/timer/app_timer.dart +++ b/lib/views/widgets/timer/app_timer.dart @@ -9,11 +9,13 @@ class AppTimer extends StatefulWidget { final TimerModel timer; final Future Function(TimerModel) onChange; final TextStyle style; + final bool enabled; const AppTimer({ Key key, this.timer, this.onChange, this.style, + this.enabled = true, }) : super(key: key); @override @@ -32,7 +34,7 @@ class _AppTimerState extends State { _startTimer() async { if (!_running) { final time = DateTime.now(); - bool result = await widget.onChange(TimerModel(startAt: time, endAt: null, durationInSecond: _delay)); + bool result = await widget.onChange(TimerModel(startAt: time, endAt: null, durationInSecond: _delay, stopped: false)); if (!result) return; _running = true; @@ -52,7 +54,7 @@ class _AppTimerState extends State { _stopTimer() async { final time = DateTime.now(); final tempStartAt = _startAt.add(Duration(seconds: _delay)); - bool result = await widget.onChange(TimerModel(startAt: tempStartAt, endAt: time, durationInSecond: _delay)); + bool result = await widget.onChange(TimerModel(startAt: tempStartAt, endAt: time, durationInSecond: _delay, stopped: true)); if (!result) return; _running = false; _endAt = time; @@ -99,7 +101,7 @@ class _AppTimerState extends State { child: ElevatedButton( style: ElevatedButton.styleFrom( minimumSize: const Size(1, 1), padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), backgroundColor: _running ? AColors.green[300] : AColors.grey, foregroundColor: Colors.black), - onPressed: _loading ? null : _onPressed, + onPressed: _loading || widget.enabled == false ? null : _onPressed, child: _loading ? const SizedBox.square( dimension: 18, @@ -108,7 +110,7 @@ class _AppTimerState extends State { )) : Row( children: [ - Icon(_running ? Icons.pause : Icons.play_arrow), + if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow), Expanded( child: Center( child: ValueListenableBuilder( @@ -116,7 +118,7 @@ class _AppTimerState extends State { builder: (context, value, _) { return Text( value, - style: widget.style, + style: widget.enabled ? widget.style : widget.style?.copyWith(color: Colors.black54), ); }), ),