Merge branch 'design_3.0_transfer_request_new_flow' into demo_branch

# Conflicts:
#	lib/controllers/api_routes/urls.dart
#	lib/l10n/app_ar.arb
#	lib/l10n/app_en.arb
#	lib/models/new_models/gas_refill_model.dart
#	lib/new_views/common_widgets/default_app_bar.dart
#	lib/views/pages/user/gas_refill/gas_refill_details.dart
#	lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart
design_3.0_task_module_new
WaseemAbbasi22 7 months ago
commit ef6c14ba55

@ -169,20 +169,27 @@ class URLs {
static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get
static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get
static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // get static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // get
static get requestGasRefill => "$_baseUrl/GasRefill/AddGasRefill"; // get static get requestGasRefill => "$_baseUrl/GasRefill/AddGasRefillFromMobile"; // get
static get updateGasRefill => "$_baseUrl/GasRefill/UpdateGasRefill"; // get static get updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get
static get getGasRefill => "$_baseUrl/GasRefill/GetGasRefills"; // get static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // get
// static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get older endpoint..
static get getGasRefillById => "$_baseUrl/GasRefill/GetGasRefillById"; // get static get getGasRefillById => "$_baseUrl/GasRefill/GetGasRefillById"; // get
static get getGasRefillComments => "$_baseUrl/GasRefill/GetHistoryComments"; // get static get getGazRefillComments => "$_baseUrl/GazRefill/GetHistoryComments"; // get
static get addGasRefillComment => "$_baseUrl/GasRefill/AddHistoryComment"; // add static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add
static get updateGasRefillByEngineer => "$_baseUrl/GasRefill/UpdateGasRefillByEngineer"; // update
//device transfer //device transfer
static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get
static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get // static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get
static get getDeviceTransfer => "$_baseUrl/AssetTransfer/GetAssetTransfers"; // get static get getDeviceTransfer => "$_baseUrl/AssetTransfer/GetAssetTransfers"; // get
static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get // static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get
static get getAssetTransferStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=406"; // get static get getAssetTransferStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=406"; // get
//Asset transfer new Apis
static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferNewById"; // get
static get createAssetTransferRequest => "$_baseUrl/AssetTransfer/AddAssetTransferMobileNew";// post
static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateEngineerAssetTransferNew"; // get
// employee // employee
static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get
static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get

@ -6,8 +6,10 @@ import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/user.dart';
import '../../../models/hospital.dart'; import '../../../models/hospital.dart';
@ -120,15 +122,27 @@ class AssetTransferProvider extends ChangeNotifier {
} }
} }
Future<PendingAssetServiceRequest?> checkAssetPendingRequest(int assetId) async {
Response response;
try {
response = await ApiManager.instance.post(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId",body: {});
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {}
return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]);
} catch (error) {
"Please Try Again\n$error".addTranslation.showToast;
return null;
}
}
Future<void> createRequest({ Future<void> createRequest({
required BuildContext context, required BuildContext context,
required AssetTransfer assetDestination, required AssetTransfer model,
required Asset asset,
}) async { }) async {
Response response; Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: assetDestination.transferBody(asset: asset)); response = await ApiManager.instance.post(URLs.createAssetTransferRequest, body: model.toCreateAssetTransferJson());
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
if (items != null) { if (items != null) {
@ -148,29 +162,15 @@ class AssetTransferProvider extends ChangeNotifier {
} }
} }
Future<int> updateRequest(BuildContext context, {required AssetTransfer assetTransfer, required bool isSender}) async { Future<int> updateRequest(BuildContext context, {required AssetTransfer model}) async {
Response response; Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.put(URLs.updateDeviceTransfer, body: assetTransfer.toJson()); response = await ApiManager.instance.post(URLs.updateDeviceTransfer, body: model.toEngineerUpdateJson());
//print(response.body);
// print("${newModel.engSignature}.png");
// response = await post(
// Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"),
// body: body,
// );
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
reset(); reset();
// Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.of(context).pop(); Navigator.of(context).pop();
// oldModel.fromDeviceTransfer(
// DeviceTransfer.fromJson(
// json.decode(utf8.decode(response.bodyBytes))[0]
// )
// );
notifyListeners(); notifyListeners();
} else { } else {
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}"); Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}");
@ -184,8 +184,5 @@ class AssetTransferProvider extends ChangeNotifier {
} }
} }
bool _isLocalUrl(String? url) {
if (url?.isEmpty ?? true) return false;
return url!.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
}
} }

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
@ -9,6 +10,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/hospital.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart'; import 'package:test_sa/models/new_models/gas_refill_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart'; import '../../../new_views/common_widgets/app_lazy_loading.dart';
@ -26,6 +28,7 @@ class GasRefillProvider extends ChangeNotifier {
building = null; building = null;
floor = null; floor = null;
department = null; department = null;
gasRefillAttachments.clear();
} }
// state code of current request to defied error message // state code of current request to defied error message
@ -43,13 +46,24 @@ class GasRefillProvider extends ChangeNotifier {
// done _loading = true // done _loading = true
// failed _loading = false // failed _loading = false
bool isLoading = false; bool isLoading = false;
List<File> _gasRefillAttachments = [];
List<File> get gasRefillAttachments => _gasRefillAttachments;
set gasRefillAttachments(List<File> value) {
_gasRefillAttachments = value;
notifyListeners();
}
Future<GasRefillModel?> getGasRefillObjectById(num id) async { Future<GasRefillModel?> getGasRefillObjectById(num id) async {
try { try {
Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id"); Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
return GasRefillModel.fromJson(json.decode(response.body)["data"]);
return GasRefillModel.fromJson(json.decode(response.body)["data"]);
} else { } else {
return null; return null;
} }
@ -58,6 +72,7 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
/// return -2 if request in progress /// return -2 if request in progress
/// return -1 if error happen when sending request /// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403 /// return state code if request complete may be 200, 404 or 403
@ -105,20 +120,14 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
Future<void> createModel({ Future<void> addGasRefillRequest({
required BuildContext context, required BuildContext context,
required User user,
required GasRefillModel model, required GasRefillModel model,
}) async { }) async {
late Response response; late Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
final Map<String, dynamic> body = { response = await ApiManager.instance.post(URLs.requestGasRefill, body: model.toJson());
"uid": user.id.toString(),
"token": user.token ?? "",
};
body.addAll(model.toJson());
response = await ApiManager.instance.post(URLs.requestGasRefill, body: body);
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
if (items != null) { if (items != null) {
@ -137,6 +146,23 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
Future<int> updateGasRefill({required int status, required GasRefillModel model}) async {
isLoading = true;
Response response;
try {
response = await ApiManager.instance.post(URLs.updateGasRefillByEngineer, body: model.toUpdateEngineerPayload(status: status));
stateCode = response.statusCode;
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
Future<int> updateModel({ Future<int> updateModel({
required String host, required String host,
required User user, required User user,
@ -145,7 +171,7 @@ class GasRefillProvider extends ChangeNotifier {
}) async { }) async {
Map<String, dynamic> body = { Map<String, dynamic> body = {
"id": newModel.id, "id": newModel.id,
"gazRefillNo": newModel.gazRefillNo ?? "", "gasRefillNo": newModel.gasRefillNo ?? "",
"status": newModel.status?.toJson(), "status": newModel.status?.toJson(),
//"expectedDate": newModel.expectedDate?.toIso8601String(), //"expectedDate": newModel.expectedDate?.toIso8601String(),
"expectedTime": newModel.expectedDate, "expectedTime": newModel.expectedDate,
@ -164,7 +190,7 @@ class GasRefillProvider extends ChangeNotifier {
"comment": newModel.comment, "comment": newModel.comment,
}; };
body["gazRefillDetails"] = newModel.gazRefillDetails! body["gasRefillDetails"] = newModel.gasRefillDetails!
.map((model) => { .map((model) => {
"gasType": model.gasType?.toJson(), "gasType": model.gasType?.toJson(),
"cylinderSize": model.cylinderSize?.toJson(), "cylinderSize": model.cylinderSize?.toJson(),

@ -550,6 +550,9 @@
"supplierName": "اسم المورد", "supplierName": "اسم المورد",
"externalEngineerName": "اسم المهندس الخارجي", "externalEngineerName": "اسم المهندس الخارجي",
"telephone": "الهاتف", "telephone": "الهاتف",
"transferAsset": "نقل الأصل",
"createAssetTransferRequest": "إنشاء طلب نقل أصل"
"telephone": "الهاتف",
"arrivedDate": "تاريخ الوصول", "arrivedDate": "تاريخ الوصول",
"closedDate": "تاريخ الإغلاق", "closedDate": "تاريخ الإغلاق",
"since": "منذ", "since": "منذ",

@ -553,6 +553,9 @@
"supplierName": "Supplier Name", "supplierName": "Supplier Name",
"externalEngineerName": "External Engineer Name", "externalEngineerName": "External Engineer Name",
"telephone": "Telephone", "telephone": "Telephone",
"transferAsset": "Transfer Asset",
"createAssetTransferRequest": "Create Asset Transfer Request"
"telephone": "Telephone",
"arrivedDate": "Arrived Date", "arrivedDate": "Arrived Date",
"closedDate": "Closed Date", "closedDate": "Closed Date",
"since": "Since", "since": "Since",

@ -68,9 +68,10 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d
import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart';
import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart';
import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart';
import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart';
import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart';
import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart';
import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart';
import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart';
import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_page.dart';
@ -293,6 +294,7 @@ class MyApp extends StatelessWidget {
ServiceRequestsPage.id: (_) => const ServiceRequestsPage(), ServiceRequestsPage.id: (_) => const ServiceRequestsPage(),
//ReportIssuesPage.id: (_) => ReportIssuesPage(), //ReportIssuesPage.id: (_) => ReportIssuesPage(),
RequestGasRefill.id: (_) => const RequestGasRefill(), RequestGasRefill.id: (_) => const RequestGasRefill(),
GasRefillForm.id: (_) => const GasRefillForm(),
CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(),
CreateNewRequest.id: (_) => const CreateNewRequest(), CreateNewRequest.id: (_) => const CreateNewRequest(),
// SingleHospitalPicker.id: (_) => SingleHospitalPicker(), // SingleHospitalPicker.id: (_) => SingleHospitalPicker(),
@ -303,7 +305,7 @@ class MyApp extends StatelessWidget {
// PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), // PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(),
PpmPage.id: (_) => const PpmPage(), PpmPage.id: (_) => const PpmPage(),
TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), TrackGasRefillPage.id: (_) => const TrackGasRefillPage(),
RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), CreateAssetTransferRequest.id: (_) => const CreateAssetTransferRequest(),
TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(),
// todo remove this class after work // todo remove this class after work

@ -2,86 +2,100 @@ import 'package:flutter/src/widgets/framework.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/assistant_employee.dart';
import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/ppm.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
import 'asset_transfer_attachment.dart'; import 'asset_transfer_attachment.dart';
class AssetTransfer { class AssetTransfer {
AssetTransfer( AssetTransfer({
{this.id, this.id,
this.transferNo, this.transferNo,
this.transferCode, this.transferType,
this.assetId, this.transferCode,
this.destSiteId, this.assetId,
this.destBuildingId, this.destSiteId,
this.destFloorId, this.destBuildingId,
this.destDepartmentId, this.destFloorId,
this.destRoomId, this.destDepartmentId,
this.senderSiteId, this.destRoomId,
this.senderBuildingId, this.senderSiteId,
this.senderFloorId, this.senderBuildingId,
this.senderDepartmentId, this.senderFloorId,
this.senderRoom, this.senderDepartmentId,
this.senderAssignedEmployeeId, this.senderRoom,
this.senderMachineStatusId, this.senderAssignedEmployeeId,
this.senderComment, this.senderMachineStatusId,
this.comment, this.senderComment,
this.receiverEndUserId, this.comment,
this.receiverEndUserName, this.receiverEndUserId,
this.senderStartDate, this.receiverEndUserName,
this.senderEndDate, this.senderStartDate,
this.senderWorkingHours, this.senderEndDate,
this.senderTravelingHours, this.senderWorkingHours,
this.senderEngSignature, this.senderTravelingHours,
this.senderAttachments, this.senderEngSignature,
this.receiverAssignedEmployeeId, this.senderAttachments,
this.receiverMachineStatusId, this.receiverAssignedEmployeeId,
this.receiverComment, this.receiverMachineStatusId,
this.receiverStartDate, this.receiverComment,
this.receiverEndDate, this.receiverStartDate,
this.receiverWorkingHours, this.receiverEndDate,
this.receiverTravelingHours, this.receiverWorkingHours,
this.receiverEngSignature, this.receiverTravelingHours,
this.receiverAttachments, this.receiverEngSignature,
this.assetNumber, this.receiverAttachments,
this.assetName, this.attachments,
this.manufacturerName, this.assetNumber,
this.modelName, this.assetName,
this.assetSerialNo, this.manufacturerName,
this.destDepartmentName, this.modelName,
this.destBuildingName, this.assetSerialNo,
this.applied, this.destDepartmentName,
this.extensionNo, this.destBuildingName,
this.name, this.applied,
this.employeeId, this.isSender,
this.createdDate, this.extensionNo,
this.createdOn, this.name,
this.destFloorName, this.employeeId,
this.destSiteName, this.createdDate,
this.manufacturerId, this.createdOn,
this.modelId, this.destFloorName,
this.modifiedOn, this.destSiteName,
this.receiverAssignedEmployeeName, this.manufacturerId,
this.receiverEngSignatureUrl, this.modelId,
this.receiverMachineStatusName, this.modifiedOn,
this.senderAssignedEmployeeName, this.receiverAssignedEmployeeName,
this.senderBuildingName, this.receiverEngSignatureUrl,
this.senderDepartmentName, this.receiverMachineStatusName,
this.senderEngSignatureUrl, this.senderAssignedEmployeeName,
this.senderFloorName, this.senderBuildingName,
this.senderMachineStatusName, this.senderDepartmentName,
this.senderSiteName, this.senderEngSignatureUrl,
this.supplierId, this.senderFloorName,
this.supplierName, this.senderMachineStatusName,
this.senderVisitTimers, this.senderSiteName,
this.receiverVisitTimers, this.supplierId,
this.tbsTimer}); this.supplierName,
this.senderVisitTimers,
this.receiverVisitTimers,
this.assetTransferEngineerTimers,
this.tbsTimer,
this.timerModelList,
this.assistantEmployees,
this.modelAssistantEmployees,
this.assetTransferAssistantEmployeesReceiver,
this.assetTransferAssistantEmployeesSender,
this.statusValue,
});
AssetTransfer.fromJson(dynamic json) { AssetTransfer.fromJson(dynamic json) {
id = json['id']; id = json['id'];
transferNo = json['transferNo']; transferNo = json['transferNo'];
transferCode = json['transferCode']; transferCode = json['transferCode'];
transferType = json["transferType"] == null ? null : Lookup.fromJson(json["transferType"]);
assetId = json['assetId']; assetId = json['assetId'];
destSiteId = json['destSiteId']; destSiteId = json['destSiteId'];
destBuildingId = json['destBuildingId']; destBuildingId = json['destBuildingId'];
@ -130,6 +144,19 @@ class AssetTransfer {
receiverVisitTimers!.add(VisitTimers.fromJson(v)); receiverVisitTimers!.add(VisitTimers.fromJson(v));
}); });
} }
if (json['assetTransferAssistantEmployeesSender'] != null) {
assetTransferAssistantEmployeesSender = [];
json['assetTransferAssistantEmployeesSender'].forEach((v) {
assetTransferAssistantEmployeesSender!.add(AssetTransferAssistantEmployees.fromJson(v));
});
}
if (json['assetTransferAssistantEmployeesReceiver'] != null) {
assetTransferAssistantEmployeesReceiver = [];
json['assetTransferAssistantEmployeesReceiver'].forEach((v) {
assetTransferAssistantEmployeesReceiver!.add(AssetTransferAssistantEmployees.fromJson(v));
});
}
tbsTimer = TimerModel(); tbsTimer = TimerModel();
// try { // try {
// receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? "")); // receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? ""));
@ -186,6 +213,8 @@ class AssetTransfer {
num? id; num? id;
num? transferNo; num? transferNo;
String? transferCode; String? transferCode;
int? statusValue;
Lookup? transferType;
String? assetSerialNo; String? assetSerialNo;
num? assetId; num? assetId;
String? assetNumber; String? assetNumber;
@ -216,6 +245,7 @@ class AssetTransfer {
String? senderTravelingHours; String? senderTravelingHours;
String? senderEngSignature; String? senderEngSignature;
List<AssetTransferAttachment>? senderAttachments; List<AssetTransferAttachment>? senderAttachments;
List<AssetTransferAttachment>? attachments;
String? receiverAssignedEmployeeId; String? receiverAssignedEmployeeId;
num? receiverMachineStatusId; num? receiverMachineStatusId;
String? receiverComment; String? receiverComment;
@ -242,6 +272,7 @@ class AssetTransfer {
String? receiverMachineStatusName; String? receiverMachineStatusName;
String? receiverEngSignatureUrl; String? receiverEngSignatureUrl;
bool? applied; bool? applied;
bool? isSender;
dynamic extensionNo; dynamic extensionNo;
String? employeeId; String? employeeId;
String? name; String? name;
@ -250,12 +281,21 @@ class AssetTransfer {
String? modifiedOn; String? modifiedOn;
List<VisitTimers>? senderVisitTimers; List<VisitTimers>? senderVisitTimers;
List<VisitTimers>? receiverVisitTimers; List<VisitTimers>? receiverVisitTimers;
List<VisitTimers>? assetTransferEngineerTimers;
List<TimerModel>? timerModelList = [];
List<AssistantEmployees>? assistantEmployees;
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesSender;
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesReceiver;
AssetTransferAssistantEmployees? modelAssistantEmployees;
TimerModel? tbsTimer = TimerModel(); TimerModel? tbsTimer = TimerModel();
AssetTransfer copyWith( AssetTransfer copyWith(
{num? id, {num? id,
num? transferNo, num? transferNo,
String? transferCode, String? transferCode,
Lookup? transferType,
num? assetId, num? assetId,
num? destSiteId, num? destSiteId,
num? destBuildingId, num? destBuildingId,
@ -326,6 +366,7 @@ class AssetTransfer {
id: id ?? this.id, id: id ?? this.id,
transferNo: transferNo ?? this.transferNo, transferNo: transferNo ?? this.transferNo,
transferCode: transferCode ?? this.transferCode, transferCode: transferCode ?? this.transferCode,
transferType: transferType ?? this.transferType,
assetId: assetId ?? this.assetId, assetId: assetId ?? this.assetId,
destSiteId: destSiteId ?? this.destSiteId, destSiteId: destSiteId ?? this.destSiteId,
destBuildingId: destBuildingId ?? this.destBuildingId, destBuildingId: destBuildingId ?? this.destBuildingId,
@ -375,10 +416,10 @@ class AssetTransfer {
receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName, receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName,
receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl, receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl,
applied: applied ?? this.applied, applied: applied ?? this.applied,
extensionNo: extensionNo??this.extensionNo, extensionNo: extensionNo ?? this.extensionNo,
employeeId: employeeId??this.employeeId, employeeId: employeeId ?? this.employeeId,
name: name??this.name, name: name ?? this.name,
createdDate: createdDate??this.createdDate, createdDate: createdDate ?? this.createdDate,
createdOn: createdOn ?? this.createdOn, createdOn: createdOn ?? this.createdOn,
modifiedOn: modifiedOn ?? this.modifiedOn, modifiedOn: modifiedOn ?? this.modifiedOn,
assetSerialNo: assetSerialNo ?? this.assetSerialNo, assetSerialNo: assetSerialNo ?? this.assetSerialNo,
@ -472,6 +513,44 @@ class AssetTransfer {
return map; return map;
} }
Map<String, dynamic> toCreateAssetTransferJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['assetId'] = assetId;
map['transferTypeId'] = transferType?.id;
map['destSiteId'] = destSiteId;
map['destSiteId'] = destSiteId;
map['destBuildingId'] = destBuildingId;
map['destFloorId'] = destFloorId;
map['destDepartmentId'] = destDepartmentId;
map['destRoomId'] = destRoomId;
map['comment'] = comment;
if (attachments != null) {
map['attachment'] = attachments!.map((v) => v.toJson()).toList();
}
return map;
}
Map<String, dynamic> toEngineerUpdateJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['statusValue'] = statusValue;
map['isSender'] = isSender;
map['techComment'] = comment;
map['assetTransferAssistantEmployees'] = modelAssistantEmployees;
map['assetTransferEngineerTimers'] = assetTransferEngineerTimers;
if (attachments != null) {
map['attachments'] = attachments!.map((v) => v.toJson()).toList();
}
if (assetTransferEngineerTimers != null) {
map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList();
}
if (modelAssistantEmployees != null) {
map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()];
}
return map;
}
Map<String, dynamic> transferBody({Asset? asset}) { Map<String, dynamic> transferBody({Asset? asset}) {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['id'] = 0; map['id'] = 0;
@ -526,6 +605,7 @@ class AssetTransfer {
if (assetTransfer == null) return; if (assetTransfer == null) return;
id = assetTransfer.id; id = assetTransfer.id;
transferNo = assetTransfer.transferNo; transferNo = assetTransfer.transferNo;
transferType = assetTransfer.transferType;
transferCode = assetTransfer.transferCode; transferCode = assetTransfer.transferCode;
assetId = assetTransfer.assetId; assetId = assetTransfer.assetId;
destSiteId = assetTransfer.destSiteId; destSiteId = assetTransfer.destSiteId;
@ -591,6 +671,8 @@ class AssetTransfer {
manufacturerName = assetTransfer.manufacturerName; manufacturerName = assetTransfer.manufacturerName;
senderVisitTimers = assetTransfer.senderVisitTimers; senderVisitTimers = assetTransfer.senderVisitTimers;
receiverVisitTimers = assetTransfer.receiverVisitTimers; receiverVisitTimers = assetTransfer.receiverVisitTimers;
assetTransferAssistantEmployeesReceiver = assetTransfer.assetTransferAssistantEmployeesReceiver;
assetTransferAssistantEmployeesSender = assetTransfer.assetTransferAssistantEmployeesSender;
} }
Future<bool> validate(BuildContext context) async { Future<bool> validate(BuildContext context) async {
@ -613,3 +695,42 @@ class AssetTransfer {
return true; return true;
} }
} }
class AssetTransferAssistantEmployees {
DateTime? startDate;
DateTime? endDate;
double? workingHours;
String? techComment;
String? employeeId;
String? employeeNumber;
String? employeeName;
String? email;
String? mobileNo;
dynamic extension;
AssetTransferAssistantEmployees(
{this.startDate, this.endDate, this.workingHours, this.techComment, this.employeeId, this.employeeName, this.employeeNumber, this.email, this.extension, this.mobileNo});
AssetTransferAssistantEmployees.fromJson(Map<String, dynamic> json) {
startDate = json['startDate'] != null ? DateTime.parse(json['startDate']) : null;
endDate = json['endDate'] != null ? DateTime.parse(json['endDate']) : null;
workingHours = json['workingHours'];
techComment = json['techComment'];
employeeId = json['employeeId'];
employeeNumber = json['employeeNumber'];
employeeName = json['employeeName'];
email = json['email'];
mobileNo = json['mobileNo'];
extension = json['extension'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['startDate'] = startDate?.toIso8601String();
data['endDate'] = endDate?.toIso8601String();
data['workingHours'] = workingHours;
data['techComment'] = techComment;
data['employeeId'] = employeeId;
return data;
}
}

@ -12,37 +12,77 @@ import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
class GasRefillModel { class GasRefillModel {
GasRefillModel( GasRefillModel({
{this.id, this.id,
this.gazRefillNo, this.gasRefillNo,
this.expectedDate, this.expectedDate,
this.expectedTime, this.expectedTime,
this.startDate, this.startDate,
this.startTime, this.startTime,
this.endDate, this.endDate,
this.endTime, this.endTime,
this.engSignature, this.engSignature,
this.nurseSignature, this.nurseSignature,
this.workingHours, this.workingHours,
this.extensionNo, this.extensionNo,
this.employeeId, this.employeeId,
this.name, this.name,
this.createdDate, this.createdDate,
this.site, this.site,
this.building, this.building,
this.floor, this.floor,
this.department, this.department,
this.assignedEmployee, this.assignedEmployee,
this.status, this.status,
this.comment, this.comment,
this.gazRefillDetails, this.techComment,
this.localEngineerSignature, this.gasRefillDetails,
this.localNurseSignature, this.localEngineerSignature,
this.timer}); this.localNurseSignature,
this.timer,
this.timerModelList,
this.gasRefillTimers,
this.gasRefillAttachments,
this.statusValue,
});
num? id; // Now nullable
String? gasRefillNo; // Now nullable
String? expectedDate; // Now nullable
String? expectedTime; // Now nullable
String? startDate; // Now nullable
String? startTime; // Now nullable
String? endDate; // Now nullable
String? endTime; // Now nullable
String? engSignature; // Now nullable
String? nurseSignature; // Now nullable
double? workingHours;
dynamic extensionNo;
String? employeeId;
String? name;
String? createdDate;
Site? site; // Now nullable
Building? building; // Now nullable
Floor? floor; // Now nullable
Department? department; // Now nullable
AssignedEmployee? assignedEmployee; // Now nullable
Lookup? status; // Now nullable
String? comment; // Now nullable
String? techComment; // Now nullable
List<GasRefillDetails>? gasRefillDetails; // Now nullable
Uint8List? localNurseSignature; // Now nullable
Uint8List? localEngineerSignature; // Now nullable
TimerModel? timer;
//TODO need to check when api provided..
List<TimerModel>? timerModelList = [];
List<GasRefillTimer>? gasRefillTimers = [];
List<GasRefillAttachments>? gasRefillAttachments;
int? statusValue;
GasRefillModel.fromJson(dynamic json) { GasRefillModel.fromJson(dynamic json) {
id = json['id']; id = json['id'];
gazRefillNo = json['gasRefillNo']; gasRefillNo = json['gasRefillNo'];
expectedDate = json['expectedDate']; expectedDate = json['expectedDate'];
expectedTime = json['expectedTime']; expectedTime = json['expectedTime'];
startDate = json['startDate']; startDate = json['startDate'];
@ -50,28 +90,44 @@ class GasRefillModel {
endDate = json['endDate']; endDate = json['endDate'];
endTime = json['endTime']; endTime = json['endTime'];
comment = json['comment']; comment = json['comment'];
techComment = json['techComment'];
workingHours = json['workingHours']; workingHours = json['workingHours'];
extensionNo = json['extensionNo']; extensionNo = json['extensionNo'];
employeeId = json['employeeId']; employeeId = json['employeeId'];
name = json['name']; name = json['name'];
createdDate = json['createdDate']; createdDate = json['createdDate'];
try { if (json['gasRefillTimers'] != null) {
final DateTime? sd = DateTime.tryParse(startDate ?? ""); gasRefillTimers = <GasRefillTimer>[];
final DateTime? st = DateTime.tryParse(startTime ?? ""); json['gasRefillTimers'].forEach((v) {
final DateTime? ed = DateTime.tryParse(endDate ?? ""); gasRefillTimers?.add(GasRefillTimer.fromJson(v));
final DateTime? et = DateTime.tryParse(endTime ?? ""); });
timer = TimerModel( workingHours = json['gasRefillTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDate']).difference(DateTime.parse(item['startDate'])).inSeconds) ?? 0;
startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd'
endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed' }
); if (json['gasRefillAttachments'] != null) {
if (timer!.endAt != null && timer!.startAt != null) { gasRefillAttachments = <GasRefillAttachments>[];
// Use '!' since timer could be null after initialization json['gasRefillAttachments'].forEach((v) {
timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; gasRefillAttachments!.add(GasRefillAttachments.fromJson(v));
workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); });
}
} catch (e) {
print(e);
} }
// try {
// final DateTime? sd = DateTime.tryParse(startDate ?? "");
// final DateTime? st = DateTime.tryParse(startTime ?? "");
// final DateTime? ed = DateTime.tryParse(endDate ?? "");
// final DateTime? et = DateTime.tryParse(endTime ?? "");
// timer = TimerModel(
// startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd'
// endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed'
// );
// if (timer!.endAt != null && timer!.startAt != null) {
// // Use '!' since timer could be null after initialization
// timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds;
// workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60);
// }
// } catch (e) {
// print(e);
// }
engSignature = json['engSignature']; engSignature = json['engSignature'];
nurseSignature = json['nurseSignature']; nurseSignature = json['nurseSignature'];
site = json['site'] != null ? Site.fromJson(json['site']) : null; site = json['site'] != null ? Site.fromJson(json['site']) : null;
@ -81,128 +137,92 @@ class GasRefillModel {
assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
status = json['status'] != null ? Lookup.fromJson(json['status']) : null; status = json['status'] != null ? Lookup.fromJson(json['status']) : null;
if (json['gasRefillDetails'] != null) { if (json['gasRefillDetails'] != null) {
gazRefillDetails = []; gasRefillDetails = [];
json['gasRefillDetails'].forEach((v) { json['gasRefillDetails'].forEach((v) {
gazRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gazRefillDetails is initialized here gasRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gasRefillDetails is initialized here
}); });
} }
} }
num? id; // Now nullable
String? gazRefillNo; // Now nullable
String? expectedDate; // Now nullable
String? expectedTime; // Now nullable
String? startDate; // Now nullable
String? startTime; // Now nullable
String? endDate; // Now nullable
String? endTime; // Now nullable
String? engSignature; // Now nullable
String? nurseSignature; // Now nullable
num? workingHours;
dynamic extensionNo;
String? employeeId;
String? name;
String? createdDate;
Site? site; // Now nullable
Building? building; // Now nullable
Floor? floor; // Now nullable
Department? department; // Now nullable
AssignedEmployee? assignedEmployee; // Now nullable
Lookup? status; // Now nullable
String? comment; // Now nullable
List<GasRefillDetails>? gazRefillDetails; // Now nullable
Uint8List? localNurseSignature; // Now nullable
Uint8List? localEngineerSignature; // Now nullable
TimerModel? timer; // Now nullable
GasRefillModel copyWith({
num? id, // Parameters are now nullable
String? gazRefillNo,
String? expectedDate,
String? expectedTime,
String? startDate,
String? startTime,
String? endDate,
String? endTime,
String? engSignature,
String? nurseSignature,
num? workingHours,
num? extensionNo,
num? employeeId,
String? name,
String? createdDate,
Site? site,
Building? building,
Floor? floor,
Department? department,
AssignedEmployee? assignedEmployee,
Lookup? status,
String? comment,
List<GasRefillDetails>? gazRefillDetails,
TimerModel? timer,
}) =>
GasRefillModel(
id: id ?? this.id,
gazRefillNo: gazRefillNo ?? this.gazRefillNo,
expectedDate: expectedDate ?? this.expectedDate,
expectedTime: expectedTime ?? this.expectedTime,
startDate: startDate ?? this.startDate,
startTime: startTime ?? this.startTime,
endDate: endDate ?? this.endDate,
endTime: endTime ?? this.endTime,
engSignature: engSignature ?? this.engSignature,
nurseSignature: nurseSignature ?? this.nurseSignature,
workingHours: workingHours ?? this.workingHours,
site: site ?? this.site,
building: building ?? this.building,
floor: floor ?? this.floor,
department: department ?? this.department,
assignedEmployee: assignedEmployee ?? this.assignedEmployee,
status: status ?? this.status,
comment: comment ?? this.comment,
gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails,
timer: timer ?? this.timer,
);
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['id'] = id ?? 0; map['id'] = id ?? 0;
map['gasRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; map['gasTypeId'] = gasRefillDetails?[0].gasType?.id;
map['expectedDate'] = expectedDate; map['cylinderTypeId'] = gasRefillDetails?[0].cylinderType?.id;
map['expectedTime'] = expectedTime; map['cylinderSizeId'] = gasRefillDetails?[0].cylinderSize?.id;
map['startDate'] = startDate; map['requestedQty'] = gasRefillDetails?[0].requestedQty;
map['startTime'] = startTime;
map['endDate'] = endDate;
map['endTime'] = endTime;
map['engSignature'] = engSignature;
map['nurseSignature'] = nurseSignature;
map['workingHours'] = workingHours;
map['extensionNo'] = extensionNo;
map['employeeId'] = employeeId;
map['name'] = name;
map['createdDate'] = createdDate;
map['comment'] = comment;
if (site != null) { if (site != null) {
map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety map['siteId'] = site?.id; // Use '?.' for null safety
} }
if (building != null) { if (building != null) {
map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety map['buildingId'] = building?.id; // Use '?.' for null safety
} }
if (floor != null) { if (floor != null) {
map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety map['floorId'] = floor?.id; // Use '?.' for null safety
} }
if (department != null) { if (department != null) {
map['department'] = department?.toJson(); // Use '?.' for null safety map['departmentId'] = department?.id; // Use '?.' for null safety
} }
if (assignedEmployee != null) { map['comment'] = comment;
map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety
if (gasRefillAttachments != null) {
map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
} }
if (status != null) {
map['status'] = status?.toJson(); // Use '?.' for null safety //older code.....
// map['gasRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}";
// map['expectedTime'] = expectedTime;
//
// map['startDate'] = startDate;
// map['startTime'] = startTime;
// map['endDate'] = endDate;
// map['endTime'] = endTime;
// map['engSignature'] = engSignature;
// map['nurseSignature'] = nurseSignature;
// map['workingHours'] = workingHours;
// map['extensionNo'] = extensionNo;
// map['employeeId'] = employeeId;
// map['name'] = name;
// map['createdDate'] = createdDate;
// map['comment'] = comment;
// if (site != null) {
// map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety
// }
// if (building != null) {
// map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety
// }
// if (floor != null) {
// map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety
// }
// if (department != null) {
// map['department'] = department?.toJson(); // Use '?.' for null safety
// }
// if (assignedEmployee != null) {
// map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety
// }
// if (status != null) {
// map['status'] = status?.toJson(); // Use '?.' for null safety
// }
// if (gasRefillDetails != null) {
// map['gasRefillDetails'] = gasRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gasRefillDetails could be null
// }
return map;
}
Map<String, dynamic> toUpdateEngineerPayload({required int status}) {
final map = <String, dynamic>{};
map['id'] = id ?? 0;
map['deliveredQty'] = gasRefillDetails?[0].deliverdQty;
map['statusValue'] = status;
map['techComment'] = techComment;
if (gasRefillTimers != null) {
map['gasRefillTimers'] = gasRefillTimers?.map((v) => v.toJson()).toList();
} }
if (gazRefillDetails != null) { if (gasRefillAttachments != null) {
map['gasRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
} }
return map; return map;
} }
@ -227,9 +247,9 @@ class GasRefillModel {
id = model.id; id = model.id;
//userId = model.userId; //userId = model.userId;
site = model.site; site = model.site;
gazRefillNo = model.gazRefillNo; gasRefillNo = model.gasRefillNo;
status = Lookup.fromStatus(model.status); status = Lookup.fromStatus(model.status);
gazRefillDetails = model.gazRefillDetails; gasRefillDetails = model.gasRefillDetails;
building = model.building; building = model.building;
floor = model.floor; floor = model.floor;
department = model.department; department = model.department;
@ -246,8 +266,60 @@ class GasRefillModel {
extensionNo = model.extensionNo; extensionNo = model.extensionNo;
employeeId = model.employeeId; employeeId = model.employeeId;
name = model.name; name = model.name;
techComment = model.techComment;
createdDate = model.createdDate; createdDate = model.createdDate;
} }
GasRefillModel copyWith({
num? id, // Parameters are now nullable
String? gasRefillNo,
String? expectedDate,
String? expectedTime,
String? startDate,
String? startTime,
String? endDate,
String? endTime,
String? engSignature,
String? nurseSignature,
double? workingHours,
num? extensionNo,
num? employeeId,
String? name,
String? createdDate,
Site? site,
Building? building,
Floor? floor,
Department? department,
AssignedEmployee? assignedEmployee,
Lookup? status,
String? comment,
List<GasRefillDetails>? gasRefillDetails,
List<GasRefillTimer>? gasRefillTimer,
TimerModel? timer,
}) =>
GasRefillModel(
id: id ?? this.id,
gasRefillNo: gasRefillNo ?? this.gasRefillNo,
expectedDate: expectedDate ?? this.expectedDate,
expectedTime: expectedTime ?? this.expectedTime,
startDate: startDate ?? this.startDate,
startTime: startTime ?? this.startTime,
endDate: endDate ?? this.endDate,
endTime: endTime ?? this.endTime,
engSignature: engSignature ?? this.engSignature,
nurseSignature: nurseSignature ?? this.nurseSignature,
workingHours: workingHours ?? this.workingHours,
site: site ?? this.site,
building: building ?? this.building,
floor: floor ?? this.floor,
department: department ?? this.department,
assignedEmployee: assignedEmployee ?? this.assignedEmployee,
status: status ?? this.status,
comment: comment ?? this.comment,
gasRefillDetails: gasRefillDetails ?? this.gasRefillDetails,
timer: timer ?? this.timer,
gasRefillTimers: gasRefillTimer ?? this.gasRefillTimers,
);
} }
class GasRefillDetails { class GasRefillDetails {
@ -331,3 +403,50 @@ class GasRefillDetails {
return true; return true;
} }
} }
class GasRefillTimer {
int? id;
String? startDate;
String? endDate;
dynamic workingHours;
GasRefillTimer({this.id, this.startDate, this.endDate, this.workingHours});
GasRefillTimer.fromJson(Map<String, dynamic> json) {
id = json['id'];
startDate = json['startDate'];
endDate = json['endDate'];
workingHours = json['workingHours'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['startDate'] = startDate;
data['endDate'] = endDate;
data['workingHours'] = workingHours;
return data;
}
}
class GasRefillAttachments {
int? id;
num? gasRefillId;
String? attachmentName;
GasRefillAttachments({this.id, this.attachmentName, this.gasRefillId});
GasRefillAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
gasRefillId = json['gasRefillId'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['gasRefillId'] = gasRefillId;
data['attachmentName'] = attachmentName;
return data;
}
}

@ -956,14 +956,14 @@ class PreventiveVisitKits {
PreventiveVisitKits.fromJson(Map<String, dynamic> json) { PreventiveVisitKits.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null; partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null;
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>(); final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id; data['id'] = id;
if (partCatalogItem != null) { if (partCatalogItem != null) {
// data['partCatalogItem'] = partCatalogItem!.toJson();
data['partCatalogItemId'] = partCatalogItem?.id; data['partCatalogItemId'] = partCatalogItem?.id;
} }
return data; return data;

@ -9,7 +9,7 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart';
import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart';
import '../app_style/app_color.dart'; import '../app_style/app_color.dart';
@ -40,7 +40,7 @@ class _AppFloatingActionButtonState extends State<AppFloatingActionButton> {
final elements = [ final elements = [
if (user.type == UsersTypes.normal_user) fabItem(context.translation.gasRefillRequest, "gas_refill_request", NewGasRefillRequestPage.routeName), if (user.type == UsersTypes.normal_user) fabItem(context.translation.gasRefillRequest, "gas_refill_request", NewGasRefillRequestPage.routeName),
if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16),
if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", RequestDeviceTransfer.id), if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", CreateAssetTransferRequest.id),
if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16),
if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id), if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id),
]; ];

@ -5,7 +5,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart';
import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart';
class CreateRequestTypeBottomSheet extends StatelessWidget { class CreateRequestTypeBottomSheet extends StatelessWidget {
const CreateRequestTypeBottomSheet({super.key}); const CreateRequestTypeBottomSheet({super.key});
@ -49,7 +49,7 @@ class CreateRequestTypeBottomSheet extends StatelessWidget {
icon: 'add_icon', icon: 'add_icon',
label: context.translation.deviceTransfer, label: context.translation.deviceTransfer,
onTap: () async { onTap: () async {
Navigator.pushReplacementNamed(context, RequestDeviceTransfer.id); Navigator.pushReplacementNamed(context, CreateAssetTransferRequest.id);
}, },
), ),
], ],

@ -1,7 +1,9 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
@ -21,9 +23,11 @@ import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.d
import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart';
import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart';
import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import '../../controllers/providers/api/gas_refill_provider.dart'; import '../../controllers/providers/api/gas_refill_provider.dart';
import '../../controllers/validator/validator.dart';
import '../common_widgets/default_app_bar.dart'; import '../common_widgets/default_app_bar.dart';
class NewGasRefillRequestPage extends StatefulWidget { class NewGasRefillRequestPage extends StatefulWidget {
@ -39,6 +43,8 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
late GasRefillDetails _currentDetails; late GasRefillDetails _currentDetails;
late GasRefillModel _gasModel; late GasRefillModel _gasModel;
Lookup? _requestedQuantity; Lookup? _requestedQuantity;
final TextEditingController _commentController = TextEditingController();
GasRefillProvider? _gasRefillProvider;
static List<Lookup> gasQuantity = [ static List<Lookup> gasQuantity = [
Lookup(name: "1", id: 1, value: 1), Lookup(name: "1", id: 1, value: 1),
@ -51,8 +57,11 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false);
_gasModel =GasRefillModel();
_currentDetails = GasRefillDetails(); _currentDetails = GasRefillDetails();
_gasModel = GasRefillModel(gazRefillDetails: []); _gasModel = GasRefillModel(gasRefillDetails: []);
_gasRefillProvider!.gasRefillAttachments.clear();
} }
@override @override
@ -66,35 +75,28 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
appBar: DefaultAppBar(title: context.translation.newGasRefillRequest), appBar: DefaultAppBar(title: context.translation.newGasRefillRequest),
body: Column( body: Column(
children: [ children: [
12.height,
SingleChildScrollView( SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
16.height,
SingleItemDropDownMenu<Lookup, GasTypesProvider>( SingleItemDropDownMenu<Lookup, GasTypesProvider>(
context: context, context: context,
title: context.translation.gasType, title: context.translation.gasType,
initialValue: _currentDetails.gasType, initialValue: _currentDetails.gasType,
backgroundColor: AppColor.neutral100,
showShadow: false,
showAsBottomSheet: true, showAsBottomSheet: true,
onSelect: (value) { onSelect: (value) {
_currentDetails.gasType = value; _currentDetails.gasType = value;
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
title: context.translation.quantity,
initialValue: _requestedQuantity,
staticData: gasQuantity,
onSelect: (value) {
_requestedQuantity = value;
_currentDetails.requestedQty = value?.value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, CylinderTypesProvider>( SingleItemDropDownMenu<Lookup, CylinderTypesProvider>(
context: context, context: context,
title: context.translation.cylinderType, title: context.translation.cylinderType,
initialValue: _currentDetails.cylinderType, initialValue: _currentDetails.cylinderType,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
_currentDetails.cylinderType = value; _currentDetails.cylinderType = value;
}, },
@ -105,136 +107,153 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
title: context.translation.cylinderSize, title: context.translation.cylinderSize,
initialValue: _currentDetails.cylinderSize, initialValue: _currentDetails.cylinderSize,
showAsBottomSheet: true, showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
_currentDetails.cylinderSize = value; _currentDetails.cylinderSize = value;
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Site, SiteProvider>( SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context, context: context,
title: context.translation.site, title: context.translation.quantity,
initialValue: _gasModel.site,
showAsBottomSheet: true, showAsBottomSheet: true,
initialValue: _requestedQuantity,
staticData: gasQuantity,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
setState(() { _requestedQuantity = value;
_gasModel.site = value; _currentDetails.requestedQty = value?.value;
_gasModel.building = null;
_gasModel.floor = null;
_gasModel.department = null;
});
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>( Row(
context: context, children: [
title: context.translation.building, SingleItemDropDownMenu<Site, SiteProvider>(
initialValue: _gasModel.building, context: context,
enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, title: context.translation.site,
staticData: _gasModel.site?.buildings ?? [], initialValue: _gasModel.site,
showAsBottomSheet: true, showAsBottomSheet: true,
onSelect: (value) { backgroundColor: AppColor.neutral100,
setState(() { showShadow: false,
_gasModel.building = value; onSelect: (value) {
_gasModel.floor = null; setState(() {
_gasModel.department = null; _gasModel.site = value;
}); _gasModel.building = null;
}, _gasModel.floor = null;
_gasModel.department = null;
});
},
).expanded,
8.width,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
context: context,
title: context.translation.building,
initialValue: _gasModel.building,
enabled: _gasModel.site?.buildings?.isNotEmpty ?? false,
staticData: _gasModel.site?.buildings ?? [],
showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) {
setState(() {
_gasModel.building = value;
_gasModel.floor = null;
_gasModel.department = null;
});
},
).expanded,
],
), ),
8.height, 8.height,
SingleItemDropDownMenu<Floor, NullableLoadingProvider>( Row(
context: context, children: [
title: context.translation.floor, SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
initialValue: _gasModel.floor, context: context,
enabled: _gasModel.building?.floors?.isNotEmpty ?? false, title: context.translation.floor,
staticData: _gasModel.building?.floors ?? [], initialValue: _gasModel.floor,
showAsBottomSheet: true, enabled: _gasModel.building?.floors?.isNotEmpty ?? false,
onSelect: (value) { staticData: _gasModel.building?.floors ?? [],
setState(() { showAsBottomSheet: true,
_gasModel.floor = value; backgroundColor: AppColor.neutral100,
_gasModel.department = null; showShadow: false,
}); onSelect: (value) {
}, setState(() {
_gasModel.floor = value;
_gasModel.department = null;
});
},
).expanded,
8.width,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
context: context,
title: context.translation.department,
initialValue: _gasModel.department,
enabled: _gasModel.floor?.departments?.isNotEmpty ?? false,
staticData: _gasModel.floor?.departments ?? [],
showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) {
_gasModel.department = value;
},
).expanded,
],
), ),
8.height, 8.height,
SingleItemDropDownMenu<Department, NullableLoadingProvider>( AppTextFormField(
context: context, labelText: context.translation.callComments,
title: context.translation.department, labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120),
initialValue: _gasModel.department, textInputType: TextInputType.multiline,
enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, alignLabelWithHint: true,
staticData: _gasModel.floor?.departments ?? [], backgroundColor: AppColor.neutral100,
showAsBottomSheet: true, showShadow: false,
onSelect: (value) { controller: _commentController,
_gasModel.department = value; onChange: (value){
_gasModel.comment = value;
}, },
onSaved: (value) {},
), ),
8.height, 8.height,
if (_gasModel.gazRefillDetails?.isEmpty ?? true) MultiFilesPicker(
AppFilledButton( label: context.translation.attachFiles,
label: context.translation.add, files: _gasRefillProvider!.gasRefillAttachments,
maxWidth: true, buttonColor: AppColor.black10,
textColor: Colors.white, onlyImages: false,
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
onPressed: _add,
),
ListView.builder(
shrinkWrap: true,
itemCount: _gasModel.gazRefillDetails?.length,
padding: const EdgeInsets.only(top: 12, bottom: 24),
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(_gasModel.gazRefillDetails![index].gasType?.name ?? "").heading5(context),
8.height,
("${context.translation.quantity}: ${_gasModel.gazRefillDetails![index].requestedQty}").bodyText(context),
("${context.translation.cylinderSize}: ${_gasModel.gazRefillDetails![index].cylinderSize?.name}").bodyText(context),
("${context.translation.cylinderType}: ${_gasModel.gazRefillDetails![index].cylinderType?.name}").bodyText(context),
],
),
Container(
height: 48.toScreenWidth,
width: 48.toScreenWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30),
),
padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight),
child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50),
).onPress(() {
_delete(index);
}),
],
),
const Divider().defaultStyle(context),
("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context),
("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context),
("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context),
("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context),
],
).toShadowContainer(context);
},
), ),
], ],
), ).toShadowContainer(context, padding: 10).paddingOnly(start: 16, end: 16, top: 16),
).expanded, ).expanded,
16.height, 16.height,
AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit), FooterActionButton.footerContainer(child: AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit)),
], ],
).paddingOnly(start: 16, end: 16, bottom: 24), ),
);
}
Future<void> _submit() async {
if (_currentDetails.gasType==null) {
Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests);
return;
}
_gasModel.gasRefillDetails=[];
_gasModel.gasRefillDetails?.add(_currentDetails);
_gasModel.gasRefillAttachments = [];
for (var item in _gasRefillProvider!.gasRefillAttachments) {
_gasModel.gasRefillAttachments?.add(GasRefillAttachments(
id: 0, gasRefillId: _gasModel.id ?? 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path));
}
await _gasRefillProvider?.addGasRefillRequest(
context: context,
model: _gasModel,
); );
} }
void _add() async { void _add() async {
if (_currentDetails.validate(context) && _gasModel.validate(context)) { if (_currentDetails.validate(context) && _gasModel.validate(context)) {
_gasModel.gazRefillDetails!.add(_currentDetails); _gasModel.gasRefillDetails!.add(_currentDetails);
_currentDetails = GasRefillDetails(); _currentDetails = GasRefillDetails();
_requestedQuantity = null; _requestedQuantity = null;
setState(() {}); setState(() {});
@ -242,19 +261,62 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
} }
void _delete(index) { void _delete(index) {
_gasModel.gazRefillDetails!.remove(_gasModel.gazRefillDetails![index]); _gasModel.gasRefillDetails!.remove(_gasModel.gasRefillDetails![index]);
setState(() {}); setState(() {});
} }
//older code....
Future<void> _submit() async { // if (_gasModel.gasRefillDetails?.isEmpty ?? true)
if (_gasModel.gazRefillDetails?.isEmpty ?? true) { // AppFilledButton(
Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); // label: context.translation.add,
return; // maxWidth: true,
} // textColor: Colors.white,
await Provider.of<GasRefillProvider>(context, listen: false).createModel( // buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50,
context: context, // onPressed: _add,
user: Provider.of<UserProvider>(context, listen: false).user!, // ),
model: _gasModel, // ListView.builder(
); // shrinkWrap: true,
} // itemCount: _gasModel.gasRefillDetails?.length,
// padding: const EdgeInsets.only(top: 12, bottom: 24),
// physics: const NeverScrollableScrollPhysics(),
// itemBuilder: (context, index) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// (_gasModel.gasRefillDetails![index].gasType?.name ?? "").heading5(context),
// 8.height,
// ("${context.translation.quantity}: ${_gasModel.gasRefillDetails![index].requestedQty}").bodyText(context),
// ("${context.translation.cylinderSize}: ${_gasModel.gasRefillDetails![index].cylinderSize?.name}").bodyText(context),
// ("${context.translation.cylinderType}: ${_gasModel.gasRefillDetails![index].cylinderType?.name}").bodyText(context),
// ],
// ),
// Container(
// height: 48.toScreenWidth,
// width: 48.toScreenWidth,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(100),
// border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30),
// ),
// padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight),
// child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50),
// ).onPress(() {
// _delete(index);
// }),
// ],
// ),
// const Divider().defaultStyle(context),
// ("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context),
// ("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context),
// ("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context),
// ("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context),
// ],
// ).toShadowContainer(context);
// },
// ),
} }

