Merge remote-tracking branch 'origin/main_latest_merged' into majd_development_new

# Conflicts:
#	lib/views/pages/user/requests/report/edit_service_report.dart
#	lib/views/widgets/equipment/single_device_picker.dart
pull/2/head
nextwo 3 years ago
commit 3737c3b41c

@ -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
// }
}
}

@ -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);

@ -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;
}
}
}

@ -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<List<Device>> 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<Device> _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<List<Device>> 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<Device> _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 [];
// }
// }
}

@ -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

@ -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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<int> 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)

@ -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<int> getOperators() async {
Future<int> 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(

@ -82,7 +82,7 @@ class Asset {
Department department;
String room;
String testsDay;
String purchasingPrice;
num purchasingPrice;
String nbv;
String currency;
String poNo;

@ -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"],

@ -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<String, String> 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<String, dynamic> 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"],

@ -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<GasRefillDetails> 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<String, dynamic> 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"]),
);
}
}

@ -58,7 +58,7 @@ class Pentry {
Map<String, dynamic> toMap(int visitId) {
Map<String, dynamic> 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<contacts.length;i++){
// contacts[i].toMap().forEach((key, value) {
@ -117,7 +117,12 @@ class Pentry {
actualVisitDate: DateTime.tryParse(map["actualDate"] ?? ""),
expectedVisitDate: DateTime.tryParse(map["expectedDate"] ?? ""),
travelingHours: map["travelingHours"],
timer: TimerModel(startAt: DateTime.tryParse(map["startDate"] ?? ""), endAt: DateTime.tryParse(map["endDate"] ?? ""), durationInSecond: (int.tryParse(map["workingHours"] ?? "") ?? 0) * 60 * 60),
timer: TimerModel(
startAt: DateTime.tryParse(map["startDate"] ?? ""),
endAt: DateTime.tryParse(map["endDate"] ?? ""),
durationInSecond: (int.tryParse(map["workingHours"] ?? "") ?? 0) * 60 * 60,
stopped: map["workingHours"] == null ? null : true,
),
// contacts: contacts,
ppmCheckLists: ppmCheckLists,
calibrationTools: calibrationTools,

@ -1,5 +1,6 @@
import 'dart:typed_data';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/device/device.dart';
import 'package:test_sa/models/engineer.dart';
@ -13,10 +14,11 @@ class ServiceReport {
int id;
double operatingHours;
DateTime visitDate;
DateTime endDate;
DateTime startDate;
// DateTime endDate;
// DateTime startDate;
Lookup assetType;
Lookup callLastSituation;
Lookup currentSituation;
Lookup repairLocation;
Engineer engineer;
Lookup equipmentStatus;
@ -25,7 +27,7 @@ class ServiceReport {
int faultDescriptionId;
String workPreformed;
//String workHours;
num workingHours;
double travelingHours;
String invoiceNumber;
String invoiceCode;
@ -40,50 +42,52 @@ class ServiceReport {
String comment;
Uint8List localNurseSignature;
Uint8List localEngineerSignature;
int travelingExpense;
num travelingExpense;
String reviewComment;
FaultDescription faultDescription;
ServiceReport(
{this.id,
this.visitDate,
this.endDate,
this.assetType,
this.equipmentStatus,
this.type,
this.faultDescriptionId,
//this.workHours,
this.travelingHours,
this.parts,
this.engineer,
this.workPreformed,
this.reason,
this.operatingHours,
this.callLastSituation,
this.jobSheetNumber,
this.image,
this.device,
this.invoiceCode,
this.invoiceNumber,
this.quantity = "1",
this.timer,
this.signatureNurse,
this.signatureEngineer,
this.localNurseSignature,
this.localEngineerSignature,
this.comment,
this.repairLocation,
this.travelingExpense,
this.startDate,
this.reviewComment,
this.faultDescription});
ServiceReport({
this.id,
this.visitDate,
// this.endDate,
this.assetType,
this.equipmentStatus,
this.type,
this.faultDescriptionId,
this.workingHours,
this.travelingHours,
this.parts,
this.engineer,
this.workPreformed,
this.reason,
this.operatingHours,
this.callLastSituation,
this.currentSituation,
this.jobSheetNumber,
this.image,
this.device,
this.invoiceCode,
this.invoiceNumber,
this.quantity = "1",
this.timer,
this.signatureNurse,
this.signatureEngineer,
this.localNurseSignature,
this.localEngineerSignature,
this.comment,
this.repairLocation,
this.travelingExpense,
// this.startDate,
this.reviewComment,
this.faultDescription,
});
Map<String, dynamic> toMap(ServiceRequest request) {
Map<String, dynamic> _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<bool> 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'],
);
}

@ -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<String, dynamic> toJson() {
final map = <String, dynamic>{};
@ -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();
}

@ -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,

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

@ -86,11 +86,15 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
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(

@ -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<UpdateDeviceTransfer> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
_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<UpdateDeviceTransfer> {
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<UpdateDeviceTransfer> {
GasStatusMenu(
initialValue: _formModel.status,
onSelect: (status) {
if (status == null) return;
_formModel.status = status;
setState(() {});
},

@ -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<Login> {
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 {

@ -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<CreateSubWorkOrderPage> {
@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<ServiceRequestFaultDescriptionProvider>(context, listen: false).reset();
assetTypesProvider = Provider.of<ServiceStatusProvider>(context, listen: false);
_callRequestForWorkOrder = await Provider.of<ServiceRequestsProvider>(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<ServiceRequestsProvider>(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<ServiceRequestsProvider>(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),
));
}
}
},
),
],
),
),
);
}

@ -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<SearchSubWorkOrderPage> {
bool _isLoading = false;
String _callerId = "", _site = "";
Lookup _dateOperator;
@override
void initState() {
super.initState();
if (context.mounted) {
Provider.of<ServiceReportMaintenanceSituationProvider>(context, listen: false).reset();
}
}
@override
Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context).subtitle;
@ -120,12 +131,16 @@ class _SearchSubWorkOrderPageState extends State<SearchSubWorkOrderPage> {
_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<SearchSubWorkOrderPage> {
_isLoading = false;
setState(() {});
if (serviceRequestsProvider.stateCode >= 200 && serviceRequestsProvider.stateCode < 300) {
Fluttertoast.showToast(msg: _subtitle.requestCompleteSuccessfully);
Navigator.push(
context,
MaterialPageRoute(

@ -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<SparePartsBottomSheet> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final SearchWorkOrder _workOrder = SearchWorkOrder();
bool _validate = false;
@override
void initState() {
@ -26,6 +30,12 @@ class _SparePartsBottomSheetState extends State<SparePartsBottomSheet> {
_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<SparePartsBottomSheet> {
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),
],
),
),
),

@ -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<WorkOrderDetailsBottomShee
@override
void initState() {
super.initState();
_workOrder.copyFrom(widget.subWorkOrder);
if (context.mounted) {
Provider.of<ServiceReportMaintenanceSituationProvider>(context, listen: false).reset();
}
}
@override
@ -66,81 +72,29 @@ class _WorkOrderDetailsBottomSheetState extends State<WorkOrderDetailsBottomShee
const ASubTitle("Assistant Employee"),
const SizedBox(height: 4),
ServiceReportAssistantEmployeeMenu(
initialValue: (_workOrder.assistantEmployees?.isEmpty ?? false) ? null : _workOrder.assistantEmployees?.first,
initialValue: (_workOrder.assistantEmployees?.isNotEmpty ?? false) ? _workOrder.assistantEmployees?.first : null,
onSelect: (assistantsEmployee) {
_workOrder.assistantEmployees = [assistantsEmployee];
},
),
const SizedBox(height: 8),
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: DateTime.tryParse(_workOrder.startofWorkTime ?? ""),
from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now(),
onDateTimePicker: (date) {
_workOrder.startofWorkTime = date?.toIso8601String();
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: DateTime.tryParse(_workOrder.endofWorkTime ?? ""),
from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now(),
onDateTimePicker: (date) {
_workOrder.endofWorkTime = date?.toIso8601String();
setState(() {});
},
),
],
child: AppTimer(
timer: _workOrder.timer,
onChange: (timer) async {
_workOrder.timer = timer;
_workOrder.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(
textAlign: TextAlign.center,
labelText: _workOrder.startofWorkTime == null
? "0"
: ((DateTime.tryParse(_workOrder.endofWorkTime ?? "")?.difference(DateTime.tryParse(_workOrder.startofWorkTime ?? ""))?.inMinutes ?? 0) / 60)
?.toStringAsFixed(2)
?.toString() ??
"0",
enable: false,
style: Theme.of(context).textTheme.titleMedium,
// validator: (value) => 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<WorkOrderDetailsBottomShee
_workOrder.calllastSituation = status;
}
},
woId: widget.subWorkOrder?.callRequest?.id?.toString(),
),
const SizedBox(height: 8),
const ASubTitle("Repair Location"),
@ -199,6 +154,13 @@ class _WorkOrderDetailsBottomSheetState extends State<WorkOrderDetailsBottomShee
AButton(
text: subtitle.submit,
onPressed: () async {
if (_workOrder?.workingHours == null) {
await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started");
return;
} else if ((_workOrder?.timer?.stopped ?? false) == false) {
await Fluttertoast.showToast(msg: "Stop The Timer");
return;
}
_formKey.currentState.save();
widget.subWorkOrder.copyFrom(_workOrder);
Navigator.pop(context);

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:test_sa/models/lookup.dart';
import '../../../controllers/localization/localization.dart';
import '../../../models/service_request/search_work_order.dart';
@ -8,7 +9,9 @@ import '../../app_style/sizing.dart';
class WorkOrderDetails extends StatelessWidget {
final SearchWorkOrder item;
WorkOrderDetails({@required this.item,Key key}) : super(key: key);
Lookup assetType;
WorkOrderDetails({@required this.item, this.assetType, Key key}) : super(key: key);
Subtitle _subtitle;
@override
@ -30,15 +33,15 @@ class WorkOrderDetails extends StatelessWidget {
),
child: Column(
children: [
_buildRow(_subtitle.callId, item.callRequest?.id?.toString()??"", context),
_buildRow(_subtitle.assetNumber, item.callRequest?.asset?.assetNumber??"", context),
_buildRow(_subtitle.callId, item.callRequest?.id?.toString() ?? "", context),
_buildRow(_subtitle.assetNumber, item.callRequest?.asset?.assetNumber ?? "", context),
_buildRow("WO No", item.workOrderNo, context),
_buildRow(_subtitle.assetName, item.callRequest?.asset?.assetNumber??'', context),
_buildRow(_subtitle.department, item.callRequest?.asset?.department??'', context),
_buildRow(_subtitle.assetSN, item.callRequest?.asset?.assetSerialNo??'', context),
_buildRow(_subtitle.model, item.callRequest?.asset?.modelDefinition?.modelName??"", context),
_buildRow("Manufacturer", item.callRequest?.asset?.modelDefinition?.manufacturerName??"", context),
_buildRow(_subtitle.site, item.callRequest?.asset?.site?.custName??"", context),
_buildRow(_subtitle.assetName, item.callRequest?.asset?.assetNumber ?? '', context),
_buildRow(_subtitle.department, item.callRequest?.asset?.department ?? '', context),
_buildRow(_subtitle.assetSN, item.callRequest?.asset?.assetSerialNo ?? '', context),
_buildRow(_subtitle.model, item.callRequest?.asset?.modelDefinition?.modelName ?? "", context),
_buildRow("Manufacturer", item.callRequest?.asset?.modelDefinition?.manufacturerName ?? "", context),
_buildRow(_subtitle.site, item.callRequest?.asset?.site?.custName ?? "", context),
],
),
),
@ -53,16 +56,18 @@ class WorkOrderDetails extends StatelessWidget {
),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
),
child: _buildRow("Asset Type", item.assetType?.name??"", context),)
child: _buildRow("Asset Type", assetType?.name ?? (item.assetType?.name ?? ""), context),
)
],
);
}
Widget _buildRow(String title, String value, BuildContext context){
Widget _buildRow(String title, String value, BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
title+" : ",
title + " : ",
style: Theme.of(context).textTheme.subtitle2.copyWith(fontWeight: FontWeight.bold),
),
//if (item.clientName != null)

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
@ -29,6 +31,7 @@ import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/hospitals_provider.dart';
import '../../../../models/enums/user_types.dart';
import '../../../widgets/e_signature/e_signature.dart';
class RequestGasRefill extends StatefulWidget {
static const String id = "/request-gas-refill";
@ -150,6 +153,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
}
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<RequestGasRefill> {
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<RequestGasRefill> {
),
],
),
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<RequestGasRefill> {
},
);
}),
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)
],
),
),