@ -128,7 +128,7 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours( ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController, workingHoursController: _workingHoursController,
updateModel: (hours){ updateModel: (hours){
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours;

@ -0,0 +1,342 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/device/asset_transfer_attachment.dart';
import 'package:test_sa/models/new_models/department.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/providers/ppm_service_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart';
import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import '../../../models/new_models/building.dart';
import '../../../models/new_models/site.dart';
import '../../../new_views/common_widgets/app_filled_button.dart';
import '../../../new_views/common_widgets/default_app_bar.dart';
import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../providers/gas_request_providers/site_provider.dart';
import '../../../providers/loading_list_notifier.dart';
class CreateAssetTransferRequest extends StatefulWidget {
static const String id = "/request-device-transfer";
const CreateAssetTransferRequest({Key? key}) : super(key: key);
@override
State<CreateAssetTransferRequest> createState() => _CreateAssetTransferRequestState();
}
class _CreateAssetTransferRequestState extends State<CreateAssetTransferRequest> {
late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _transferModel = AssetTransfer(id: 0);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController();
final Asset _assetDestination = Asset();
Asset? _pickedAsset;
final List<File> _deviceImages = [];
PendingAssetServiceRequest? pendingAssetServiceRequest;
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
}
bool checkPendingRequest = false;
void showPendingRequests() {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!)));
}
void _onSubmit() async {
_transferModel.assetId = _pickedAsset?.id;
_transferModel.destSiteId = _assetDestination.site?.id;
_transferModel.destBuildingId = _assetDestination.building?.id;
_transferModel.destFloorId = _assetDestination.floor?.id;
_transferModel.destDepartmentId = _assetDestination.department?.id;
_transferModel.destRoomId = _assetDestination.room?.id;
if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) {
return;
}
_formKey.currentState!.save();
List<AssetTransferAttachment> attachement = [];
for (var item in _deviceImages) {
attachement.add(AssetTransferAttachment(id: 0, attachmentName: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}"));
}
_transferModel.attachments = attachement;
await _deviceTransferProvider.createRequest(
context: context,
model: _transferModel,
);
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
Provider.of<PpmServiceProvider>(context, listen: false).getDate();
});
super.initState();
}
@override
void dispose() {
_requestedQuantityController.dispose();
_deviceTransferProvider.reset();
_receiverNameController.dispose();
_commentsController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
_deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: context.translation.createAssetTransferRequest,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: SafeArea(
child: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AssetPicker(
device: _pickedAsset,
showLoading: false,
borderColor: AppColor.black20,
backgroundColor: AppColor.white936,
onPick: (asset) async {
_pickedAsset = asset;
await checkAssetForPendingServiceRequest(asset.id!.toInt());
if (_pickedAsset != null && pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) {
showPendingRequestBottomSheet();
}
setState(() {});
}),
if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[
8.height,
Row(
children: [
const Icon(Icons.warning, color: Color(0xffEE404C), size: 14),
8.width,
Text(
"This asset already have ${pendingAssetServiceRequest!.details!.length} request pending",
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline),
).expanded,
],
).onPress(() {
showPendingRequests();
}),
],
21.height,
requestTypeWidget(context),
12.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: context.translation.site,
initialValue: _assetDestination.site,
showShadow: false,
backgroundColor: AppColor.neutral100,
showAsBottomSheet: true,
onSelect: (value) {
_assetDestination.site = value;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
setState(() {});
},
).expanded,
8.width,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
context: context,
title: context.translation.building,
initialValue: _assetDestination.building,
showShadow: false,
backgroundColor: AppColor.neutral100,
enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false,
staticData: _assetDestination.site?.buildings ?? [],
onSelect: (value) {
_assetDestination.building = value;
_assetDestination.floor = null;
_assetDestination.department = null;
setState(() {});
},
).expanded,
],
),
8.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
context: context,
title: context.translation.floor,
showShadow: false,
initialValue: _assetDestination.floor,
backgroundColor: AppColor.neutral100,
enabled: _assetDestination.building?.floors?.isNotEmpty ?? false,
staticData: _assetDestination.building?.floors ?? [],
onSelect: (value) {
_assetDestination.floor = value;
_assetDestination.department = null;
setState(() {});
},
).expanded,
8.width,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
context: context,
title: context.translation.department,
showShadow: false,
initialValue: _assetDestination.department,
backgroundColor: AppColor.neutral100,
enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false,
staticData: _assetDestination.floor?.departments ?? [],
onSelect: (value) {
_assetDestination.department = value;
_assetDestination.room = null;
setState(() {});
},
).expanded,
],
),
8.height,
AppTextFormField(
controller: _commentsController,
backgroundColor: AppColor.neutral100,
labelText: context.translation.callComments,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
showShadow: false,
onSaved: (text) {
_transferModel.comment = text;
},
),
8.height,
23.height,
MultiFilesPicker(
label: context.translation.attachImage,
files: _deviceImages,
buttonColor: AppColor.black10,
onlyImages: true,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
// 100.height,
],
).toShadowContainer(context).paddingOnly(top: 20, start: 16, end: 16),
).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(buttonColor: AppColor.primary10, label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit),
),
],
),
),
),
);
}
Future<void> checkAssetForPendingServiceRequest(int assetId) async {
checkPendingRequest = true;
setState(() {});
pendingAssetServiceRequest = await _deviceTransferProvider.checkAssetPendingRequest(assetId);
await Future.delayed(const Duration(milliseconds: 250));
checkPendingRequest = false;
setState(() {});
}
void showPendingRequestBottomSheet() async {
bool view = (await showModalBottomSheet(
context: context,
isDismissible: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _pickedAsset!),
)) as bool;
if (view) {
showPendingRequests();
}
}
Widget requestTypeWidget(BuildContext context) {
return Consumer<PpmServiceProvider>(builder: (cxt, snapshot, _) {
try {
_transferModel.transferType ??= snapshot.items.first;
} catch (ex) {
print("snapshot.items:${snapshot.items.length}");
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
context.translation.requestType.bodyText(context).custom(color: AppColor.white936),
8.height,
Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (var element in snapshot.items)
Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 24,
height: 24,
child: Radio(
value: element,
activeColor: AppColor.primary10,
fillColor: WidgetStateColor.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return AppColor.primary10; // Thumb color when selected
}
return Colors.grey; // Thumb color when unselected (grey)
}),
groupValue: _transferModel.transferType,
onChanged: (state) {
_transferModel.transferType = element;
setState(() {});
// });
}),
),
8.width,
Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)),
],
)
],
).toShimmer(isShow: snapshot.loading),
],
);
});
}
}