@ -212,7 +212,7 @@ class _LandPageState extends State<LandPage> {
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",

@ -306,7 +306,7 @@ class CreateRequestPageState extends State<CreateRequestPage> {
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;
}

@ -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<CreateServiceReport> 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<CreateServiceReport> 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<CreateServiceReport> 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<CreateServiceReport> 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<CreateServiceReport> 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<CreateServiceReport> 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<CreateServiceReport> with TickerPr
// setState(() {});
// return;
// }
if (!_serviceReport.validate()) return;
if (!(await _serviceReport.validate())) {
setState(() {});
return;
}
_formKey.currentState.save();
_isLoading = true;

@ -31,6 +31,8 @@ class _FutureServiceReportState extends State<FutureServiceReport> {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(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<ServiceReport>(
future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: _subtitle),

@ -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,

@ -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<EditPentry> 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<EditPentry> 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<EditPentry> with SingleTickerProviderStateM
PentryInfoForm(
model: _pentry,
enableValidate: _validate,
)
),
],
),
Align(

@ -21,7 +21,7 @@ class DeviceTransferInfoSection extends StatelessWidget {
info: info.client.name,
),
RequestInfoRow(
title: subtitle.unite,
title: subtitle.department,
info: info.department.name,
),
RequestInfoRow(

@ -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(

@ -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,
),

@ -33,20 +33,20 @@ class _SingleDevicePickerState extends State<SingleDevicePicker> {
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<Device> 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<Device> 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<SingleDevicePicker> {
_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(

@ -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<PartItem> {
//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,

@ -43,9 +43,8 @@ class _PentryCalibrationToolFormState extends State<PentryCalibrationToolForm> {
);
}
final model = widget.models[index];
return ListView(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,

@ -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<PentryInfoForm> {
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,
),

@ -26,133 +26,66 @@ class _PentryPMKitFormState extends State<PentryPMKitForm> {
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,
),
],
);
},
);
}
}