@ -237,4 +237,6 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
} }
} }
} }

@ -1,211 +0,0 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/employee.dart';
import 'package:test_sa/models/new_models/department.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/room_model.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/views/widgets/status/employee/nurse_menu.dart';
import '../../../models/new_models/building.dart';
import '../../../models/new_models/site.dart';
import '../../../new_views/common_widgets/app_filled_button.dart';
import '../../../new_views/common_widgets/default_app_bar.dart';
import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../providers/gas_request_providers/site_provider.dart';
import '../../../providers/loading_list_notifier.dart';
import '../../widgets/equipment/pick_asset.dart';
class RequestDeviceTransfer extends StatefulWidget {
static const String id = "/request-device-transfer";
const RequestDeviceTransfer({Key? key}) : super(key: key);
@override
State<RequestDeviceTransfer> createState() => _RequestDeviceTransferState();
}
class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
UserProvider? _userProvider;
SettingProvider? _settingProvider;
late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _transferModel = AssetTransfer();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController();
final Asset _assetDestination = Asset();
Asset? _pickedAsset;
Employee? receiverEndUser;
Employee? _selectedNurse;
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
}
void _onSubmit() async {
_transferModel.assetId = _pickedAsset?.id;
_transferModel.destSiteId = _assetDestination.site?.id;
_transferModel.destBuildingId = _assetDestination.building?.id;
_transferModel.destFloorId = _assetDestination.floor?.id;
_transferModel.destDepartmentId = _assetDestination.department?.id;
_transferModel.destRoomId = _assetDestination.room?.id;
_transferModel.receiverEndUserId = _selectedNurse?.id;
if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) {
return;
}
_formKey.currentState!.save();
await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset!);
}
@override
void dispose() {
_requestedQuantityController.dispose();
_deviceTransferProvider.reset();
_receiverNameController.dispose();
_commentsController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context, listen: false);
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
_deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
// _selectedNurse ??= Employee(id: _userProvider.user.userID, name: _userProvider.user.username);
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.newTransferRequest),
body: Form(
key: _formKey,
child: SafeArea(
child: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
16.height,
PickAsset(
device: _pickedAsset,
onPickAsset: (asset) {
_pickedAsset = asset;
setState(() {});
},
),
16.height,
context.translation.receiverDetails.heading5(context),
8.height,
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: context.translation.destinationSite,
initialValue: _assetDestination.site,
onSelect: (value) {
_assetDestination.site = value;
_assetDestination.building = null;
_assetDestination.floor = null;
_assetDestination.department = null;
_selectedNurse = null;
Provider.of<NurseProvider>(context, listen: false).siteId = value!.id!.toInt();
Provider.of<NurseProvider>(context, listen: false).getData();
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
context: context,
title: context.translation.building,
initialValue: _assetDestination.building,
enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false,
staticData: _assetDestination.site?.buildings ?? [],
onSelect: (value) {
_assetDestination.building = value;
_assetDestination.floor = null;
_assetDestination.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
context: context,
title: context.translation.floor,
initialValue: _assetDestination.floor,
enabled: _assetDestination.building?.floors?.isNotEmpty ?? false,
staticData: _assetDestination.building?.floors ?? [],
onSelect: (value) {
_assetDestination.floor = value;
_assetDestination.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
context: context,
title: context.translation.department,
initialValue: _assetDestination.department,
enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false,
staticData: _assetDestination.floor?.departments ?? [],
onSelect: (value) {
_assetDestination.department = value;
_assetDestination.room = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Rooms, NullableLoadingProvider>(
context: context,
title: context.translation.room,
initialValue: _assetDestination.room,
enabled: _assetDestination.department?.rooms?.isNotEmpty ?? false,
staticData: _assetDestination.department?.rooms ?? [],
onSelect: (value) {
_assetDestination.room = value;
setState(() {});
},
),
8.height,
NurseMenu(
title: context.translation.receiverName,
initialValue: _selectedNurse,
enable: _assetDestination.site != null,
onSelect: (employee) {
if (employee != null) {
_selectedNurse = employee;
setState(() {});
}
},
),
16.height,
context.translation.comments.heading5(context),
8.height,
AppTextFormField(
controller: _commentsController,
labelText: context.translation.comments,
onSaved: (text) {
_transferModel.comment = text;
},
),
100.height,
],
),
).expanded,
AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit)
],
).paddingOnly(start: 16, end: 16, bottom: 24),
),
),
);
}
}

@ -1,33 +1,365 @@
//older code.
// import 'dart:convert';
// import 'dart:io';
//
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:fluttertoast/fluttertoast.dart';
// import 'package:provider/provider.dart';
// import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
// import 'package:test_sa/controllers/providers/api/user_provider.dart';
// import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
// import 'package:test_sa/extensions/context_extension.dart';
// import 'package:test_sa/extensions/int_extensions.dart';
// import 'package:test_sa/extensions/string_extensions.dart';
// import 'package:test_sa/extensions/widget_extensions.dart';
// import 'package:test_sa/models/device/asset_transfer.dart';
// import 'package:test_sa/models/device/asset_transfer_attachment.dart';
// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
// import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart';
// import 'package:test_sa/views/app_style/sizing.dart';
// import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
// import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
//
// import '../../../extensions/text_extensions.dart';
// import '../../../models/lookup.dart';
// import '../../../models/ppm/ppm.dart';
// import '../../../new_views/app_style/app_color.dart';
// import '../../../new_views/common_widgets/app_text_form_field.dart';
// import '../../../new_views/common_widgets/default_app_bar.dart';
// import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
// import '../../widgets/e_signature/e_signature.dart';
// import '../../widgets/timer/app_timer.dart';
//
// class UpdateDeviceTransfer extends StatefulWidget {
// final AssetTransfer model;
// final bool isSender;
//
// const UpdateDeviceTransfer({Key? key, required this.model, required this.isSender}) : super(key: key);
//
// @override
// State<UpdateDeviceTransfer> createState() => _UpdateDeviceTransferState();
// }
//
// class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
// final bool _isLoading = false;
// bool _validate = false;
// late UserProvider _userProvider;
// late SettingProvider _settingProvider;
// Uint8List? _signature;
// late AssetTransferProvider _deviceTransferProvider;
// final TextEditingController _requestedQuantityController = TextEditingController();
// final AssetTransfer _formModel = AssetTransfer();
// final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
//
// List<File> _files = [];
//
// _update() async {
// if (widget.isSender) {
// _formModel.senderVisitTimers?.add(
// VisitTimers(
// id: 0,
// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
// ),
// );
// } else {
// _formModel.receiverVisitTimers?.add(
// VisitTimers(
// id: 0,
// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
// ),
// );
// }
//
// if (_formModel.tbsTimer?.startAt == null) {
// await Fluttertoast.showToast(msg: "Working Hours Required");
// return false;
// }
// if (_formModel.tbsTimer?.endAt == null || isTimerRunning) {
// await Fluttertoast.showToast(msg: "Please Stop The Timer");
// return false;
// }
// _validate = true;
// if (!(_formKey.currentState!.validate())) {
// setState(() {});
// return false;
// }
// _formKey.currentState!.save();
//
// if (widget.isSender) {
// _formModel.senderAttachments = [];
// } else {
// _formModel.receiverAttachments = [];
// }
//
// try {
// for (var file in _files) {
// String attachmentName = file.path;
// if (attachmentName.contains("/")) {
// attachmentName = file.path.split("/").last;
// attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}";
// }
//
// if (widget.isSender) {
// _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
// } else {
// _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
// }
// }
// } catch (error) {
// print(error);
// }
// await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender);
// }
//
// @override
// void initState() {
// _formModel.fromDetails(widget.model);
//
// if (widget.isSender) {
// _files = widget.model.senderAttachments?.map((e) => File(e.attachmentName!)).toList() ?? [];
// } else {
// _files = widget.model.receiverAttachments?.map((e) => File(e.attachmentName!)).toList() ?? [];
// }
//
// super.initState();
// }
//
// @override
// void dispose() {
// _requestedQuantityController.dispose();
// super.dispose();
// }
//
// bool isTimerRunning = false;
//
// @override
// Widget build(BuildContext context) {
// _userProvider = Provider.of<UserProvider>(context);
// _settingProvider = Provider.of<SettingProvider>(context);
// _deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
//
// double totalWorkingHours = widget.isSender
// ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0)
// : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0);
//
// bool isTimerEnable = widget.isSender
// ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false))
// : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false));
//
// return Scaffold(
// appBar: DefaultAppBar(title: context.translation.updateRequest),
// key: _scaffoldKey,
// body: SafeArea(
// child: LoadingManager(
// isLoading: _isLoading,
// isFailedLoading: false,
// stateCode: 200,
// onRefresh: () async {},
// child: Form(
// key: _formKey,
// child: Column(
// children: [
// SingleChildScrollView(
// padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: [
// _buildCard(),
// 8.height,
// AppTextFormField(
// initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "",
// labelText: context.translation.travelingHours,
// onChange: (text) {
// widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text;
// },
// onSaved: (value) {
// widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value;
// //_formModel?.workingHours = double.tryParse(value);
// // _formModel.travelingHours = value;
// },
// textInputType: TextInputType.number,
// //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only",
// ),
// 8.height,
// if (totalWorkingHours > 0.0) ...[
// Container(
// height: 50.toScreenHeight,
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
// alignment: Alignment.centerLeft,
// decoration: BoxDecoration(
// color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
// borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// "Total Working Time",
// style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
// ),
// Text(
// " ${formatDuration(totalWorkingHours.round())}",
// style: Theme.of(context).textTheme.bodyLarge,
// ),
// ],
// ),
// ),
// 8.height,
// ],
// AppTimer(
// label: context.translation.workingHours,
// timer: _formModel.tbsTimer,
// enabled: isTimerEnable,
// // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false),
// timerProgress: (isRunning) {
// isTimerRunning = isRunning;
// },
// onChange: (timer) async {
// _formModel.tbsTimer = timer;
// return true;
// },
// ),
// 8.height,
// Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
// return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
// context: context,
// title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus,
// initialValue:
// snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null),
// onSelect: (value) {
// if (value?.value == 4) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {});
// return;
// }
// if (widget.isSender) {
// _formModel.senderMachineStatusName = value?.name;
// _formModel.senderMachineStatusId = value?.id;
// } else {
// _formModel.receiverMachineStatusName = value?.name;
// _formModel.receiverMachineStatusId = value?.id;
// }
// setState(() {});
// },
// );
// }),
// 8.height,
// MultiFilesPicker(label: context.translation.attachImage, files: _files),
// 8.height,
// AppTextFormField(
// initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
// labelText: context.translation.comments,
// textInputType: TextInputType.multiline,
// alignLabelWithHint: true,
// onSaved: (value) {
// widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
// },
// ),
// 8.height,
// ESignature(
// title: "Signature",
// oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature,
// newSignature: _signature,
// onSaved: (signature) {
// _signature = signature;
// if (signature == null || signature.isEmpty) return;
// widget.isSender
// ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"
// : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// },
// ),
// ],
// ),
// ).expanded,
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: AppFilledButton(
// label: context.translation.update,
// onPressed: _update,
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
//
// _buildCard() {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// context.translation.transferDetails.heading5(context),
// 8.height,
// '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
// '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context),
// ],
// ).toShadowContainer(context);
// }
//
// String formatDuration(int seconds) {
// int hours = seconds ~/ 3600;
// int minutes = (seconds % 3600) ~/ 60;
// int remainingSeconds = seconds % 60;
//
// String formattedDuration = '';
// if (hours > 0) {
// formattedDuration += '$hours hour${hours > 1 ? 's' : ''} ';
// }
// if (minutes > 0) {
// formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} ';
// }
// if (remainingSeconds > 0) {
// formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} ';
// }
// if (formattedDuration.isEmpty) {
// formattedDuration = 'Less than a second';
// }
//
// return formattedDuration.trim();
// }
// }
//.....new design..
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/device/asset_transfer_attachment.dart'; import 'package:test_sa/models/device/asset_transfer_attachment.dart';
import 'package:test_sa/models/new_models/assigned_employee.dart';
import 'package:test_sa/models/new_models/assistant_employee.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart';
import '../../../extensions/text_extensions.dart'; import '../../../extensions/text_extensions.dart';
import '../../../models/lookup.dart';
import '../../../models/ppm/ppm.dart'; import '../../../models/ppm/ppm.dart';
import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/app_style/app_color.dart';
import '../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../new_views/common_widgets/default_app_bar.dart'; import '../../../new_views/common_widgets/default_app_bar.dart';
import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../widgets/e_signature/e_signature.dart';
import '../../widgets/timer/app_timer.dart'; import '../../widgets/timer/app_timer.dart';
class UpdateDeviceTransfer extends StatefulWidget { class UpdateDeviceTransfer extends StatefulWidget {
@ -42,10 +374,7 @@ class UpdateDeviceTransfer extends StatefulWidget {
class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> { class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
final bool _isLoading = false; final bool _isLoading = false;
bool _validate = false;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
Uint8List? _signature;
late AssetTransferProvider _deviceTransferProvider; late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController(); final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _formModel = AssetTransfer(); final AssetTransfer _formModel = AssetTransfer();
@ -54,27 +383,7 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
List<File> _files = []; List<File> _files = [];
_update() async { _update({required int status}) async {
if (widget.isSender) {
_formModel.senderVisitTimers?.add(
VisitTimers(
id: 0,
startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
),
);
} else {
_formModel.receiverVisitTimers?.add(
VisitTimers(
id: 0,
startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
),
);
}
if (_formModel.tbsTimer?.startAt == null) { if (_formModel.tbsTimer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required"); await Fluttertoast.showToast(msg: "Working Hours Required");
return false; return false;
@ -83,19 +392,38 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
await Fluttertoast.showToast(msg: "Please Stop The Timer"); await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false; return false;
} }
_validate = true;
if (!(_formKey.currentState!.validate())) { if (!(_formKey.currentState!.validate())) {
setState(() {}); setState(() {});
return false; return false;
} }
_formKey.currentState!.save(); _formKey.currentState!.save();
_formModel.statusValue = status;
_formModel.isSender = widget.isSender;
if (widget.isSender) { if (widget.isSender) {
_formModel.senderAttachments = []; _formModel.senderAttachments = [];
_formModel.senderVisitTimers?.add(
VisitTimers(
id: 0,
startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
),
);
_formModel.assetTransferEngineerTimers = _formModel.senderVisitTimers;
} else { } else {
_formModel.receiverAttachments = []; _formModel.receiverAttachments = [];
_formModel.receiverVisitTimers?.add(
VisitTimers(
id: 0,
startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
),
);
_formModel.assetTransferEngineerTimers = _formModel.receiverVisitTimers;
} }
try { try {
for (var file in _files) { for (var file in _files) {
String attachmentName = file.path; String attachmentName = file.path;
@ -103,17 +431,19 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
attachmentName = file.path.split("/").last; attachmentName = file.path.split("/").last;
attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}";
} }
if (widget.isSender) { if (widget.isSender) {
_formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
_formModel.attachments = _formModel.senderAttachments;
} else { } else {
_formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
_formModel.attachments = _formModel.receiverAttachments;
} }
} }
} catch (error) { } catch (error) {
print(error); print(error);
} }
await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender);
await _deviceTransferProvider.updateRequest(context, model: _formModel);
} }
@override @override
@ -139,20 +469,16 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false); _deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
double totalWorkingHours = widget.isSender double totalWorkingHours = widget.isSender
? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0) ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0)
: (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0); : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0);
bool isTimerEnable = widget.isSender bool isTimerEnable = widget.isSender
? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false))
: (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false));
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: context.translation.updateRequest), appBar: DefaultAppBar(title: context.translation.transferAsset),
key: _scaffoldKey, key: _scaffoldKey,
body: SafeArea( body: SafeArea(
child: LoadingManager( child: LoadingManager(
@ -167,122 +493,60 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
SingleChildScrollView( SingleChildScrollView(
padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
_buildCard(), Column(
8.height, crossAxisAlignment: CrossAxisAlignment.stretch,
AppTextFormField( children: [
initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", _timerWidget(context, totalWorkingHours, isTimerEnable),
labelText: context.translation.travelingHours, 8.height,
onChange: (text) { AppTextFormField(
widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
}, labelText: context.translation.technicalComment,
onSaved: (value) { labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral20),
widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; textInputType: TextInputType.multiline,
//_formModel?.workingHours = double.tryParse(value); backgroundColor: AppColor.neutral100,
// _formModel.travelingHours = value; showShadow: false,
}, alignLabelWithHint: true,
textInputType: TextInputType.number, onSaved: (value) {
//validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
), },
8.height,
if (totalWorkingHours > 0.0) ...[
Container(
height: 50.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
), ),
child: Column( 8.height,
crossAxisAlignment: CrossAxisAlignment.start, MultiFilesPicker(
mainAxisAlignment: MainAxisAlignment.center, label: context.translation.attachFiles,
children: [ files: _files,
Text( buttonColor: AppColor.black10,
"Total Working Time", onlyImages: false,
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
Text(
" ${formatDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyLarge,
),
],
), ),
), 8.height,
8.height, ],
], ).toShadowContainer(context),
AppTimer( 16.height,
label: context.translation.workingHours, AssistantEmployeeCard(
timer: _formModel.tbsTimer, isSender: widget.isSender,
enabled: isTimerEnable, formModel: _formModel,
// enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), ).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)),
timerProgress: (isRunning) {
isTimerRunning = isRunning;
},
onChange: (timer) async {
_formModel.tbsTimer = timer;
return true;
},
),
8.height,
Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
context: context,
title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus,
initialValue:
snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null),
onSelect: (value) {
if (value?.value == 4) {
"Status cannot be change to ${value?.name}.".addTranslation.showToast;
setState(() {});
return;
}
if (widget.isSender) {
_formModel.senderMachineStatusName = value?.name;
_formModel.senderMachineStatusId = value?.id;
} else {
_formModel.receiverMachineStatusName = value?.name;
_formModel.receiverMachineStatusId = value?.id;
}
setState(() {});
},
);
}),
8.height,
MultiFilesPicker(label: context.translation.attachImage, files: _files),
8.height,
AppTextFormField(
initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
onSaved: (value) {
widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
},
),
8.height,
ESignature(
title: "Signature",
oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature,
newSignature: _signature,
onSaved: (signature) {
_signature = signature;
if (signature == null || signature.isEmpty) return;
widget.isSender
? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"
: _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
},
),
], ],
), ),
).expanded, ).expanded,
Padding( FooterActionButton.footerContainer(
padding: const EdgeInsets.all(16.0), child: Row(
child: AppFilledButton( mainAxisAlignment: MainAxisAlignment.spaceAround,
label: context.translation.update, children: [
onPressed: _update, AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () => _update(status: 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () => _update(status: 1),
).expanded,
],
), ),
), ),
], ],
@ -293,37 +557,245 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
); );
} }
_buildCard() { void updateTimer({TimerModel? timer}) {
_formModel.tbsTimer = timer;
if (timer?.startAt != null && timer?.endAt != null) {
_formModel.timerModelList = _formModel.timerModelList ?? [];
_formModel.timerModelList!.add(timer!);
}
// notifyListeners();
}
Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min,
children: [ children: [
context.translation.transferDetails.heading5(context), AppTimer(
8.height, label: context.translation.workingHours,
'${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), timer: _formModel.tbsTimer,
'${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), width: double.infinity,
enabled: isTimerEnable,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
updateTimer(timer: timer);
return true;
},
),
if (totalWorkingHours > 0.0) ...[
12.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120),
8.width,
Text(
ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()),
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
],
),
],
], ],
).toShadowContainer(context); );
} }
}
String formatDuration(int seconds) { class AssistantEmployeeCard extends StatefulWidget {
int hours = seconds ~/ 3600; bool? isSender = false;
int minutes = (seconds % 3600) ~/ 60; AssetTransfer? formModel;
int remainingSeconds = seconds % 60;
String formattedDuration = ''; AssistantEmployeeCard({super.key, this.isSender, this.formModel});
if (hours > 0) {
formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; @override
} State<AssistantEmployeeCard> createState() => _AssistantEmployeeCardState();
if (minutes > 0) { }
formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} ';
} class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
if (remainingSeconds > 0) { final TextEditingController _workingHoursController = TextEditingController(text: '');
formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; bool isCurrentUserIsAssistantEmp = false;
} bool isExpanded = false;
if (formattedDuration.isEmpty) { List<AssetTransferAssistantEmployees> employeeList = [];
formattedDuration = 'Less than a second'; AssistantEmployees selectedEmployee = AssistantEmployees();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
Future<void> getInitialData() async {
if (widget.isSender!) {
employeeList = widget.formModel!.assetTransferAssistantEmployeesSender ?? [];
} else {
employeeList = widget.formModel!.assetTransferAssistantEmployeesReceiver ?? [];
} }
widget.formModel?.modelAssistantEmployees = employeeList.isNotEmpty ? employeeList[0] : AssetTransferAssistantEmployees();
AssignedEmployee? assignedUser = AssignedEmployee(
id: employeeList[0].employeeId,
name: employeeList[0].employeeName,
);
selectedEmployee = AssistantEmployees(userId: assignedUser.id, user: assignedUser);
}
@override
void dispose() {
_workingHoursController.dispose();
super.dispose();
}
return formattedDuration.trim(); @override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 56.toScreenHeight,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10),
Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded),
],
),
).onPress(() {
setState(() {
isExpanded = !isExpanded;
});
}),
isExpanded
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ServiceReportAssistantEmployeeMenu(
title: context.translation.select,
backgroundColor: AppColor.neutral100,
assetId: widget.formModel?.assetId ?? 0,
initialValue: selectedEmployee,
onSelect: (employee) {
if (employee == null) {
widget.formModel?.assistantEmployees = [];
} else {
widget.formModel?.assistantEmployees = [employee.copyWith(id: 0)];
widget.formModel?.modelAssistantEmployees?.employeeId = employee.user?.id;
}
},
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ADatePicker(
label: context.translation.startTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: widget.formModel?.modelAssistantEmployees?.startDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
widget.formModel?.modelAssistantEmployees?.startDate = selectedDateTime;
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: widget.formModel?.modelAssistantEmployees?.startDate,
endTime: widget.formModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController,
updateModel: (hours) {
widget.formModel?.modelAssistantEmployees?.workingHours = hours;
});
setState(() {});
}
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: widget.formModel?.modelAssistantEmployees?.endDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (widget.formModel?.modelAssistantEmployees?.startDate != null && selectedDateTime.isBefore(widget.formModel!.modelAssistantEmployees!.startDate!)) {
"End Date time must be greater then start date".showToast;
return;
}
widget.formModel?.modelAssistantEmployees?.endDate = selectedDateTime;
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: widget.formModel?.modelAssistantEmployees?.startDate,
endTime: widget.formModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController,
updateModel: (hours) {
widget.formModel?.modelAssistantEmployees?.workingHours = hours;
});
setState(() {});
}
});
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
controller: _workingHoursController,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: widget.formModel?.modelAssistantEmployees?.workingHours != null ? widget.formModel?.modelAssistantEmployees?.workingHours.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
enable: false,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: widget.formModel?.modelAssistantEmployees?.techComment,
labelText: context.translation.technicalComment,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
widget.formModel?.modelAssistantEmployees?.techComment = value;
},
onSaved: (value) {
widget.formModel?.modelAssistantEmployees?.techComment = value;
},
),
16.height,
],
)
: const SizedBox(),
],
);
} }
} }