@ -27,7 +27,7 @@ class _SingleAssistantEmployeeMenuState extends State<AssistantEmployeeMenu> {
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<AssistantEmployeeMenu> {
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) {

@ -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<SettingProvider>(context);
@ -29,6 +30,7 @@ class GasStatusMenu extends StatelessWidget {
initialStatus: initialValue,
statuses: menuProvider.items,
onSelect: onSelect,
enabled: enabled,
));
}
}

@ -26,7 +26,7 @@ class _SingleStatusMenuState extends State<FaultDescriptionMenu> {
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<FaultDescriptionMenu> {
@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) {

@ -63,7 +63,7 @@ class _ServiceReportEquipmentStatusMenuState extends State<ServiceReportEquipmen
callsLastSituationsProvider.getCalls(
user: userProvider.user,
host: settingProvider.host,
serviceStatus: status.id,
serviceStatus: status?.id,
id: widget.report?.id,
woId: widget.request?.id,
typeName: widget.report?.type?.name,

@ -14,6 +14,7 @@ class ServiceReportLastCallsMenu extends StatelessWidget {
@override
Widget build(BuildContext context) {
ServiceReportLastCallsProvider _menuProvider = Provider.of<ServiceReportLastCallsProvider>(context);
print("report?.callLastSituation:${report?.callLastSituation?.toMap()}");
return LoadingManager(
isLoading: _menuProvider.isLoading,
isFailedLoading: _menuProvider.calls == null,

@ -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<ServiceReportMaintenanceSituationProvider>(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,

@ -7,8 +7,9 @@ class SingleStatusMenu extends StatefulWidget {
final List<Lookup> 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<SingleStatusMenu> {
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<DropdownMenuItem<Lookup>>((Lookup value) {
return DropdownMenuItem<Lookup>(
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
),

@ -9,11 +9,13 @@ class AppTimer extends StatefulWidget {
final TimerModel timer;
final Future<bool> 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<AppTimer> {
_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<AppTimer> {
_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<AppTimer> {
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<AppTimer> {
))
: Row(
children: [
Icon(_running ? Icons.pause : Icons.play_arrow),
if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow),
Expanded(
child: Center(
child: ValueListenableBuilder<String>(
@ -116,7 +118,7 @@ class _AppTimerState extends State<AppTimer> {
builder: (context, value, _) {
return Text(
value,
style: widget.style,
style: widget.enabled ? widget.style : widget.style?.copyWith(color: Colors.black54),
);
}),
),

Loading…
Cancel
Save