@ -7,6 +7,8 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart';
import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@ -30,7 +32,7 @@ class GasRefillDetailsPage extends StatefulWidget {
} }
class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> { class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
GasRefillModel _model = GasRefillModel(gazRefillDetails: []); GasRefillModel _model = GasRefillModel(gasRefillDetails: []);
late UserProvider _userProvider; late UserProvider _userProvider;
late GasRefillProvider gasRefillProvider; late GasRefillProvider gasRefillProvider;
final bool _isLoading = false; final bool _isLoading = false;
@ -68,6 +70,14 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: informationCard(_model), child: informationCard(_model),
).expanded, ).expanded,
if (_userProvider.user!.type == UsersTypes.engineer && (_model.status!.id! != 5833))//TODO need to check this value for complete status.
AppFilledButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => GasRefillForm(gasRefillModel: _model)));
// getVisitData();
},
label: context.translation.updateRequest,
).paddingAll(16)
], ],
); );
} }
@ -109,21 +119,21 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
context.translation.gasRefillRequest.heading5(context), context.translation.gasRefillRequest.heading5(context),
8.height, 8.height,
'${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails?[0].gasType?.name}'.bodyText(context), '${context.translation.gasRequest}: ${gasRefillModel.gasRefillDetails![0].gasType?.name}'.bodyText(context),
'${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails?[0].cylinderType?.name}'.bodyText(context), '${context.translation.cylinderType}: ${gasRefillModel.gasRefillDetails![0].cylinderType?.name}'.bodyText(context),
'${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails?[0].cylinderSize?.name}'.bodyText(context), '${context.translation.cylinderSize}: ${gasRefillModel.gasRefillDetails![0].cylinderSize?.name}'.bodyText(context),
'${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
'${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
'${context.translation.requestNo}: ${gasRefillModel.gazRefillNo}'.bodyText(context), '${context.translation.requestNo}: ${gasRefillModel.gasRefillNo}'.bodyText(context),
//TODO need to confirm where to display this new data... //TODO need to confirm where to display this new data...
infoText(label:context.translation.gasRequest ,value:gasRefillModel.extensionNo ), infoText(label: context.translation.gasRequest, value: gasRefillModel.extensionNo),
infoText(label:context.translation.employeeId ,value:gasRefillModel.employeeId ), infoText(label: context.translation.employeeId, value: gasRefillModel.employeeId),
infoText(label:context.translation.name ,value:gasRefillModel.name ), infoText(label: context.translation.name, value: gasRefillModel.name),
infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), infoText(label: context.translation.createdDate, value: gasRefillModel.createdDate?.toInitialVisitCardFormat),
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
'${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails?[0].requestedQty ?? 0}'.bodyText(context), '${context.translation.requestedQuantity}: ${gasRefillModel.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
'${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails?[0].deliverdQty ?? 0}'.bodyText(context), '${context.translation.deliveredQuantity}: ${gasRefillModel.gasRefillDetails![0].deliverdQty ?? 0}'.bodyText(context),
8.height, 8.height,
if (gasRefillModel.comment?.isNotEmpty ?? false) ...[ if (gasRefillModel.comment?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
@ -132,34 +142,11 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
] ]
], ],
).expanded, ).expanded,
Column( if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height,
crossAxisAlignment: CrossAxisAlignment.end, Text(
children: [ (widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "",
if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) textAlign: TextAlign.end,
"edit".toSvgAsset(height: 48, width: 48).onPress( style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
() async {
_model.fromGasRefillModel(gasRefillModel);
// setState(() {});
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RequestGasRefill(gasRefillModel: gasRefillModel),
),
).then((value) {
if (value != null) {
_model = value;
setState(() {});
}
});
},
),
if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height,
Text(
(widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
],
), ),
], ],
).paddingOnly(top: 16, start: 16, end: 16), ).paddingOnly(top: 16, start: 16, end: 16),
@ -229,13 +216,14 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
).toShadowContainer(context, padding: 0); ).toShadowContainer(context, padding: 0);
} }
Widget infoText({String ?label,String ?value,}){ Widget infoText({
if(value==null||value.isEmpty){ String? label,
return const SizedBox(); String? value,
} }) {
else { if (value == null || value.isEmpty) {
return const SizedBox();
} else {
return '$label: $value'.bodyText(context); return '$label: $value'.bodyText(context);
} }
} }
} }

@ -0,0 +1,401 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/controllers/validator/validator.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../controllers/providers/api/hospitals_provider.dart';
import '../../../../extensions/text_extensions.dart';
import '../../../../models/new_models/gas_refill_model.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../providers/gas_request_providers/gas_status_provider.dart';
import '../../../widgets/e_signature/e_signature.dart';
import '../../../widgets/timer/app_timer.dart';
class GasRefillForm extends StatefulWidget {
static const String id = "/gas-refill-form";
final GasRefillModel? gasRefillModel;
const GasRefillForm({this.gasRefillModel, Key? key}) : super(key: key);
@override
State<GasRefillForm> createState() => _GasRefillFormState();
}
class _GasRefillFormState extends State<GasRefillForm> {
final bool _isLoading = false;
bool _validate = false;
Uint8List? _engineerSignature;
Uint8List? _nurseSignature;
double totalWorkingHours = 0.0;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
GasRefillProvider? _gasRefillProvider;
GasRefillDetails _currentDetails = GasRefillDetails();
final TextEditingController _deliveredQuantityController = TextEditingController();
final TextEditingController _commentController = TextEditingController();
final TextEditingController _workingHoursController = TextEditingController();
final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey _DetailsKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool _firstTime = true;
Lookup? _deliveredQuantity;
static List<Lookup> deliveredQuantity = [
Lookup(name: "1", id: 1, value: 1),
Lookup(name: "2", id: 2, value: 2),
Lookup(name: "3", id: 3, value: 3),
Lookup(name: "4", id: 4, value: 4),
Lookup(name: "5", id: 5, value: 5)
];
@override
void initState() {
super.initState();
_gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false);
if (widget.gasRefillModel != null) {
_formModel.fromGasRefillModel(widget.gasRefillModel!);
// totalWorkingHours =
// _formModel?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0;
_commentController.text = _formModel.techComment ?? "";
try {
_deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty);
_currentDetails.deliverdQty = _deliveredQuantity!.value;
} catch (ex) {}
}
if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) {
_gasRefillProvider?.gasRefillAttachments = [];
_gasRefillProvider?.gasRefillAttachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList());
}
}
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
}
_onSubmit(BuildContext context,int status) async {
if (_formModel.timer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required");
return false;
}
if (_formModel.timer?.endAt == null) {
await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false;
}
if(_currentDetails.deliverdQty==null){
await Fluttertoast.showToast(msg: "Delivered Quantity is Required");
return false;
}
_formModel.gasRefillDetails=[];
_formModel.gasRefillDetails?.add(_currentDetails);
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
_formModel.gasRefillTimers = _formModel.gasRefillTimers ?? [];
_formModel.timerModelList?.forEach((timer) {
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
_formModel.gasRefillTimers?.add(
GasRefillTimer(
id: 0,
startDate: timer.startAt!.toIso8601String(), // Handle potential null
endDate: timer.endAt?.toIso8601String(), // Handle potential null
workingHours: ((durationInSecond) / 60 / 60),
),
);
});
_formModel.gasRefillAttachments = [];
for (var item in _gasRefillProvider!.gasRefillAttachments) {
_formModel.gasRefillAttachments
?.add(GasRefillAttachments(id: 0,gasRefillId: _formModel.id??0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path));
}
await _gasRefillProvider
?.updateGasRefill(
status: status,
model: _formModel
)
.whenComplete(() {
if (status == 1) {
AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context,listen: false);
// when click complete then this request remove from the list and status changes to closed..
_gasRefillProvider?.reset();
allRequestsProvider.getAllRequests(context, typeTransaction: 2);
}
Navigator.pop(context);
Navigator.pop(context);
});
}
@override
void dispose() {
_deliveredQuantityController.dispose();
_commentController.dispose();
_workingHoursController.dispose();
super.dispose();
}
void updateTimer({TimerModel? timer}) {
_formModel.timer = timer;
if (timer?.startAt != null && timer?.endAt != null) {
_formModel.timerModelList = _formModel.timerModelList ?? [];
_formModel.timerModelList!.add(timer!);
}
// notifyListeners();
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
if (_firstTime) {
String? clientName;
if (widget.gasRefillModel != null) {
//_formModel.status = widget.gasRefillModel?.status ?? Lookup(value: 0);
_gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? "");
_formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? ""));
clientName = _formModel.site?.custName;
} else {
_formModel.timer = null;
clientName = _userProvider.user?.clientName;
}
// HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) {
// _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null);
// _gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null);
// _gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null);
// _gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null);
// _firstTime = false;
// setState(() {});
// });
}
return Scaffold(
appBar: DefaultAppBar(title: context.translation.gasRefill),
key: _scaffoldKey,
body: Form(
key: _formKey,
child: SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// context.translation.gasRefill.heading5(context),
// 8.height,
// '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context),
// '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context),
// '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context),
// '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
// '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context),
// ],
// ).toShadowContainer(context),
8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
title: context.translation.quantity,
backgroundColor: AppColor.neutral100,
showShadow: false,
initialValue: _deliveredQuantity,
staticData: deliveredQuantity,
onSelect: (value) {
_deliveredQuantity = value;
_currentDetails.deliverdQty = value!.value;
},
),
8.height,
// AppTextFormField(
// initialValue: _formModel.gasRefillDetails?[0].deliverdQty?.toString() ?? "",
// labelText: context.translation.deliveredQuantity,
// onSaved: (value) {
// _currentDetails.deliverdQty = double.tryParse(value);
// },
// textInputType: TextInputType.number,
// controller: _deliveredQuantityController,
// validator: (value) => value == null || value.isEmpty
// ? context.translation.requiredField
// : Validator.isNumeric(value)
// ? null
// : context.translation.onlyNumbers,
// ),
// 8.height,
_timerWidget(context, _formModel.workingHours ?? 0),
8.height,
// SingleItemDropDownMenu<Lookup, GasStatusProvider>(
// context: context,
// title: context.translation.requestStatus,
// initialValue: _formModel.status,
// onSelect: (value) {
// if (value?.value == 0) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {});
// return;
// }
// if (value != null) {
// _formModel.status = value;
// }
// },
// ),
// 8.height,
// 8.height,
/// TBD
AppTextFormField(
labelText: context.translation.technicalComment,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
controller: _commentController,
onChange: (value){
_formModel.techComment = value;
},
onSaved: (value) {},
),
16.height,
MultiFilesPicker(
label: context.translation.attachFiles,
files: _gasRefillProvider!.gasRefillAttachments,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
8.height,
// ESignature(
// title: "Engineer Signature",
// oldSignature: widget.gasRefillModel?.engSignature,
// newSignature: _engineerSignature,
// onSaved: (signature) {
// _engineerSignature = signature;
// if (signature == null || signature.isEmpty) return;
// _formModel.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// //base64Encode(signature);
// },
// ),
// 8.height,
// ESignature(
// title: "Nurse Signature",
// oldSignature: widget.gasRefillModel?.nurseSignature,
// newSignature: _nurseSignature,
// onSaved: (signature) {
// _nurseSignature = signature;
// if (signature == null || signature.isEmpty) return;
// _formModel.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// //base64Encode(signature);
// },
// ),
],
).toShadowContainer(context),
).expanded,
FooterActionButton.footerContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
AppFilledButton(
label: context.translation.save,
buttonColor: AppColor.white60,
textColor: AppColor.black10,
onPressed: () => _onSubmit(context, 0),
).expanded,
12.width,
AppFilledButton(
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () => _onSubmit(context, 1),
).expanded,
],
),
),
],
)),
),
),
);
}
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
AppTimer(
label: context.translation.workingHours,
timer: _formModel.timer,
//TODO need to fix this..
// enabled: _formModel.endDate == null,
width: double.infinity,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
updateTimer(timer: timer);
return true;
},
),
if (totalWorkingHours > 0.0) ...[
12.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120),
8.width,
Text(
ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()),
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
],
),
],
],
);
}
}

@ -53,7 +53,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
final TextEditingController _commentController = TextEditingController(); final TextEditingController _commentController = TextEditingController();
final TextEditingController _workingHoursController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController();
final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey _DetailsKey = GlobalKey<FormState>(); final GlobalKey _DetailsKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -77,7 +77,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
_formModel.fromGasRefillModel(widget.gasRefillModel!); _formModel.fromGasRefillModel(widget.gasRefillModel!);
_commentController.text = _formModel.comment ?? ""; _commentController.text = _formModel.comment ?? "";
try { try {
_deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty); _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty);
_currentDetails.deliverdQty = _deliveredQuantity!.value; _currentDetails.deliverdQty = _deliveredQuantity!.value;
} catch (ex) {} } catch (ex) {}
} }
@ -101,7 +101,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
await Fluttertoast.showToast(msg: "Please Stop The Timer"); await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false; return false;
} }
if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { if (_formModel.gasRefillDetails?.isNotEmpty ?? false) {
if (!(await _addNewModel(context))) return; if (!(await _addNewModel(context))) return;
} }
@ -147,15 +147,15 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
// return false; // return false;
// } // }
_formKey.currentState!.save(); _formKey.currentState!.save();
_currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; _currentDetails.gasType = _formModel.gasRefillDetails![0].gasType;
_currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; _currentDetails.cylinderSize = _formModel.gasRefillDetails![0].cylinderSize;
_currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; _currentDetails.cylinderType = _formModel.gasRefillDetails![0].cylinderType;
_currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; _currentDetails.requestedQty = _formModel.gasRefillDetails![0].requestedQty;
if (!( _currentDetails.validate(context))) { if (!( _currentDetails.validate(context))) {
setState(() {}); setState(() {});
return false; return false;
} }
_formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; _formModel.gasRefillDetails![0].deliverdQty = _currentDetails.deliverdQty;
_validate = false; _validate = false;
// Scrollable.ensureVisible(_DetailsKey.currentContext); // Scrollable.ensureVisible(_DetailsKey.currentContext);
_deliveredQuantityController.clear(); _deliveredQuantityController.clear();
@ -225,10 +225,10 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
children: [ children: [
context.translation.gasRefill.heading5(context), context.translation.gasRefill.heading5(context),
8.height, 8.height,
'${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context),
'${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context),
'${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context),
'${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
'${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context),
], ],
).toShadowContainer(context), ).toShadowContainer(context),

@ -19,7 +19,7 @@
// //
// import '../../../models/enums/user_types.dart'; // import '../../../models/enums/user_types.dart';
// import '../../widgets/land_page/land_page_item.dart'; // import '../../widgets/land_page/land_page_item.dart';
// import '../device_transfer/request_device_transfer.dart'; // import '../device_transfer/create__asset_transfer_request.dart';
// import 'requests/requests_page.dart'; // import 'requests/requests_page.dart';
// //
// @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder") // @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder")

@ -51,11 +51,11 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
buildingInfoWidget(label: context.translation.department, value: model?.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context),
8.height, 8.height,
buildingInfoWidget(label: context.translation.floor, value: model?.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context),
8.height, 8.height,
buildingInfoWidget(label: context.translation.room, value: model?.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context),
8.height, 8.height,
_timerWidget(context, model!.totalWorkingHours!), _timerWidget(context, model!.totalWorkingHours!),
8.height, 8.height,
@ -129,7 +129,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
} }
} }
Widget buildingInfoWidget({required String label, required String? value, required BuildContext context}) { Widget buildingInfoWidget({required String label, required String value, required BuildContext context}) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -112,11 +112,7 @@ void _updateTask({required BuildContext context, required int status}) async {
if (validate(model: allRequestsProvider.recurrentWoData!)) { if (validate(model: allRequestsProvider.recurrentWoData!)) {
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? [];
DateTime? startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt;
DateTime? endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt;
// final duration = (endTime?.difference(startTime!));
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) { allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) {
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add(

@ -63,7 +63,6 @@ class _WoInfoFormState extends State<WoInfoForm> {
double totalWorkingHours = double totalWorkingHours =
widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0;
totalWorkingHours = totalWorkingHours;
return Consumer<PpmProvider>(builder: (context, ppmProvider, child) { return Consumer<PpmProvider>(builder: (context, ppmProvider, child) {

@ -15,10 +15,12 @@ class AssetPicker extends StatelessWidget {
final bool editable; final bool editable;
final bool showAssetInfo; final bool showAssetInfo;
final Color? borderColor; final Color? borderColor;
Color? backgroundColor;
final bool forPPM; final bool forPPM;
final bool showLoading; final bool showLoading;
const AssetPicker({Key? key, this.editable = true, this.device, this.onPick,this.borderColor, this.showAssetInfo = true, this.forPPM = false, this.showLoading = false}) : super(key: key); AssetPicker({Key? key, this.editable = true, this.device, this.onPick, this.borderColor, this.showAssetInfo = true, this.forPPM = false, this.backgroundColor, this.showLoading = false})
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -29,7 +31,7 @@ class AssetPicker extends StatelessWidget {
height: 50, height: 50,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.blueStatus(context), color: backgroundColor ?? AppColor.blueStatus(context),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),
@ -43,7 +45,10 @@ class AssetPicker extends StatelessWidget {
], ],
), ),
).onPress(() async { ).onPress(() async {
Asset? device = await Navigator.of(context).push(MaterialPageRoute(builder: (context)=>AssetScanQr(title: context.translation.assetScan,))) as Asset?; Asset? device = await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AssetScanQr(
title: context.translation.assetScan,
))) as Asset?;
if (device != null) { if (device != null) {
onPick!(device); onPick!(device);
} }
@ -53,7 +58,7 @@ class AssetPicker extends StatelessWidget {
height: 50, height: 50,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color:borderColor?? AppColor.blueStatus(context), width: 2), color: Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color: borderColor ?? AppColor.blueStatus(context), width: 2),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
@ -66,7 +71,10 @@ class AssetPicker extends StatelessWidget {
], ],
), ),
).onPress(() async { ).onPress(() async {
Asset? device = await Navigator.of(context).push(MaterialPageRoute(builder: (context)=>AssetScanQr(title: context.translation.assetScan,))) as Asset?; Asset? device = await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AssetScanQr(
title: context.translation.assetScan,
))) as Asset?;
if (device != null) { if (device != null) {
onPick!(device); onPick!(device);
} }

@ -41,7 +41,7 @@ class GasRefillItem extends StatelessWidget {
), ),
8.height, 8.height,
context.translation.gasRefillRequest.heading5(context), context.translation.gasRefillRequest.heading5(context),
'${context.translation.gasType}: ${item.gazRefillDetails![0].gasType!.name}'.bodyText(context), '${context.translation.gasType}: ${item.gasRefillDetails![0].gasType!.name}'.bodyText(context),
'${context.translation.site}: ${item.site!.name}'.bodyText(context), '${context.translation.site}: ${item.site!.name}'.bodyText(context),
8.height, 8.height,
Row( Row(

@ -32,6 +32,7 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
@override @override
void initState() { void initState() {
print('initial value i got is ${widget.initialValue}');
_controller = TextEditingController(text: widget.initialValue); _controller = TextEditingController(text: widget.initialValue);
super.initState(); super.initState();
} }

Loading…
Cancel
Save