Compare commits

...

2 Commits

@ -4,13 +4,14 @@ class URLs {
static const String appReleaseBuildNumber = "28";
// static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static const host1 = "http://10.201.111.125:9495"; // temporary Server UAT url
// static String _baseUrl = "$_host/mobile";
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
static final String _baseUrl = "$_host/v3/mobile"; // for asset delivery module
// static final String _baseUrl = "$_host/mobile"; // host local UAT and for internal audit dev
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation
@ -391,4 +392,56 @@ class URLs {
static get getLoanById => '$_baseUrl/Loan/GetLoanById';
static get addLoan => '$_baseUrl/Loan/AddLoan';
//Asset Delivery Module
static get getAssetDeliveryDetailsById => '$_baseUrl/AssetDeliveryExternal/GetAssetDeliveryExternalById';
static get getAssetDeliveryTableListById => '$_baseUrl/AssetDeliveryExternalDelivery/GetDeliveriesByMasterId';
static get addNewDelivery => '$_baseUrl/AssetDeliveryExternalDelivery/AddNewDelivery';
static get changeDeliveryStatusToCancel => '$_baseUrl/AssetDeliveryExternalDelivery/ChangeStatusDeliveryToCancel';
static get changeDeliveryStatus => '$_baseUrl/AssetDeliveryExternalDelivery/ChangeStatusDelivery';
static get getAssetDeliveryInspectionData => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetAssetDeliveryExternalDeliveryInspectionByDeliveryId';
static get getOracleUserList => '$_baseUrl/AssetDeliveryExternal/GetEmployeesFromOracle';
static get getLineFromExternalPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetLineFromExternalPo';
static get getCostCenterListToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToLineDeliveryInspection';
static get getCostCenterToPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToPo';
static get saveCostCenterToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterToLineDeliveryInspection';
static get getDeliveryHistories => '$_baseUrl/AssetDeliveryExternalDelivery/GetDeliveryHistories';
//Technical Inscption...
static get getLineFromTechnicalInspection => '$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetLineFromDeliveryInspection';
static get getTechnicalInspectionByDetailId => '$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetTechnicalInspectionByDetailId';
static get powerSupplyTypeLookUp => "$_baseUrl/Lookups/GetLookup?lookupEnum=527";
static get saveTechnicalInspection => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/SaveTechnicalInspection";
static get getTechnicalInspectionParentData => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetTechnicalInspectionItemByCostCenterId";
static get getAssetFromInternalTechnicalInspection => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetFromInternal";
static get getAssetDetailsByAssetId => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetByIdFromInternal";
static get saveTechnicalInspectionAsset => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/SaveTechnicalInspectionItem";
static get getAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/GetAttachments";
static get saveAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/Save";
//End user Acceptance...
static get getEndUserAcceptanceCostCenter => "$_baseUrl/AssetDeliveryEndUserAcceptance/GetEndUserAcceptanceCostCenter";
static get getCostCenterAssetList => "$_baseUrl/AssetDeliveryEndUserAcceptance/GetItemByCostCenter";
static get saveEndUserFormData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveMaster";
static get saveEndUserAssetData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveDetail";
static get endUserStatusLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=534";
static get endUserRejectionReasonLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5007";
//Medical Gas Request..
// 4004
static get orderTypeLookUp => "$_baseUrl/Lookups/GetLookup?lookupEnum=4004";
static get itemTypeLookUp => "$_baseUrl/Lookups/GetLookup?lookupEnum=4005";
static get getMedicalGasSupplierList => "$_baseUrl/MedicalGas/GetMedicalGasSupplierAsync";
static get getMedicalGasInfoBySupplier => "$_baseUrl/MedicalGas/GetMedicalGasInfoBySupplierAsync";
static get addMedicalGasRequest => "$_baseUrl/MedicalGas/AddUpdateMedicalGasRequestAsync";
static get getMedicalGasById => "$_baseUrl/MedicalGas/GetMedicalGasRequestByIdAsync";
static get updateDeliveryNote => "$_baseUrl/MedicalGas/MedicalGasRequestDeliveryNotesAsync";
}

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -10,6 +11,7 @@ import 'package:test_sa/models/device/asset_by_id_model.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inpection_asset_model.dart';
import '../../../models/device/asset.dart';
@ -38,6 +40,7 @@ class AssetProvider extends ChangeNotifier {
List<Asset> _devices = [];
List<Asset> _searchDevices = [];
List<TechnicalInspectionAssetBasicInfoModel> technicalInspectionAsset= [];
List<Asset> get devices => _devices;
@ -99,6 +102,49 @@ class AssetProvider extends ChangeNotifier {
return response.statusCode;
}
Future<int> getAssetsForAssetDelivery({DeviceSearch? search, bool isSearchBy = false, int? lineId}) async {
if (_loading == true) return -2;
_loading = true;
notifyListeners();
late Response response;
try {
final Map<String, dynamic> body = {
"pageSize": isSearchBy ? searchPageItemNumber : pageItemNumber,
"pageNumber": isSearchBy ? (searchDevices.length / searchPageItemNumber).ceil() + 1 : devices.length ~/ pageItemNumber + 1,
///Uncommit this after testing...
"assetDeliveryExternalDetailId": lineId,
"assetName": search?.assetName,
// "assetDeliveryExternalDetailId": 2,
// "assetName": "Treatment Center Intego - Dental Chair",
"assetNumber": search?.assetNo,
"model": search?.model,
"manufacturer": search?.manufacturer,
};
response = await ApiManager.instance.post(URLs.getAssetFromInternalTechnicalInspection, body: body);
} catch (error) {
_loading = false;
_stateCode = -1;
notifyListeners();
return -1;
}
_stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List equipmentListJson = json.decode(response.body)["data"];
var dList = equipmentListJson.map<TechnicalInspectionAssetBasicInfoModel>((asset) => TechnicalInspectionAssetBasicInfoModel.fromJson(asset)).toList() ?? [];
log('dlist ${dList.length}');
technicalInspectionAsset.addAll(dList);
nextPage = true;
} else {
nextPage = false;
}
_loading = false;
notifyListeners();
return response.statusCode;
}
Future<AssetByIdModel> getAssetById(int assetId, AppLocalizations appLocalizations) async {
late Response response;
try {

@ -121,3 +121,7 @@ extension StringExtensionsRecurrentTaskInpesctionDataType on String {
}
}
}
enum DropDownMatchType {
identifier,
name,
}

@ -27,6 +27,11 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/report/servic
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_rejection_reason_lookup_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_status_lookup_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/power_supply_type_provider.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/create_cm_request.dart';
@ -41,6 +46,10 @@ import 'package:test_sa/modules/loan_module/pages/create_loan_request_page.dart'
import 'package:test_sa/modules/loan_module/provider/loan_period_provider.dart';
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
import 'package:test_sa/modules/loan_module/provider/medical_department_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/create_medical_gas_request_page.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/item_type_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_inspection_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/order_type_provider.dart';
import 'package:test_sa/modules/tm_module/gas_refill/create_gas_refill_request.dart';
import 'package:test_sa/modules/tm_module/gas_refill/update_gas_refill_request.dart';
import 'package:test_sa/modules/traf_module/create_traf_request_page.dart';
@ -109,6 +118,7 @@ import 'dashboard_latest/dashboard_provider.dart';
import 'modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart';
import 'modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
import 'modules/cx_module/survey/survey_provider.dart';
import 'modules/medical_gas_inspection/providers/medical_gas_supplier_provider.dart';
import 'modules/tm_module/device_transfer/create_device_transfer_request.dart';
import 'modules/tm_module/device_transfer/device_filter_screen.dart';
import 'modules/tm_module/device_transfer/device_search_screen.dart';
@ -316,6 +326,15 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => LoanProvider()),
ChangeNotifierProvider(create: (_) => LoanPeriodProvider()),
ChangeNotifierProvider(create: (_) => MedicalDepartmentProvider()),
ChangeNotifierProvider(create: (_) => AssetDeliveryProvider()),
ChangeNotifierProvider(create: (_) => CostCenterProvider()),
ChangeNotifierProvider(create: (_) => PowerSupplyTypeProvider()),
ChangeNotifierProvider(create: (_) => EndUserStatusLookupProvider()),
ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider()),
ChangeNotifierProvider(create: (_) => MedicalGasOrderTypeProvider()),
ChangeNotifierProvider(create: (_) => MedicalGasItemTypeProvider()),
ChangeNotifierProvider(create: (_) => MedicalGasInspectionProvider()),
ChangeNotifierProvider(create: (_) => MedicalGasSupplierProvider()),
],
child: GestureDetector(
onTap: () {
@ -383,6 +402,7 @@ class MyApp extends StatelessWidget {
UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(),
UpdateSystemInternalAuditPage.id: (_) => UpdateSystemInternalAuditPage(),
CreateLoanRequestPage.id: (_) => CreateLoanRequestPage(),
CreateMedicalGasRequestPage.id: (_) => CreateMedicalGasRequestPage(),
// SwipeSuccessView.routeName: (_) => const SwipeSuccessView(),
// SwipeHistoryView.routeName: (_) => const SwipeHistoryView(),
},

@ -128,6 +128,8 @@ class RequestsDetails {
String? date;
String? siteTransferFrom;
String? siteTransferTo;
String? poInternal;
String? poExternal;
int? transactionType;
int? numberOfAssets;
int? numberOfSites;
@ -156,6 +158,8 @@ class RequestsDetails {
this.code,
this.siteTransferFrom,
this.siteTransferTo,
this.poInternal,
this.poExternal,
this.date,
this.transactionType});
@ -182,6 +186,8 @@ class RequestsDetails {
assetTransferTo = json['assetTransferTo'];
code = json['code'];
date = json['date'];
poInternal = json['poInternal'];
poExternal = json['poExternal'];
siteTransferFrom = json['siteTransferFrom'];
siteTransferTo = json['siteTransferTo'];
transactionType = json['transactionType'];

@ -1,6 +1,7 @@
import 'package:test_sa/models/lookup.dart';
class DeviceSearch {
DeviceSearch(
{this.code,
this.assetSerialNumber,

@ -8,7 +8,6 @@ class GenericAttachmentModel {
String ?createdBy;
String? originalName;
GenericAttachmentModel.fromJson(Map<String, dynamic> json) {
print('created by here is ${json['createdBy']}');
id = json['id'];
name = json['name'];
createdBy = json['createdBy'];

@ -55,6 +55,9 @@ class Data {
String? assetNumber;
String? requestTypeName;
String? requestNo;
String? requestType;
String? poInternal;
String? poExternal;
int? transactionNo;
int? numberOfSites;
int? numberOfAssets;
@ -75,6 +78,9 @@ class Data {
this.assetNumber,
this.requestTypeName,
this.requestNo,
this.requestType,
this.poExternal,
this.poInternal,
this.transactionNo});
Data.fromJson(Map<String, dynamic> json) {
@ -86,6 +92,7 @@ class Data {
isHighPriority = json['isHighPriority'];
assetName = json['assetName'];
sessionType = json['sessionType'];
requestType = json['requestType'];
numberOfSites = json['numberOfSites'];
numberOfAssets = json['numberOfAssets'];
assetNumber = json['assetNumber'];
@ -93,6 +100,8 @@ class Data {
requestNo = json['requestNo'];
rejectReason = json['rejectReason'];
transactionNo = json['transactionNo'];
poInternal = json['poInternal'];
poExternal = json['poExternal'];
nameOfType = json['nameOfType'];
}

@ -0,0 +1,383 @@
import 'package:test_sa/models/lookup.dart';
class AssetDeliveryDataModel {
int? id;
bool? isHMG;
int? operatingUnitId;
String? operatingUnit;
String? clientName;
int? poNumberId;
int? poNumber;
SiteModel? site;
Lookup? paymentTerm;
num? paymentTermAmount;
num? deliveryAmount;
num? total;
num? totalInvoice;
String? edd;
double? warrentyPeriod;
AssetDeliveryInternalMaster? assetDeliveryInternalMaster;
PurchaseOrderMaster? purchaseOrderMaster;
List<AssetDeliveryExternalDetail>? assetDeliveryExternalDetails;
List<AssetDeliveryTableModel>? assetDeliveryExternalDeliveries;
AssetDeliveryDataModel();
AssetDeliveryDataModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
isHMG = json['isHMG'];
operatingUnitId = json['operatingUnitId'];
clientName = json['clientName'];
operatingUnit = json['operatingUnit'];
poNumberId = json['poNumberId'];
poNumber = json['poNumber'];
total = json['total'];
totalInvoice = json['totalInvoice'];
edd = json['edd'];
deliveryAmount = json['deliveryAmount'];
site = json['site'] != null
? SiteModel.fromJson(json['site'])
: null;
paymentTerm = json['paymentTerm'] != null
? Lookup.fromJson(json['paymentTerm'])
: null;
paymentTermAmount = json['paymentTermAmount'];
warrentyPeriod = json['warrentyPeriod'];
assetDeliveryInternalMaster = json['assetDeliveryInternalMaster'] != null
? AssetDeliveryInternalMaster.fromJson(json['assetDeliveryInternalMaster'])
: null;
purchaseOrderMaster = json['purchaseOrderMaster'] != null
? PurchaseOrderMaster.fromJson(json['purchaseOrderMaster'])
: null;
if (json['assetDeliveryExternalDetails'] != null) {
assetDeliveryExternalDetails = [];
json['assetDeliveryExternalDetails'].forEach((v) {
assetDeliveryExternalDetails!.add(AssetDeliveryExternalDetail.fromJson(v));
});
}
if (json['assetDeliveryExternalDeliveries'] != null) {
assetDeliveryExternalDeliveries = [];
json['assetDeliveryExternalDeliveries'].forEach((v) {
assetDeliveryExternalDeliveries!.add(AssetDeliveryTableModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['id'] = id;
data['isHMG'] = isHMG;
data['operatingUnitId'] = operatingUnitId;
data['operatingUnit'] = operatingUnit;
data['clientName'] = clientName;
data['poNumberId'] = poNumberId;
data['poNumber'] = poNumber;
data['total'] = total;
data['edd'] = edd;
data['totalInvoice'] = totalInvoice;
data['deliveryAmount'] = deliveryAmount;
data['site'] = site;
data['paymentTermAmount'] = paymentTermAmount;
data['warrentyPeriod'] = warrentyPeriod;
if (paymentTerm != null) data['paymentTerm'] = paymentTerm!.toJson();
if (assetDeliveryInternalMaster != null) {
data['assetDeliveryInternalMaster'] =
assetDeliveryInternalMaster!.toJson();
}
if (assetDeliveryExternalDetails != null) {
data['assetDeliveryExternalDetails'] =
assetDeliveryExternalDetails!.map((v) => v.toJson()).toList();
}
if (assetDeliveryExternalDeliveries != null) {
data['assetDeliveryExternalDeliveries'] =
assetDeliveryExternalDeliveries!.map((v) => v.toJson()).toList();
}
return data;
}
}
class AssetDeliveryInternalMaster {
int? id;
int? operatingUnitId;
String? operatingUnit;
int? poNumberId;
int? poNumber;
String? supplier;
String? supplierSite;
String? type;
String? buyer;
num? total;
String? currency;
String? remark;
String? status;
String? paymentTerms;
double? warrantyPeriod;
String? assetDeliveryStatus;
String? statusDocument;
String? remarkDocument;
String? edd;
AssetDeliveryInternalMaster();
AssetDeliveryInternalMaster.fromJson(Map<String, dynamic> json) {
id = json['id'];
operatingUnitId = json['operatingUnitId'];
operatingUnit = json['operatingUnit'];
poNumberId = json['poNumberId'];
poNumber = json['poNumber'];
supplier = json['supplier'];
supplierSite = json['supplierSite'];
type = json['type'];
buyer = json['buyer'];
total = json['total'];
currency = json['currency'];
remark = json['remark'];
status = json['status'];
paymentTerms = json['paymentTerms'];
warrantyPeriod = json['warrantyPeriod'];
assetDeliveryStatus = json['assetDeliveryStatus'];
statusDocument = json['statusDocument'];
remarkDocument = json['remarkDocument'];
edd = json['edd'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'operatingUnitId': operatingUnitId,
'operatingUnit': operatingUnit,
'poNumberId': poNumberId,
'poNumber': poNumber,
'supplier': supplier,
'supplierSite': supplierSite,
'type': type,
'buyer': buyer,
'total': total,
'currency': currency,
'remark': remark,
'status': status,
'paymentTerms': paymentTerms,
'warrantyPeriod': warrantyPeriod,
'assetDeliveryStatus': assetDeliveryStatus,
'statusDocument': statusDocument,
'remarkDocument': remarkDocument,
'edd': edd,
};
}
}
class AssetDeliveryExternalDetail {
int? id;
AssetDeliveryInternalDetail? assetDeliveryInternalDetail;
String? itemNumber;
String? lineType;
String? unitMeasure;
num? qtyOrdered;
num? qtyReceived;
num? qtyBilled;
num? qtyCancelled;
num? unitPrice;
num? unitPriceWithTax;
String? itemDescription;
AssetDeliveryExternalDetail();
AssetDeliveryExternalDetail.fromJson(Map<String, dynamic> json) {
id = json['id'];
itemNumber = json['itemNumber'];
lineType = json['lineType'];
unitMeasure = json['unitMeasure'];
qtyOrdered = json['qtyOrdered'];
qtyReceived = json['qtyReceived'];
qtyBilled = json['qtyBilled'];
qtyCancelled = json['qtyCancelled'];
unitPrice = json['unitPrice'];
unitPriceWithTax = json['unitPriceWithTax'];
itemDescription = json['itemDescription'];
assetDeliveryInternalDetail =
json['assetDeliveryInternalDetail'] != null
? AssetDeliveryInternalDetail.fromJson(
json['assetDeliveryInternalDetail'])
: null;
}
Map<String, dynamic> toJson() {
return {
'id': id,
'itemNumber': itemNumber,
'lineType': lineType,
'unitMeasure': unitMeasure,
'qtyOrdered': qtyOrdered,
'qtyReceived': qtyReceived,
'qtyBilled': qtyBilled,
'qtyCancelled': qtyCancelled,
'unitPrice': unitPrice,
'unitPriceWithTax': unitPriceWithTax,
'itemDescription': itemDescription,
'assetDeliveryInternalDetail':
assetDeliveryInternalDetail?.toJson(),
};
}
}
class AssetDeliveryInternalDetail {
int? id;
int? lineId;
String? itemNumber;
String? itemDescription;
String? unitMeasure;
num? qtyOrdered;
num? qtyReceived;
num? qtyBilled;
num? qtyCancelled;
num? unitPrice;
num? unitPriceWithTax;
String? itemCategory;
num? totalAssets;
num? childPerAsset;
AssetDeliveryInternalDetail();
AssetDeliveryInternalDetail.fromJson(Map<String, dynamic> json) {
id = json['id'];
lineId = json['lineId'];
itemNumber = json['itemNumber'];
itemDescription = json['itemDescription'];
unitMeasure = json['unitMeasure'];
qtyOrdered = json['qtyOrdered'];
qtyReceived = json['qtyReceived'];
qtyBilled = json['qtyBilled'];
qtyCancelled = json['qtyCancelled'];
unitPrice = json['unitPrice'];
unitPriceWithTax = json['unitPriceWithTax'];
itemCategory = json['itemCategory'];
totalAssets = json['totalAssets'];
childPerAsset = json['childPerAsset'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'lineId': lineId,
'itemNumber': itemNumber,
'itemDescription': itemDescription,
'unitMeasure': unitMeasure,
'qtyOrdered': qtyOrdered,
'qtyReceived': qtyReceived,
'qtyBilled': qtyBilled,
'qtyCancelled': qtyCancelled,
'unitPrice': unitPrice,
'unitPriceWithTax': unitPriceWithTax,
'itemCategory': itemCategory,
'totalAssets': totalAssets,
'childPerAsset': childPerAsset,
};
}
}
class AssetDeliveryTableModel {
int? id;
Lookup? status;
String? number;
num? deliveryAmount;
num? invoiceAmount;
bool? isContainsTechnicalInspection;
AssetDeliveryTableModel();
AssetDeliveryTableModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
number = json['number'];
deliveryAmount = json['deliveryAmount'];
invoiceAmount = json['invoiceAmount'];
isContainsTechnicalInspection = json['isContainsTechnicalInspection'];
status = json['status'] != null
? Lookup.fromJson(json['status'])
: null;
}
Map<String, dynamic> toJson() {
return {
'id': id,
'number': number,
'deliveryAmount': deliveryAmount,
'invoiceAmount': invoiceAmount,
'isContainsTechnicalInspection': isContainsTechnicalInspection,
'status': status?.toJson(),
};
}
}
class PurchaseOrderMaster {
int? id;
num? poNumber;
int? siteId;
String? siteName;
num? amount;
String? remarks;
String? statuss;
List<PurchaseOrderDetails>? assetDeliveryPurchaseOrderDetails;
PurchaseOrderMaster({
this.id,
this.poNumber,
this.siteId,
this.siteName,
this.amount,
this.remarks,
this.statuss,
this.assetDeliveryPurchaseOrderDetails,
});
PurchaseOrderMaster.fromJson(Map<String, dynamic> json) {
id = json['id'];
poNumber = json['poNumber'];
siteId = json['siteId'];
siteName = json['siteName'];
amount = json['amount'];
remarks = json['remarks'];
statuss = json['statuss'];
if (json['assetDeliveryPurchaseOrderDetails'] != null &&
json['assetDeliveryPurchaseOrderDetails'] is List) {
assetDeliveryPurchaseOrderDetails =
(json['assetDeliveryPurchaseOrderDetails'] as List)
.map((e) => PurchaseOrderDetails.fromJson(e))
.toList();
} else {
assetDeliveryPurchaseOrderDetails = null;
}
}
}
class SiteModel{
int? id;
String? siteName;
SiteModel({
this.id,
this.siteName,
});
SiteModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
siteName = json['siteName'];
}
}
///Check this model if required and whats the parm
class PurchaseOrderDetails {
// No fields provided in your JSON placeholder
PurchaseOrderDetails();
PurchaseOrderDetails.fromJson(Map<String, dynamic> json);
}

@ -1,345 +0,0 @@
import 'dart:developer';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/room_model.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import '../../../models/new_models/department.dart';
class AssetInventoryResponse {
num? totalRows;
num? count;
String? message;
String? title;
String? innerMessage;
num? responseCode;
bool? isSuccess;
List<AssetInventoryModel>? assetList;
AssetInventoryResponse({
this.totalRows,
this.count,
this.message,
this.title,
this.innerMessage,
this.responseCode,
this.isSuccess,
this.assetList,
});
AssetInventoryResponse.fromJson(Map<String, dynamic> json) {
totalRows = json['totalRows'];
count = json['count'];
message = json['message'];
title = json['title'];
innerMessage = json['innerMessage'];
responseCode = json['responseCode'];
isSuccess = json['isSuccess'];
if (json['data'] != null) {
assetList = (json['data'] as List).map((item) => AssetInventoryModel.fromJson(item)).toList();
}
}
Map<String, dynamic> toJson() {
return {
'totalRows': totalRows,
'count': count,
'message': message,
'title': title,
'innerMessage': innerMessage,
'responseCode': responseCode,
'isSuccess': isSuccess,
};
}
}
class AssetInventoryModel {
num? id;
num? assetId;
String? transactionDate;
String? assetNumber;
String? serialNo;
String? assetName;
num? assetNameId;
String? model;
String? manufacturer;
String? supplierName;
String? siteName;
String? buildingName;
String? floorName;
String? departmentName;
String? roomName;
num? statusId;
String? status;
num? statusValue;
num? statusByAdminId;
String? statusByAdmin;
num? statusByAdminValue;
bool? isNotRegistered;
num? sessionId;
num? assetImportId;
num? siteId;
num? supplierId;
num? buildingId;
num? floorId;
num? departmentId;
num? roomId;
String? newAssetNumber;
String? newSerialNo;
num? newAssetNameId;
String? newAssetNameText;
num? newModelId;
String? newModelName;
num? manufacturerId;
num? modelId;
num? newManufacturerId;
String? newManufacturerName;
num? newSupplierId;
String? newSupplierName;
String? photo;
String? photoOriginName;
String? remarks;
Site? site;
Building? building;
Floor? floor;
Department? department;
Rooms? room;
SupplierDetails? supplier;
List<AssetInventoryDetailAssetAttachments> assetInventoryDetailAssetAttachments = [];
AssetInventoryModel({
this.id,
this.sessionId,
this.assetId,
this.transactionDate,
this.assetNumber,
this.assetNameId,
this.serialNo,
this.assetName,
this.model,
this.manufacturer,
this.supplierName,
this.siteName,
this.buildingName,
this.floorName,
this.departmentName,
this.roomName,
this.statusId,
this.status,
this.statusValue,
this.statusByAdminId,
this.statusByAdmin,
this.statusByAdminValue,
this.isNotRegistered,
this.assetImportId,
this.siteId,
this.buildingId,
this.floorId,
this.departmentId,
this.supplierId,
this.roomId,
this.newAssetNumber,
this.manufacturerId,
this.newSerialNo,
this.newAssetNameId,
this.newAssetNameText,
this.newModelId,
this.modelId,
this.newModelName,
this.newManufacturerId,
this.newManufacturerName,
this.newSupplierId,
this.newSupplierName,
this.photo,
this.photoOriginName,
this.remarks,
this.site,
this.department,
this.building,
this.floor,
this.room,
this.supplier,
this.assetInventoryDetailAssetAttachments = const [],
});
AssetInventoryModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
assetId = json['assetId'];
transactionDate = json['transactionDate'];
assetNumber = json['assetNumber'];
assetNameId = json['assetNameId'];
serialNo = json['serialNo'];
assetName = json['assetName'];
model = json['model'] ?? json['modelName'];
manufacturer = json['manufacturer'] ?? json['manufacturerName'];
supplierName = json['supplierName'];
siteName = json['site'] ?? json['siteName'];
buildingName = json['building'] ?? json['buildingName'];
floorName = json['floor'] ?? json['floorName'];
departmentName = json['department'] ?? json['departmentName'];
roomName = json['room'] ?? json['roomName'];
statusId = json['statusId'];
status = json['status'] ?? json['classification'];
statusValue = json['statusValue'];
isNotRegistered = json['isNotRegistered'];
sessionId = json['sessionId'];
assetImportId = json['assetImportId']??json['id'];
siteId = json['siteId'];
buildingId = json['buildingId'];
floorId = json['floorId'];
supplierId = json['supplierId'];
departmentId = json['departmentId'];
roomId = json['roomId'];
modelId = json['modelId'];
photo = json['photo'];
photoOriginName = json['photoOriginName'];
remarks = json['remarks'];
if (json['assetTransferAttachments'] != null) {
assetInventoryDetailAssetAttachments = [];
json['assetInventoryDetailAssetAttachments'].forEach((v) {
assetInventoryDetailAssetAttachments.add(AssetInventoryDetailAssetAttachments.fromJson(v));
});
}
//new data..
// newAssetNumber = json['newAssetNumber'] ?? json['assetNumber'];
// manufacturerId = json['manufacturerId'] ?? json['manufacturerId'];
// newSerialNo = json['newSerialNo'] ?? json['serialNo'];
// newAssetNameId = json['newAssetNameId'] ?? json['assetNameId'];
// newAssetNameText = json['newAssetNameText'] ?? json['assetNameText'];
// newModelId = json['newModelId'] ?? json['modelId'];
// newModelName = json['newModelName'] ?? json['modelName'];
// newManufacturerId = json['newManufacturerId'] ?? json['manufacturerId'];
// newManufacturerName = json['newManufacturerName'] ?? json['manufacturerName'];
// newSupplierId = json['newSupplierId'] ?? json['supplierId'];
// newSupplierName = json['newSupplierName'] ?? json['supplierName'];
}
Map<String, dynamic> toJson() {
return {
'isNotRegistered': isNotRegistered,
'sessionId': sessionId,
'assetImportId': assetImportId,
'transactionDate': transactionDate,
'assetId': assetId,
'siteId': siteId,
'buildingId': buildingId,
'floorId': floorId,
'departmentId': departmentId,
'roomId': roomId,
'newSerialNo': newSerialNo,
'newAssetNameId': newAssetNameId,
'newAssetNameText': newAssetNameText,
'newAssetNumber': newAssetNumber,
'newModelId': newModelId,
'newModelName': newModelName,
'newManufacturerId': newManufacturerId,
'newManufacturerName': newManufacturerName,
'newSupplierId': newSupplierId,
'newSupplierName': newSupplierName,
'photo': photo,
'remarks': remarks,
'assetInventoryDetailAssetAttachments': assetInventoryDetailAssetAttachments != null
? assetInventoryDetailAssetAttachments!.map((v) => v.toJson()).toList()
: [],
};
}
AssetInventoryModel mergeWith(AssetInventoryModel? other) {
if (other == null) return this;
return AssetInventoryModel(
id: id ?? other.id,
assetId: assetId ?? other.assetId,
transactionDate: transactionDate ?? other.transactionDate,
assetNumber: assetNumber ?? other.assetNumber,
serialNo: serialNo ?? other.serialNo,
assetName: assetName ?? other.assetName,
assetNameId: assetNameId ?? other.assetNameId,
model: model ?? other.model,
manufacturer: manufacturer ?? other.manufacturer,
supplierName: supplierName ?? other.supplierName,
siteName: siteName ?? other.siteName,
buildingName: buildingName ?? other.buildingName,
floorName: floorName ?? other.floorName,
departmentName: departmentName ?? other.departmentName,
roomName: roomName ?? other.roomName,
statusId: statusId ?? other.statusId,
status: status ?? other.status,
statusValue: statusValue ?? other.statusValue,
statusByAdminId: statusByAdminId ?? other.statusByAdminId,
statusByAdmin: statusByAdmin ?? other.statusByAdmin,
statusByAdminValue: statusByAdminValue ?? other.statusByAdminValue,
isNotRegistered: isNotRegistered ?? other.isNotRegistered,
sessionId: sessionId ?? other.sessionId,
assetImportId: assetImportId ?? other.assetImportId,
siteId: siteId ?? other.siteId,
supplierId: supplierId ?? other.supplierId,
buildingId: buildingId ?? other.buildingId,
floorId: floorId ?? other.floorId,
departmentId: departmentId ?? other.departmentId,
roomId: roomId ?? other.roomId,
newAssetNumber: newAssetNumber ?? other.newAssetNumber,
newSerialNo: newSerialNo ?? other.newSerialNo,
newAssetNameId: newAssetNameId ?? other.newAssetNameId,
newAssetNameText: newAssetNameText ?? other.newAssetNameText,
newModelId: newModelId ?? other.newModelId,
newModelName: newModelName ?? other.newModelName,
manufacturerId: manufacturerId ?? other.manufacturerId,
modelId: modelId ?? other.modelId,
newManufacturerId: newManufacturerId ?? other.newManufacturerId,
newManufacturerName: newManufacturerName ?? other.newManufacturerName,
newSupplierId: newSupplierId ?? other.newSupplierId,
newSupplierName: newSupplierName ?? other.newSupplierName,
photo: photo ?? other.photo,
photoOriginName: photoOriginName ?? other.photoOriginName,
remarks: remarks ?? other.remarks,
site: site ?? other.site,
building: building ?? other.building,
floor: floor ?? other.floor,
department: department ?? other.department,
room: room ?? other.room,
supplier: supplier ?? other.supplier,
assetInventoryDetailAssetAttachments: assetInventoryDetailAssetAttachments??other.assetInventoryDetailAssetAttachments,
);
}
}
class AssetInventoryDetailAssetAttachments {
AssetInventoryDetailAssetAttachments({
this.id,
this.name,
this.originalName,
});
AssetInventoryDetailAssetAttachments.fromJson(dynamic json) {
id = json['id'];
name = json['name'];
originalName = json['originalName'];
}
num? id;
String? name;
String? originalName;
AssetInventoryDetailAssetAttachments copyWith({
num? id, // Parameter is now nullable
String? name, // Parameter is now nullable
String? originalName, // Parameter is now nullable
}) =>
AssetInventoryDetailAssetAttachments(
id: id ?? this.id,
name: name??this.name,
originalName: originalName??this.originalName,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['name'] = name;
map['originalName'] = originalName;
return map;
}
}

@ -1,27 +1,62 @@
import 'package:test_sa/models/lookup.dart';
class CostCenterModel {
int? id;
int? assetDeliveryExternalDetailId;
Lookup? costCenter;
String? acceptedBy;
String? costCenterName;
DateTime? acceptanceDate;
String? acceptedByEmail;
String? acceptedBySignature;
double? quantity;
CostCenterModel({
this.id,
this.assetDeliveryExternalDetailId,
this.costCenter,
this.acceptedBy,
this.costCenterName,
this.acceptanceDate,
this.acceptedByEmail,
this.acceptedBySignature,
this.quantity,
});
CostCenterModel.fromJson(Map<String, dynamic> json) {
costCenter = json['costCenter'] != null
? Lookup.fromJson(json['costCenter'])
: null;
quantity = json['quantity'];
costCenterName = json['costCenter'] ?? json['costCenterName'];
acceptanceDate = json['acceptanceDate'] != null ? DateTime.tryParse(json['acceptanceDate']) : null;
acceptedBySignature = json['acceptedBySignature'];
acceptedByEmail = json['acceptedByEmail'];
quantity = json['qty'] ?? json['costCenterQty'];
acceptedBy = json['acceptedBy'];
costCenter = json['costCenter'] != null ? Lookup(name: json['costCenter']) : null;
id = json['id'] ?? json['costCenterId'];
assetDeliveryExternalDetailId = json['assetDeliveryExternalDetailId'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
if (costCenter != null) {
data['costCenter'] = costCenter!.toJson();
}
data['quantity'] = quantity;
data['id'] = id ?? 0;
data['qty'] = quantity;
// data['costCenter'] = costCenter;
// data['acceptedBy'] = acceptedBy;
// data['acceptanceDate'] = acceptanceDate;
// data['acceptedByEmail'] = acceptedByEmail;
// data['acceptedBySignature'] = acceptedBySignature;
data['costCenter'] = costCenterName;
return data;
}
Map<String, dynamic> toEndUserAcceptanceFormJson() {
final Map<String, dynamic> data = {};
data['assetDeliveryExternalDeliveryId'] = assetDeliveryExternalDetailId;
data['costCenterName'] = costCenterName;
data['acceptedBy'] = acceptedBy;
data['acceptanceDate'] = acceptanceDate?.toIso8601String();
data['acceptedByEmail'] = acceptedByEmail;
data['acceptedBySignature'] = acceptedBySignature;
return data;
}
}

@ -0,0 +1,37 @@
class DeliveryInspectionFormModel {
int? assetDeliveryExternalDeliveryId;
String? deliveryInspectionInspectedBy;
DateTime? deliveryInspectionInspectedDateFrom;
DateTime? deliveryInspectionInspectedDateTo;
num? totalTime;
String? deliveryInspectionApprovedBy;
DeliveryInspectionFormModel({
this.assetDeliveryExternalDeliveryId,
this.deliveryInspectionInspectedBy,
this.deliveryInspectionInspectedDateFrom,
this.deliveryInspectionInspectedDateTo,
this.totalTime,
this.deliveryInspectionApprovedBy,
});
DeliveryInspectionFormModel.fromJson(Map<String, dynamic> json) {
assetDeliveryExternalDeliveryId = json['assetDeliveryExternalDeliveryId'];
deliveryInspectionInspectedBy = json['deliveryInspectionInspectedBy'];
deliveryInspectionInspectedDateFrom = json['deliveryInspectionInspectedDateFrom']!=null?DateTime.tryParse(json['deliveryInspectionInspectedDateFrom']):null;
deliveryInspectionInspectedDateTo = json['deliveryInspectionInspectedDateTo']!=null?DateTime.tryParse(json['deliveryInspectionInspectedDateTo']):null;
totalTime = json['totalTime'];
deliveryInspectionApprovedBy = json['deliveryInspectionApprovedBy'];
}
Map<String, dynamic> toJson() {
return {
'assetDeliveryExternalDeliveryId': assetDeliveryExternalDeliveryId,
'deliveryInspectionInspectedBy': deliveryInspectionInspectedBy,
'deliveryInspectionInspectedDateFrom': deliveryInspectionInspectedDateFrom?.toIso8601String(),
'deliveryInspectionInspectedDateTo': deliveryInspectionInspectedDateTo?.toIso8601String(),
'totalTime': totalTime,
'deliveryInspectionApprovedBy': deliveryInspectionApprovedBy,
};
}
}

@ -0,0 +1,61 @@
class DeliveryLineModel {
int? id;
int? assetDeliveryInternalDetailId;
String? itemNumber;
String? itemDescription;
num? qty;
num? remainingQty;
num? usingQtyInThisDelivery;
num? unitPrice;
num? total;
String? unitOfMeasure;
String? lineType;
String? itemCategory;
DeliveryLineModel({
this.id,
this.assetDeliveryInternalDetailId,
this.itemNumber,
this.itemDescription,
this.qty,
this.remainingQty,
this.usingQtyInThisDelivery,
this.unitPrice,
this.total,
this.unitOfMeasure,
this.lineType,
this.itemCategory,
});
DeliveryLineModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
assetDeliveryInternalDetailId = json['assetDeliveryInternalDetailId'];
itemNumber = json['itemNumber'];
itemDescription = json['itemDescription'];
qty = json['qty'];
remainingQty = json['remainingQty'];
usingQtyInThisDelivery = json['usingQtyInThisDelivery'];
unitPrice = json['unitPrice'];
total = json['total'];
unitOfMeasure = json['unitOfMeasure'];
lineType = json['lineType'];
itemCategory = json['itemCategory'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'assetDeliveryInternalDetailId': assetDeliveryInternalDetailId,
'itemNumber': itemNumber,
'itemDescription': itemDescription,
'qty': qty,
'remainingQty': remainingQty,
'usingQtyInThisDelivery': usingQtyInThisDelivery,
'unitPrice': unitPrice,
'total': total,
'unitOfMeasure': unitOfMeasure,
'lineType': lineType,
'itemCategory': itemCategory,
};
}
}

@ -0,0 +1,71 @@
import 'package:test_sa/models/lookup.dart';
class EndUserAssetDetailsModel {
int? id;
int? typeId;
int? assetDeliveryExternalDeliveryId;
String? type;
String? itemNumber;
String? costCenterName;
Lookup? status;
Lookup? rejectionReason;
String? description;
double? receivedQty;
num? rejectedQty;
String? assetNumber;
String? serialNo;
String? assetType;
String? replacedAssetNo;
EndUserAssetDetailsModel(
{this.costCenterName,
this.rejectedQty,
this.description,
this.id,
this.typeId,
this.status,
this.rejectionReason,
this.assetType,
this.assetNumber,
this.serialNo,
this.itemNumber,
this.type,
this.receivedQty,
this.replacedAssetNo,
this.assetDeliveryExternalDeliveryId});
EndUserAssetDetailsModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
typeId = json['typeId'];
type = json['type'];
itemNumber = json['itemNumber'];
status = json['status'] != null ? Lookup.fromJson(json['status']) : null;
rejectionReason = json['rejectReason'] != null ? Lookup.fromJson(json['rejectReason']) : null;
description = json['description'];
receivedQty = json['receivedQty'];
rejectedQty = json['rejectedQty'];
assetNumber = json['assetNumber'];
serialNo = json['serialNo'];
assetType = json['assetType'];
replacedAssetNo = json['replacedAssetNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['id'] = id;
data['assetDeliveryExternalDeliveryId'] = assetDeliveryExternalDeliveryId;
data['costCenterName'] = costCenterName;
data['typeId'] = typeId;
data['type'] = type;
data['itemNumber'] = itemNumber;
data['statusId'] = status?.id;
// data['status'] = status;
// data['rejectionReason'] = rejectionReason;
data['rejectReasonId'] = rejectionReason?.id;
data['description'] = description;
data['receivedQty'] = receivedQty;
data['rejectedQty'] = rejectedQty;
return data;
}
}

@ -0,0 +1,34 @@
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
class AssetDeliveryHistoryModel {
WorkOrderAssignedEmployee? user;
Lookup? status;
DateTime? createdDate;
String ?timeDifference;
AssetDeliveryHistoryModel({
this.user,
this.status,
this.createdDate,
this.timeDifference,
});
AssetDeliveryHistoryModel.fromJson(Map<String, dynamic> json) {
user = json['user'] != null ? WorkOrderAssignedEmployee.fromJson(json['user']) : null;
status = json['status'] != null ? Lookup.fromJson(json['status']) : null;
createdDate = json['createdDate'] != null ? DateTime.tryParse(json['createdDate']) : null;
timeDifference = '';
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (user != null) {
data['user'] = user!.toJson();
}
if (status != null) {
data['status'] = status!.toJson();
}
return data;
}
}

@ -0,0 +1,26 @@
class OracleUserModel {
String? employeeNumber;
String? fullName;
String? job;
String? employeeMobileNumber;
String? employeeExtensionNumber;
String? employeeEmail;
OracleUserModel({
this.employeeNumber,
this.fullName,
this.job,
this.employeeMobileNumber,
this.employeeExtensionNumber,
this.employeeEmail,
});
OracleUserModel.fromJson(Map<String, dynamic> json) {
employeeNumber = json['employeeNumber'];
fullName = json['fullName'];
job = json['job'];
employeeMobileNumber = json['employeeMobileNumber'];
employeeExtensionNumber = json['employeeExtensionNumber'];
employeeEmail = json['employeeEmail'];
}
}

@ -1,234 +0,0 @@
import 'package:test_sa/models/new_models/site.dart';
class SessionModel {
int? id;
String? createdDate;
String? sessionName;
int? sessionTypeId;
int? sessionTypeValue;
String? sessionTypeName;
int? statusId;
String? statusName;
String? startDate;
String? endDate;
List<Site> assetInventorySites = [];
List<AssetInventoryAssignedEmployee> assetInventoryAssignedEmployee = [];
SessionModel({
this.id,
this.sessionName,
this.createdDate,
this.sessionTypeId,
this.sessionTypeValue,
this.sessionTypeName,
this.statusId,
this.statusName,
this.startDate,
this.endDate,
List<Site>? assetInventorySites,
List<AssetInventoryAssignedEmployee>? assetInventoryAssignedEmployee,
}) {
this.assetInventorySites = assetInventorySites ?? [];
this.assetInventoryAssignedEmployee = assetInventoryAssignedEmployee ?? [];
}
SessionModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
sessionName = json['sessionName'];
sessionTypeId = json['sessionTypeId'];
sessionTypeValue = json['sessionTypeValue'];
sessionTypeName = json['sessionTypeName'];
statusId = json['statusId'];
createdDate = json['createdDate'];
statusName = json['statusName'];
startDate = json['startDate'];
endDate = json['endDate'];
if (json['assetInventorySites'] != null) {
assetInventorySites = (json['assetInventorySites'] as List).map((e) => Site.fromJson(e)).toList();
}
if (json['assetInventoryAssignedEmployee'] != null) {
assetInventoryAssignedEmployee = (json['assetInventoryAssignedEmployee'] as List).map((e) => AssetInventoryAssignedEmployee.fromJson(e)).toList();
}
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['sessionName'] = sessionName;
map['sessionTypeId'] = sessionTypeId;
map['sessionTypeValue'] = sessionTypeValue;
map['sessionTypeName'] = sessionTypeName;
map['statusId'] = statusId;
map['statusName'] = statusName;
map['createdDate'] = createdDate;
map['startDate'] = startDate;
map['endDate'] = endDate;
map['assetInventorySites'] = assetInventorySites.map((e) => e.toJson()).toList();
map['assetInventoryAssignedEmployee'] = assetInventoryAssignedEmployee.map((e) => e.toJson()).toList();
return map;
}
}
// class AssetInventorySite {
// int? siteId;
// String? siteName;
// List<AssetInventoryBuilding> assetInventoryBuildings = [];
//
// AssetInventorySite({
// this.siteId,
// this.siteName,
// List<AssetInventoryBuilding>? assetInventoryBuildings,
// }) {
// this.assetInventoryBuildings = assetInventoryBuildings ?? [];
// }
//
// AssetInventorySite.fromJson(Map<String, dynamic> json) {
// siteId = json['siteId'];
// siteName = json['siteName'];
//
// if (json['assetInventoryBuildings'] != null) {
// assetInventoryBuildings = (json['assetInventoryBuildings'] as List).map((e) => AssetInventoryBuilding.fromJson(e)).toList();
// }
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['siteId'] = siteId;
// map['siteName'] = siteName;
// map['assetInventoryBuildings'] = assetInventoryBuildings.map((e) => e.toJson()).toList();
// return map;
// }
// }
//
// class AssetInventoryBuilding {
// int? buildingId;
// String? buildingName;
// List<AssetInventoryFloor> assetInventoryFloors = [];
//
// AssetInventoryBuilding({
// this.buildingId,
// this.buildingName,
// List<AssetInventoryFloor>? assetInventoryFloors,
// }) {
// this.assetInventoryFloors = assetInventoryFloors ?? [];
// }
//
// AssetInventoryBuilding.fromJson(Map<String, dynamic> json) {
// buildingId = json['buildingId'];
// buildingName = json['buildingName'];
//
// if (json['assetInventoryFloors'] != null) {
// assetInventoryFloors = (json['assetInventoryFloors'] as List).map((e) => AssetInventoryFloor.fromJson(e)).toList();
// }
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['buildingId'] = buildingId;
// map['buildingName'] = buildingName;
// map['assetInventoryFloors'] = assetInventoryFloors.map((e) => e.toJson()).toList();
// return map;
// }
// }
//
// class AssetInventoryFloor {
// int? floorId;
// String? floorName;
// List<AssetInventoryDepartment> assetInventoryDepartments = [];
//
// AssetInventoryFloor({
// this.floorId,
// this.floorName,
// List<AssetInventoryDepartment>? assetInventoryDepartments,
// }) {
// this.assetInventoryDepartments = assetInventoryDepartments ?? [];
// }
//
// AssetInventoryFloor.fromJson(Map<String, dynamic> json) {
// floorId = json['floorId'];
// floorName = json['floorName'];
//
// if (json['assetInventoryDepartments'] != null) {
// assetInventoryDepartments = (json['assetInventoryDepartments'] as List).map((e) => AssetInventoryDepartment.fromJson(e)).toList();
// }
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['floorId'] = floorId;
// map['floorName'] = floorName;
// map['assetInventoryDepartments'] = assetInventoryDepartments.map((e) => e.toJson()).toList();
// return map;
// }
// }
//
// class AssetInventoryDepartment {
// int? departmentId;
// String? departmentName;
// List<AssetInventoryRoom> assetInventoryRooms = [];
//
// AssetInventoryDepartment({
// this.departmentId,
// this.departmentName,
// List<AssetInventoryRoom>? assetInventoryRooms,
// }) {
// this.assetInventoryRooms = assetInventoryRooms ?? [];
// }
//
// AssetInventoryDepartment.fromJson(Map<String, dynamic> json) {
// departmentId = json['departmentId'];
// departmentName = json['departmentName'];
//
// if (json['assetInventoryRooms'] != null) {
// assetInventoryRooms = (json['assetInventoryRooms'] as List).map((e) => AssetInventoryRoom.fromJson(e)).toList();
// }
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['departmentId'] = departmentId;
// map['departmentName'] = departmentName;
// map['assetInventoryRooms'] = assetInventoryRooms.map((e) => e.toJson()).toList();
// return map;
// }
// }
//
// class AssetInventoryRoom {
// int? roomId;
// String? roomName;
//
// AssetInventoryRoom({this.roomId, this.roomName});
//
// AssetInventoryRoom.fromJson(Map<String, dynamic> json) {
// roomId = json['roomId'];
// roomName = json['roomName'];
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['roomId'] = roomId;
// map['roomName'] = roomName;
// return map;
// }
// }
class AssetInventoryAssignedEmployee {
String? assignedEngineerId;
String? assignedEngineerName;
AssetInventoryAssignedEmployee({this.assignedEngineerId, this.assignedEngineerName});
AssetInventoryAssignedEmployee.fromJson(Map<String, dynamic> json) {
assignedEngineerId = json['assignedEngineerId'];
assignedEngineerName = json['assignedEngineerName'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['assignedEngineerId'] = assignedEngineerId;
map['assignedEngineerName'] = assignedEngineerName;
return map;
}
}

@ -0,0 +1,61 @@
class TechnicalInspectionAssetBasicInfoModel {
int? id;
String? assetNumber;
String? assetType;
String? assetOrigin;
String? assetName;
String? model;
String? manufacturer;
String? site;
String? building;
String? floor;
String? department;
String? room;
TechnicalInspectionAssetBasicInfoModel({
this.id,
this.assetNumber,
this.assetType,
this.assetOrigin,
this.assetName,
this.model,
this.manufacturer,
this.site,
this.building,
this.floor,
this.department,
this.room,
});
TechnicalInspectionAssetBasicInfoModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
assetNumber = json['assetNumber'];
assetType = json['assetType'];
assetOrigin = json['assetOrigin'];
assetName = json['assetName'];
model = json['model'];
manufacturer = json['manufacturer'];
site = json['site'];
building = json['building'];
floor = json['floor'];
department = json['department'];
room = json['room'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'assetNumber': assetNumber,
'assetType': assetType,
'assetOrigin': assetOrigin,
'assetName': assetName,
'model': model,
'manufacturer': manufacturer,
'site': site,
'building': building,
'floor': floor,
'department': department,
'room': room,
};
}
}

@ -0,0 +1,215 @@
import 'dart:developer';
import 'package:test_sa/models/device/supplier.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/room_model.dart';
import 'package:test_sa/models/new_models/site.dart';
import '../../../models/device/model_definition.dart';
import '../../../models/new_models/department.dart';
class TechnicalInspectionAssetModel {
num? id;
num? tableItemId;
num? lineId;
num? assetDeliveryInternalDetailAssetId;
num? assetDeliveryInternalDetailAssetChildId;
num? costCenterId;
String? assetNumber;
String? status;
Lookup? assetOrigin;
Lookup? replacedAsset;
AssetModelDefination? modelDefinition;
Supplier? supplier;
Lookup? assetType; // Now nullable
Site? site; // Now nullable
Building? building; // Now nullable
Floor? floor; // Now nullable
Department? department; // Now nullable
Rooms? room;
String? serialNo;
String? systemId;
DateTime? installationDate;
List<TechnicalInspectionAssetModel>? childAssetList;
bool? flagphysicalInspection;
bool? flagFunctionPerformance;
bool? flagGroundingResistance;
bool? flagChassiss;
bool? flagLeadsLeakage;
bool? flagAlert;
TechnicalInspectionAssetModel({
this.id,
this.assetDeliveryInternalDetailAssetId,
this.assetDeliveryInternalDetailAssetChildId,
this.tableItemId,
this.status,
this.lineId,
this.costCenterId,
this.assetNumber,
this.assetOrigin,
this.assetType,
this.replacedAsset,
this.modelDefinition,
this.supplier,
this.site,
this.building,
this.floor,
this.department,
this.room,
this.serialNo,
this.systemId,
this.installationDate,
this.childAssetList,
this.flagphysicalInspection,
this.flagFunctionPerformance,
this.flagGroundingResistance,
this.flagChassiss,
this.flagLeadsLeakage,
this.flagAlert,
});
TechnicalInspectionAssetModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
assetDeliveryInternalDetailAssetId = json['assetDeliveryInternalDetailAssetId'];
assetDeliveryInternalDetailAssetChildId = json['assetDeliveryInternalDetailAssetChildId'];
assetNumber = json['assetNumber'];
assetOrigin = json['assetOrigin'] != null ? Lookup.fromJson(json['assetOrigin']) : null;
replacedAsset = json['replacedAsset'] != null ? Lookup.fromJson(json['replacedAsset']) : null;
modelDefinition = json['modelDefinition'] != null ? AssetModelDefination.fromJson(json['modelDefinition']) : null;
supplier = json['supplier'] != null ? Supplier.fromJson(json['supplier']) : null;
assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null;
site = json['site'] != null ? Site.fromJson(json['site']) : null;
building = json['building'] != null ? Building.fromJson(json['building']) : null;
floor = json['floor'] != null ? Floor.fromJson(json['floor']) : null;
department = json['department'] != null ? Department.fromJson(json['department']) : null;
room = json['room'] != null ? Rooms.fromJson(json['room']) : null;
serialNo = json['serialNo'];
systemId = json['systemId'];
installationDate = json['installationDate'] != null ? DateTime.tryParse(json['installationDate']) : null;
childAssetList =
json['assetDeliveryInternalDetailAssetChild'] != null ? (json['assetDeliveryInternalDetailAssetChild'] as List).map((e) => TechnicalInspectionAssetModel.fromJson(e)).toList() : [];
//Need to keep one parm from backend
// childAssetList = json['assetDeliveryExternalDeliveryLineTechnicalInspectionItemChild'] != null
// ? (json['assetDeliveryExternalDeliveryLineTechnicalInspectionItemChild'] as List).map((e) => TechnicalInspectionAssetModel.fromJson(e)).toList()
// : [];
flagphysicalInspection = json['flagphysicalInspection'];
flagFunctionPerformance = json['flagFunctionPerformance'];
flagGroundingResistance = json['flagGroundingResistance'];
flagChassiss = json['flagChassiss'];
flagLeadsLeakage = json['flagLeadsLeakage'];
flagAlert = json['flagAlert'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['id'] = id;
data['assetDeliveryInternalDetailAssetId'] = assetDeliveryInternalDetailAssetId;
data['assetDeliveryExternalDeliveryId'] = tableItemId;
data['assetDeliveryExternalDetailId'] = lineId;
data['costCenterId'] = costCenterId;
data['assetNumber'] = assetNumber;
data['assetOriginId'] = assetOrigin?.id;
data['assetTypeId'] = assetType?.id;
data['replacedAssetId'] = replacedAsset?.id;
data['modelDefinitionId'] = modelDefinition?.modelDefinitionId;
data['supplierId'] = supplier?.id;
data['siteId'] = site?.id;
data['buildingId'] = building?.id;
data['floorId'] = floor?.id;
data['departmentId'] = department?.id;
data['roomId'] = room?.id;
data['serialNo'] = serialNo;
data['systemId'] = systemId;
data['installationDate'] = installationDate?.toIso8601String();
data['assetDeliveryInternalDetailAssetChild'] = childAssetList?.map((e) => e.toChildJson()).toList();
data['flagphysicalInspection'] = flagphysicalInspection;
data['flagFunctionPerformance'] = flagFunctionPerformance;
data['flagGroundingResistance'] = flagGroundingResistance;
data['flagChassiss'] = flagChassiss;
data['flagLeadsLeakage'] = flagLeadsLeakage;
data['flagAlert'] = flagAlert;
return data;
}
Map<String, dynamic> toChildJson() {
final Map<String, dynamic> data = {};
data['id'] = id;
data['assetDeliveryInternalDetailAssetChildId'] = assetDeliveryInternalDetailAssetChildId;
data['assetNumber'] = assetNumber;
data['assetOriginId'] = assetOrigin?.id;
data['assetTypeId'] = assetType?.id;
data['replacedAssetId'] = replacedAsset?.id;
data['modelDefinitionId'] = modelDefinition?.modelDefinitionId;
data['supplierId'] = supplier?.id;
data['siteId'] = site?.id;
data['buildingId'] = building?.id;
data['floorId'] = floor?.id;
data['departmentId'] = department?.id;
data['roomId'] = room?.id;
data['serialNo'] = serialNo;
data['systemId'] = systemId;
data['installationDate'] = installationDate?.toIso8601String();
data['flagphysicalInspection'] = flagphysicalInspection;
data['flagFunctionPerformance'] = flagFunctionPerformance;
data['flagGroundingResistance'] = flagGroundingResistance;
data['flagChassiss'] = flagChassiss;
data['flagLeadsLeakage'] = flagLeadsLeakage;
data['flagAlert'] = flagAlert;
return data;
}
}
class InspectionChecklistItem {
String? title;
String? value;
String? status; // "PASS" or "FAIL"
InspectionChecklistItem({this.title, this.status, this.value});
InspectionChecklistItem.fromJson(Map<String, dynamic> json) {
title = json['title'];
value = json['value'];
status = json['status'];
}
Map<String, dynamic> toJson() {
return {
'title': title,
'value': value,
'status': status,
};
}
}
class AssetModelDefination {
int? modelDefinitionId;
String? assetName;
String? model;
String? manufacturer;
AssetModelDefination({
this.modelDefinitionId,
this.assetName,
this.model,
this.manufacturer,
});
AssetModelDefination.fromJson(Map<String, dynamic> json) {
modelDefinitionId = json['modelDefinitionId'];
assetName = json['assetName'];
model = json['model'];
manufacturer = json['manufacturer'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['modelDefinitionId'] = modelDefinitionId;
data['assetName'] = assetName;
data['model'] = model;
data['manufacturer'] = manufacturer;
return data;
}
}

@ -0,0 +1,53 @@
import 'dart:developer';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
class TechnicalInspectionFormModel {
Lookup? powerSupplyType;
num? powerReading;
num? maxCurrent;
num? voltage;
num? frequency;
List<CostCenterModel>? costCenters;
int? tableItemId;
int? lineId;
TechnicalInspectionFormModel({
this.powerSupplyType,
this.powerReading,
this.maxCurrent,
this.voltage,
this.frequency,
this.costCenters,
this.lineId,
this.tableItemId,
});
TechnicalInspectionFormModel.fromJson(Map<String, dynamic> json) {
powerSupplyType = json["powerSupplyType"] == null ? null : Lookup.fromJson(json["powerSupplyType"]);
powerReading = json['powerReading'];
maxCurrent = json['maxCurrent'];
voltage = json['voltage'];
frequency = json['frequency'];
if (json['costCenters'] != null) {
costCenters = <CostCenterModel>[];
json['costCenters'].forEach((v) {
costCenters!.add(CostCenterModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['powerSupplyTypeId'] = powerSupplyType?.id;
data['assetDeliveryExternalDeliveryId'] = tableItemId;
data['assetDeliveryExternalDetailId'] = lineId;
data['powerReading'] = powerReading;
data['maxCurrent'] = maxCurrent;
data['voltage'] = voltage;
data['frequency'] = frequency;
// data['costCenters'] = costCenters != null ? costCenters!.map((v) => v.toJson()).toList() : [];
return data;
}
}

@ -1,105 +0,0 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/delivery_inspection_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/history_log_view.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cx_module/chat/chat_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
class AssetDeliveryDetailPage extends StatefulWidget {
final int requestId;
AssetDeliveryDetailPage({Key? key, required this.requestId}) : super(key: key);
@override
_AssetDeliveryDetailPageState createState() {
return _AssetDeliveryDetailPageState();
}
}
class _AssetDeliveryDetailPageState extends State<AssetDeliveryDetailPage> {
late CMDetailProvider _requestProvider;
static const int moduleId = 1;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Provider.of<ChatProvider>(context, listen: false).reset();
getInitialData();
});
}
Future<void> getInitialData() async {
///Replace with data ...
// _requestProvider = Provider.of<CMDetailProvider>(context, listen: false);
// await _requestProvider.getWorkOrderById(id: widget.requestId);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
///Title should be change with view change
title: 'Delivery Inspection'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: DefaultTabController(
length: 2,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, top: 12.toScreenHeight),
decoration: BoxDecoration(color: context.isDark ? AppColor.neutral50 : AppColor.white10, borderRadius: BorderRadius.circular(10)),
child: TabBar(
//controller: _tabController,
padding: EdgeInsets.symmetric(vertical: 4.toScreenHeight, horizontal: 4.toScreenWidth),
labelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelStyle: AppTextStyles.bodyText,
labelStyle: AppTextStyles.bodyText,
indicatorPadding: EdgeInsets.zero,
indicatorSize: TabBarIndicatorSize.tab,
dividerColor: Colors.transparent,
indicator: BoxDecoration(color: context.isDark ? AppColor.neutral60 : AppColor.neutral110, borderRadius: BorderRadius.circular(7)),
onTap: (index) {
// setState(() {});
},
tabs: [
Tab(text: context.translation.details, height: 57.toScreenHeight),
Tab(text: context.translation.historyLogs, height: 57.toScreenHeight),
],
),
),
12.height,
TabBarView(
children: [
DeliveryInspectionFormView(),
const AssetDeliveryHistoryLogView(),
],
).expanded,
],
),
));
}
}

@ -15,6 +15,7 @@ class AssetDeliveryItemView extends StatelessWidget {
final Data? requestData;
final RequestsDetails? requestDetails;
final bool showShadow;
const AssetDeliveryItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key);
@override
@ -23,27 +24,10 @@ class AssetDeliveryItemView extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// StatusLabel(
// label: requestData!.statusName!,
// textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!),
// backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!),
// ),
// 1.width.expanded,
// Text(
// requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
// ),
// ],
// ),
8.height,
'Asset Delivery'.addTranslation.heading5(context),
infoWidget(label: 'Delivery Type'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Assets'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Sites'.addTranslation, value: '-', context: context),
(requestData?.typeTransaction ?? 'Asset Delivery').heading5(context),
infoWidget(label: 'PO Internal'.addTranslation, value: requestData?.poInternal ?? '-', context: context),
infoWidget(label: 'PO External'.addTranslation, value: requestData?.poExternal ?? '-', context: context),
// infoWidget(label: 'No of Sites'.addTranslation, value: requestData?.numberOfSites != null ? requestData?.numberOfSites.toString() : '-', context: context),
8.height,
Row(
@ -59,33 +43,21 @@ class AssetDeliveryItemView extends StatelessWidget {
),
],
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => AssetInventoryPage(sessionId: requestData!.id!, moduleId: requestData!.transactionNo!)));
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => AssetDeliveryPage(
requestId: requestData!.id!,
poInternal: requestData?.poInternal,
poExternal: requestData?.poExternal,
)));
});
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// StatusLabel(
// label: requestDetails!.status!,
// textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!),
// backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!),
// ),
// 1.width.expanded,
// Text(
// requestDetails!.date?.toServiceRequestCardFormat ?? "",
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
// ),
// ],
// ),
8.height,
'Asset Delivery'.addTranslation.heading5(context),
infoWidget(label: 'Delivery Type'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Assets'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Sites'.addTranslation, value: '-', context: context),
(requestDetails?.nameOfType ?? 'Asset Delivery').heading5(context),
infoWidget(label: 'PO Internal'.addTranslation, value: requestDetails?.poInternal ?? '-', context: context),
infoWidget(label: 'PO External'.addTranslation, value: requestDetails?.poExternal ?? '-', context: context),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
@ -100,7 +72,12 @@ class AssetDeliveryItemView extends StatelessWidget {
),
],
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => AssetDeliveryPage(requestId: requestDetails!.id!)));
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => AssetDeliveryPage(
requestId: requestDetails!.id!,
poInternal: requestDetails?.poInternal,
poExternal: requestDetails?.poExternal,
)));
});
}

@ -1,22 +1,21 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class AssetDeliveryLineCard extends StatelessWidget {
///Need to replace with Lines model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
DeliveryLineModel deliveryLineModel;
bool isViewOnly;
VoidCallback ?editPress;
VoidCallback? editPress;
bool isTechnical;
AssetDeliveryLineCard({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
required this.deliveryLineModel,
this.isTechnical = false,
this.editPress,
});
@ -30,43 +29,55 @@ class AssetDeliveryLineCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Item No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
'Item Category: ${deliveryLineModel.itemCategory ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
if (!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if (editPress != null) {
editPress!();
}
}),
],
),
Text(
'Item Description: ${deliveryDetails.assetNumber ?? '-'}',
'Item No: ${deliveryLineModel.itemNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Quantity: ${deliveryDetails.assetName ?? '-'}',
'Item Description: ${deliveryLineModel.itemDescription ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Remaining Quantity: ${deliveryDetails.assetName ?? '-'}',
'Quantity: ${deliveryLineModel.qty ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if(!isTechnical)...[
Text(
'Remaining Quantity: ${deliveryLineModel.remainingQty ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Quantity of this Delivery: ${deliveryLineModel.usingQtyInThisDelivery ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
Text(
'Quantity of this Delivery: ${deliveryDetails.assetName ?? '-'}',
'Measure Unit: ${deliveryLineModel.unitOfMeasure ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Marge Unit: ${deliveryDetails.assetName ?? '-'}',
'Unit price: ${deliveryLineModel.unitPrice ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Unit price: ${deliveryDetails.assetName ?? '-'}',
'Line Type: ${deliveryLineModel.lineType ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Total: ${deliveryDetails.assetName ?? '-'}',
'Total: ${deliveryLineModel.total ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],

@ -1,30 +1,31 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_detail_page.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_table_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/change_status_bottomsheet.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/delivery_inspection_form_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/session_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/history_log_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryPage extends StatefulWidget {
final int? requestId;
final String? poInternal;
final String? poExternal;
const AssetDeliveryPage({
Key? key,
this.requestId,
this.poInternal,
this.poExternal,
}) : super(key: key);
@override
@ -32,11 +33,28 @@ class AssetDeliveryPage extends StatefulWidget {
}
class _AssetDeliveryPageState extends State<AssetDeliveryPage> {
AssetDeliveryDataModel? dataModel;
AssetDeliveryProvider? assetDeliveryProvider;
@override
void initState() {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
WidgetsBinding.instance.addPostFrameCallback((_) {
getDetailsById();
});
super.initState();
}
Future<void> getDetailsById() async {
final futures = <Future>[
assetDeliveryProvider!.getAssetDeliveryDetailById(requestId: widget.requestId).then((value) => dataModel = value),
assetDeliveryProvider!.getAssetDeliveryTableListById(requestId: widget.requestId),
];
await Future.wait(futures);
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
@ -47,17 +65,72 @@ class _AssetDeliveryPageState extends State<AssetDeliveryPage> {
Navigator.pop(context);
},
),
body: widget.requestId == null
? const NoDataFound()
: ListView(
padding: const EdgeInsets.all(12),
children: [
requestDetailCard(context),
// const SizedBox(height: 12),
const Divider().defaultStyle(context),
assetDeliveryTableList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 0, margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12)),
body: Consumer<AssetDeliveryProvider>(
builder: (context, provider, child) {
final dataModel = provider.assetDeliveryDataModel;
if (provider.isLoading) {
return const CircularProgressIndicator(color: AppColor.primary10).center;
}
if (dataModel == null) {
return const NoDataFound().center;
}
return ListView(
padding: const EdgeInsets.all(12),
children: [
requestDetailCard(context),
const Divider().defaultStyle(context),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Asset Delivery Table",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
Row(
children: [
Container(
height: 24,
width: 24,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColor.primary10, // or AppColor.blueStatus(context)
),
alignment: Alignment.center,
child: const Icon(
Icons.add,
color: Colors.white,
size: 16,
),
),
4.width,
Text(
"Add more",
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral50,
decoration: TextDecoration.underline,
),
),
],
).onPress(() async {
await assetDeliveryProvider?.addNewDelivery(requestId: widget.requestId).then((status) async {
if (status) {
await assetDeliveryProvider?.getAssetDeliveryTableListById(requestId: widget.requestId);
}
});
}),
],
),
8.height,
assetDeliveryTableList(context: context, assetDeliveryProvider: provider),
],
).toShadowContainer(
context,
borderRadius: 20,
padding: 0,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
);
},
),
);
}
@ -67,183 +140,207 @@ class _AssetDeliveryPageState extends State<AssetDeliveryPage> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'PO No. Internal'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
widget.poInternal ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Client Name'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
dataModel?.clientName ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// mainAxisSize: MainAxisSize.min,
// children: [
// //
// StatusLabel(
// label: sessionModel.statusName,
// id: sessionModel.statusId,
// radius: 4,
// textColor: AppColor.getRequestStatusTextColorByName(context, sessionModel.statusName),
// backgroundColor: AppColor.getRequestStatusColorByName(context, sessionModel.statusName),
// // textColor: AppColor.green15,
// // backgroundColor: AppColor.greenStatus(context),
// Checkbox(
// value: dataModel!.isHMG,
// activeColor: AppColor.neutral120,
// materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
// visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
// onChanged: (value) {},
// ),
// 8.width,
// Text(
// sessionModel.createdDate!.toString().toServiceRequestCardFormat,
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
// )
// 'HMG'.addTranslation,
// style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
// ),
// ],
// ),
8.height,
//neutral120
if (dataModel?.isHMG == true) ...[
Text(
'Operation Units'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
dataModel?.operatingUnit ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
] else ...[
Text(
'Site'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
dataModel?.site?.siteName ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
8.height,
Text(
'PO No. Internal'.addTranslation,
'PO No.'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
//Need to verify this with backend ...
// widget.poInternal?? '-',
Text(
'PO8745623'.addTranslation,
dataModel?.isHMG == true
? dataModel?.poNumber != null
? dataModel!.poNumber.toString()
: '-'
: dataModel?.poNumber != null
? dataModel!.poNumber.toString()
: '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: true,
activeColor: AppColor.neutral120,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
onChanged: (value) {},
),
8.width,
Text(
'HMS'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
],
),
8.height,
Text(
'Operation Units'.addTranslation,
'Warranty Period'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'50'.addTranslation,
dataModel?.warrentyPeriod != null ? dataModel!.warrentyPeriod.toString() : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'PO No.'.addTranslation,
'Payment Term'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'PO438'.addTranslation,
dataModel?.paymentTerm != null ? dataModel!.paymentTerm!.name.toString() : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Warranty Period'.addTranslation,
'Payment Terms Amount'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'1 Year'.addTranslation,
dataModel?.paymentTermAmount != null ? dataModel!.paymentTermAmount.toString() : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Payment Terms Amount'.addTranslation,
'EDD (Estimated Delivery Date)'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'70%'.addTranslation,
dataModel?.edd != null ? dataModel!.edd!.toAssetDetailsFormat : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'EDD (Estimated Delivery Date)'.addTranslation,
'Total'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'25 December, 2025'.addTranslation,
dataModel?.total != null ? dataModel!.total.toString() : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Total'.addTranslation,
'Total Invoice'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'4930'.addTranslation,
dataModel?.totalInvoice != null ? dataModel!.totalInvoice.toString() : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
Widget assetDeliveryTableList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Asset Delivery Table",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
Container(
height: 24,
width: 24,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColor.primary10, // or AppColor.blueStatus(context)
),
alignment: Alignment.center,
child: const Icon(
Icons.add,
color: Colors.white,
size: 16,
),
).onPress(() {
//add entry into table.
}),
// AppFilledButton(
// label: '',
// maxWidth: true,
// textColor: AppColor.textColor(context),
// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
// icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
// showIcon: true,
// onPressed: (){
//
// },
// )
],
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryTableCard(
deliveryDetails: AssetInventoryModel(),
onCardTap: () {
///TODO need to display bottomsheet to change status if new...
// if(status=='NEW')
// AssetDeliveryBottomSheet.changeStatusBottomSheet(context: context);
Navigator.of(context).push(MaterialPageRoute(builder: (_) => AssetDeliveryDetailPage(requestId: 13,)));
},
onViewHistoryPress: () {},
);
},
),
],
);
Widget assetDeliveryTableList({required BuildContext context, required AssetDeliveryProvider assetDeliveryProvider}) {
List<AssetDeliveryTableModel> assetDeliveryTableList = assetDeliveryProvider.assetDeliveryTableList;
return assetDeliveryProvider.isDeliveryTableListLoading
? SizedBox(height: 200.toScreenHeight, child: const CircularProgressIndicator(color: AppColor.primary10).center)
: assetDeliveryTableList.isEmpty
? const NoDataFound().center
: ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
AssetDeliveryTableModel model = assetDeliveryTableList[itemIndex];
return AssetDeliveryTableCard(
deliveryTableModel: model,
onCardTap: () {
//status new
if (model.status?.value == 1) {
AssetDeliveryBottomSheet.changeStatusBottomSheet(
context: context,
cancelStatusTap: () async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.changeDeliveryStatusToCancel(itemId: model.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider.getAssetDeliveryTableListById(requestId: widget.requestId);
}
});
},
statusChangeTap: () async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.changeDeliveryStatus(itemId: model.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider.getAssetDeliveryTableListById(requestId: widget.requestId);
}
});
});
} else {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => DeliveryInspectionFormView(
deliveryTableModel: model,
requestModel: dataModel,
),
));
}
},
onViewHistoryTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryHistoryLogView(
tableItemId: model.id,
)));
},
);
},
);
}
}

@ -1,30 +1,28 @@
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryTableCard extends StatelessWidget {
//Need to replace with AssetTableCard.
AssetInventoryModel deliveryDetails;
VoidCallback onViewHistoryPress;
AssetDeliveryTableModel deliveryTableModel;
VoidCallback onCardTap;
VoidCallback onViewHistoryTap;
AssetDeliveryTableCard({
super.key,
required this.deliveryDetails,
required this.onViewHistoryPress,
required this.deliveryTableModel,
required this.onCardTap,
required this.onViewHistoryTap,
});
@override
Widget build(BuildContext context) {
deliveryDetails.status = 'New';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -32,35 +30,35 @@ class AssetDeliveryTableCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: deliveryDetails.status,
textColor: AppColor.getRequestStatusTextColorByName(context, deliveryDetails.status),
backgroundColor: AppColor.getRequestStatusColorByName(context, deliveryDetails.status),
label: deliveryTableModel.status?.name,
textColor: AppColor.neutral50,
backgroundColor: AppColor.orange30,
),
Row(
children: [
'history_icon'.toSvgAsset(),
6.width,
'history_icon'.toSvgAsset(height: 14, width: 14),
8.width,
Text(
'View History'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
style: AppTextStyles.bodyText.copyWith(color: AppColor.primary10),
),
],
).onPress(() {
onViewHistoryPress();
onViewHistoryTap();
}),
],
),
8.height,
Text(
'Delivery Number: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
'Delivery Number: ${deliveryTableModel.number ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Delivery Amount: ${deliveryDetails.assetNumber ?? '-'}',
'Delivery Amount: ${deliveryTableModel.deliveryAmount ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Invoice Amount: ${deliveryDetails.assetName ?? '-'}',
'Invoice Amount: ${deliveryTableModel.invoiceAmount ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Align(
@ -68,7 +66,7 @@ class AssetDeliveryTableCard extends StatelessWidget {
child: Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14),
),
],
).toShadowContainer(context, borderRadius: 20).onPress((){
).toShadowContainer(context, borderRadius: 20).onPress(() {
onCardTap();
});
}

@ -0,0 +1,126 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
class AssetDeliveryAttachmentView extends StatefulWidget {
///Need to check which parm need here.
final int? lineId;
final int? tableItemId;
final int? requestId;
final bool? isHmg;
const AssetDeliveryAttachmentView({
super.key,
this.lineId,
this.requestId,
this.tableItemId,
this.isHmg,
});
@override
State<AssetDeliveryAttachmentView> createState() => _AssetDeliveryAttachmentViewState();
}
class _AssetDeliveryAttachmentViewState extends State<AssetDeliveryAttachmentView> {
List<GenericAttachmentModel> _attachments = [];
bool isLoading = false;
late AssetDeliveryProvider assetDeliveryProvider;
@override
void initState() {
super.initState();
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
}
void getInitialData() async {
///get previoues Attachment from Apis.
isLoading = true;
setState(() {});
_attachments = await assetDeliveryProvider.getAttachments(tableItemId: widget.tableItemId);
isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'Attachments'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
children: [
AttachmentPicker(
label: context.translation.attachments,
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
// showAsGrid: true,
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
onChange: (attachment) {},
)
.toShadowContainer(
context,
borderRadius: 20,
padding: 12,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
)
.expanded,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Save'.addTranslation,
maxWidth: true,
onPressed: () async {
List<GenericAttachmentModel> attachement = [];
for (var item in _attachments) {
String fileName =
CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
attachement.add(GenericAttachmentModel(id: item.id ?? 0, name: fileName));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
Map<String,dynamic> payLoad ={
'assetDeliveryExternalDeliveryId': widget.tableItemId,
'attachments':attachement,
};
await assetDeliveryProvider.saveAttachment(payload:payLoad).then((status) async {
Navigator.pop(context);
if (status) {
///Need to verify need to stay on this page and refresh or go back..
Navigator.pop(context);
// assetDeliveryProvider.getDeliveryLinesListById(
// itemId: widget.tableItemId,
// );
}
});
}),
),
],
),
);
}
}

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
@ -19,7 +21,7 @@ class AssetDeliveryBottomSheet {
);
}
static Future changeStatusBottomSheet({required BuildContext context}) {
static Future changeStatusBottomSheet({required BuildContext context,required VoidCallback cancelStatusTap,required VoidCallback statusChangeTap}) {
return buildBottomSheetParent(
context: context,
childWidget: Column(
@ -46,12 +48,16 @@ class AssetDeliveryBottomSheet {
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: () {
Navigator.pop(context);
onPressed: () async {
cancelStatusTap();
},
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: () {}).expanded,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: () {
statusChangeTap();
}).expanded,
],
),
],

@ -1,35 +1,45 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/enum_extensions.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/lookups/request_type_lookup_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart';
class CostCenterFormView extends StatefulWidget {
final List<CostCenterModel>? costCenterList;
final ValueChanged<List<CostCenterModel>>? onListChanged;
final String? itemNo;
final String? itemDescription;
final int? lineId;
final int? tableItemId;
final int? requestId;
final bool? isHmg;
final double? cardPadding;
const CostCenterFormView({
super.key,
this.costCenterList,
this.onListChanged,
this.lineId,
this.requestId,
this.tableItemId,
this.itemNo,
this.isHmg,
this.itemDescription,
this.cardPadding,
});
@ -38,26 +48,47 @@ class CostCenterFormView extends StatefulWidget {
}
class _CostCenterFormViewState extends State<CostCenterFormView> {
late List<CostCenterModel> _list;
List<CostCenterModel> _list = [];
late AssetDeliveryProvider assetDeliveryProvider;
@override
void initState() {
super.initState();
_list = List<CostCenterModel>.from(widget.costCenterList ?? []);
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
}
void getInitialData() async {
_list = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines(
lineId: widget.lineId,
tableItemId: widget.tableItemId,
);
if (_list.isEmpty) {
_list.add(CostCenterModel(
id: 0,
));
}
if (widget.isHmg == true) {
CostCenterProvider costCenterProvider = Provider.of<CostCenterProvider>(context, listen: false);
if (costCenterProvider.items.isEmpty) {
await costCenterProvider.getData(id: widget.requestId);
}
}
setState(() {});
}
void _addNewEntry() {
setState(() {
_list.add(CostCenterModel());
_list.add(CostCenterModel(costCenter: Lookup()));
});
widget.onListChanged?.call(_list);
}
void _removeEntry(int index) {
setState(() {
_list.removeAt(index);
});
widget.onListChanged?.call(_list);
}
void _updateModel(int index, void Function(CostCenterModel model) updateList) {
@ -68,8 +99,6 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
@override
Widget build(BuildContext context) {
///Need to add check if status changes..
final isReadOnly = Provider.of<CMDetailProvider>(context, listen: false).isReadOnlyRequest;
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
@ -78,51 +107,105 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
Navigator.pop(context);
},
),
body: Column(
children: [
ListView.builder(
itemCount: _list.length + 1,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(widget.cardPadding ?? 16),
itemBuilder: (context, index) {
if (index == _list.length) {
return Visibility(
visible: !isReadOnly,
child: AppFilledButton(
label: "Add Cost Center".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: _addNewEntry,
),
);
}
return CostCenterItemCard(
model: _list[index],
index: index,
isReadOnly: isReadOnly,
onUpdate: (updateList) => _updateModel(index, updateList),
onRemove: () => _removeEntry(index),
);
},
).expanded,
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: () {}),
),
],
),
body: Consumer<AssetDeliveryProvider>(builder: (context, provider, child) {
return Column(
children: [
itemDetails(context: context, itemNo: widget.itemNo, itemDescription: widget.itemDescription),
provider.isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: ListView.builder(
itemCount: _list.length + 1,
shrinkWrap: true,
padding: EdgeInsets.all(widget.cardPadding ?? 16),
itemBuilder: (context, index) {
if (index == _list.length) {
return Visibility(
child: AppFilledButton(
label: "Add Cost Center".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: _addNewEntry,
),
);
}
return CostCenterItemCard(
model: _list[index],
index: index,
isReadOnly: false,
isHmg: widget.isHmg,
requestId: widget.requestId,
onUpdate: (updateList) => _updateModel(index, updateList),
onRemove: () => _removeEntry(index),
);
},
).expanded,
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Save'.addTranslation,
maxWidth: true,
onPressed: () async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.saveCostCenterToLineDeliveryInspection(tableItemId: widget.tableItemId, lineId: widget.lineId, list: _list).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
assetDeliveryProvider.getDeliveryLinesListById(
itemId: widget.tableItemId,
);
}
});
}),
),
],
);
}),
);
}
}
Widget itemDetails({required BuildContext context, String? itemNo, String? itemDescription}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Item No'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
itemNo ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Item Description'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
itemDescription ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
).toShadowContainer(
context,
borderRadius: 20,
padding: 12,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
);
}
class CostCenterItemCard extends StatelessWidget {
final CostCenterModel model;
final bool? isHmg;
final int index;
final int? requestId;
final bool isReadOnly;
final void Function(void Function(CostCenterModel model)) onUpdate;
final VoidCallback onRemove;
@ -130,6 +213,8 @@ class CostCenterItemCard extends StatelessWidget {
const CostCenterItemCard({
super.key,
required this.model,
this.requestId,
this.isHmg,
required this.index,
required this.isReadOnly,
required this.onUpdate,
@ -138,8 +223,6 @@ class CostCenterItemCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final requestedDate = Provider.of<CMDetailProvider>(context, listen: false).currentWorkOrder?.data?.requestedDate;
return Column(
children: [
if (!isReadOnly)
@ -160,50 +243,52 @@ class CostCenterItemCard extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
///TODO replace with exact data or type like searchable dropdown...
AppTextFormField(
labelText: 'Item No'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '232434',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
isHmg == true
? SingleItemDropDownMenu<Lookup, CostCenterProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Cost Center'.addTranslation,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
requestById: requestId,
showAsBottomSheet: true,
matchBy: DropDownMatchType.name,
initialValue: model.costCenter,
onSelect: (status) {
if (status != null) {
model.costCenter = status;
model.costCenterName = status.name;
}
},
)
: AppTextFormField(
labelText: 'Cost Center'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.costCenterName ?? '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.costCenterName = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Item Description',
labelText: 'Quantity'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: 'test decription abc',
initialValue: model.quantity != null ? model.quantity.toString() : '',
textAlign: TextAlign.center,
enable: true,
textInputType: TextInputType.number,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
LookUpAutoCompleteField(
clearAfterPick: false,
forAssetName: true,
onChanged: (value) {},
initialValue: model.costCenter?.name ?? '',
label: 'Cost Center'.addTranslation,
onPick: (value) {
model.costCenter = value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, RequestTypeLookupProvider>(
context: context,
showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
title: 'Quantity'.addTranslation,
initialValue: model.costCenter,
onSelect: (value) {
model.costCenter = value;
onChange: (value) {
if (value.isNotEmpty) {
model.quantity = double.tryParse(value);
}
},
style: Theme.of(context).textTheme.titleMedium,
),
],
)

@ -1,45 +1,40 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/cost_center_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_lines_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class DeliveryInspectionFormView extends StatefulWidget {
static const String id = "/delivery-inspection-form";
final AssetDeliveryTableModel deliveryTableModel;
final AssetDeliveryDataModel? requestModel;
DeliveryInspectionFormView({
Key? key,
required this.deliveryTableModel,
this.requestModel,
}) : super(key: key);
@override
@ -48,14 +43,39 @@ class DeliveryInspectionFormView extends StatefulWidget {
class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = true;
bool viewOnly = false;
AssetDeliveryProvider? assetDeliveryProvider;
DeliveryInspectionFormModel model = DeliveryInspectionFormModel();
bool isLoading = false;
@override
void initState() {
viewOnly = widget.deliveryTableModel.status?.value != 2;
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
setState(() {
isLoading = true;
});
final results = await Future.wait([
assetDeliveryProvider!.getAssetDeliveryInspectionData(
itemId: widget.deliveryTableModel.id,
),
assetDeliveryProvider!.getDeliveryLinesListById(
itemId: widget.deliveryTableModel.id,
),
]);
model = results[0] as DeliveryInspectionFormModel;
setState(() {
isLoading = false;
});
}
@override
void dispose() {
super.dispose();
@ -63,162 +83,189 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!viewOnly) ...[inspectionDetailsForm()] else ...[inspectionDetails()],
8.height,
const Divider().defaultStyle(context),
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
),
),
],
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'Delivery Inspection'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!viewOnly) ...[inspectionDetailsForm()] else ...[inspectionDetails()],
8.height,
Text(
'Total Time'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
model.totalTime != null ? '${model.totalTime.toString()} hours' : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
const Divider().defaultStyle(context),
Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap).expanded,
],
)
: AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap),
),
],
),
),
);
}
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryLineCard(
deliveryDetails: AssetInventoryModel(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CostCenterFormView(
costCenterList: [CostCenterModel()],
onListChanged: (updatedList) {
// requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployList = updatedList;
},
)));
},
);
},
),
],
);
return Consumer<AssetDeliveryProvider>(builder: (context, provider, child) {
List<DeliveryLineModel> linesList = provider.deliveryLinesList;
return provider.isDeliveryLineListLoading
? SizedBox.expand(child: const CircularProgressIndicator(color: AppColor.primary10).center)
: linesList.isEmpty
? const NoDataFound().center
: ListView.separated(
itemCount: linesList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
DeliveryLineModel model = linesList[itemIndex];
return AssetDeliveryLineCard(
deliveryLineModel: model,
isViewOnly: viewOnly,
editPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CostCenterFormView(
itemNo: model.itemNumber,
lineId: model.id,
isHmg: widget.requestModel?.isHMG,
tableItemId: widget.deliveryTableModel.id,
requestId: widget.requestModel?.id,
itemDescription: model.itemDescription,
)));
},
);
},
);
});
}
void calculateTotalTime() {
if (model.deliveryInspectionInspectedDateFrom == null || model.deliveryInspectionInspectedDateTo == null) {
model.totalTime = null;
return;
}
final fromDate = model.deliveryInspectionInspectedDateFrom!;
final toDate = model.deliveryInspectionInspectedDateTo!;
final hours = toDate.difference(fromDate).inSeconds / 3600.0;
model.totalTime = num.parse(hours.toStringAsFixed(3));
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
if (widget.requestModel?.isHMG == true) ...[
OracleUserAutoCompleteField(
clearAfterPick: false,
initialValue: model.deliveryInspectionInspectedBy ?? '',
label: 'Inspected by'.addTranslation,
onPick: (value) {
model.deliveryInspectionInspectedBy = value.fullName;
setState(() {});
}
},
),
// LookUpAutoCompleteField(
// clearAfterPick: false,
// forAssetName: true,
// onChanged: (value) {
// _scannedAssetModel?.newAssetNameId = null;
// _scannedAssetModel?.newAssetNameText = value;
// },
// initialValue: _scannedAssetModel?.assetName ?? "",
// label: 'Asset Name'.addTranslation,
// onPick: (value) {
// _scannedAssetModel?.newAssetNameText = null;
// _scannedAssetModel?.assetName = value.name;
// _scannedAssetModel?.newAssetNameId = value.id;
// setState(() {});
// },
// ),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
},
onChanged: (value) {},
),
8.height,
OracleUserAutoCompleteField(
clearAfterPick: false,
initialValue: model.deliveryInspectionApprovedBy ?? '',
label: 'Approved by'.addTranslation,
onChanged: (value) {},
onPick: (value) {
model.deliveryInspectionApprovedBy = value.fullName;
setState(() {});
}
},
),
},
),
] //No HMG user free text insted of dropdown ...
else ...[
AppTextFormField(
labelText: 'Inspected by'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.deliveryInspectionInspectedBy ?? '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.deliveryInspectionInspectedBy = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Approved by'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.deliveryInspectionApprovedBy ?? '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.deliveryInspectionApprovedBy = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
],
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
date: model.deliveryInspectionInspectedDateFrom,
from: DateTime(DateTime.now().year, 1, 1),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
@ -244,19 +291,23 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
model.deliveryInspectionInspectedDateFrom = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// calculateTotalTime();
///need to check if need validation or not.
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
if (model.deliveryInspectionInspectedDateFrom!.isAfter(DateTime.now())) {
"Start time is after than current time".showToast;
model.deliveryInspectionInspectedDateFrom = null;
selectedTime = null;
return;
}
setState(() {});
}
});
@ -268,8 +319,8 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
date: model.deliveryInspectionInspectedDateTo,
from: model.deliveryInspectionInspectedDateFrom,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
@ -295,19 +346,22 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
model.deliveryInspectionInspectedDateTo = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
calculateTotalTime();
///Need to check need validation or not..
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
if (model.deliveryInspectionInspectedDateTo!.isAfter(DateTime.now())) {
"End time is after than current time".showToast;
model.deliveryInspectionInspectedDateTo = null;
selectedTime = null;
return;
}
setState(() {});
}
});
@ -327,7 +381,7 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
model.deliveryInspectionInspectedBy ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
@ -337,7 +391,7 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
model.deliveryInspectionApprovedBy ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
@ -347,7 +401,7 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
),
8.height,
Text(
'19 August, 2025'.addTranslation,
model.deliveryInspectionInspectedDateFrom != null ? model.deliveryInspectionInspectedDateFrom!.toString().toServiceRequestDetailsFormat : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
@ -357,22 +411,63 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
),
8.height,
Text(
'19 August, 2025'.addTranslation,
model.deliveryInspectionInspectedDateTo != null ? model.deliveryInspectionInspectedDateTo!.toString().toServiceRequestDetailsFormat : '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
void _viewHistoryTap() async {}
void _attachmentTap() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: widget.deliveryTableModel.id,
)));
}
void _cancelTap() async {}
void _cancelTap() async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider!.changeDeliveryStatusToCancel(itemId: widget.deliveryTableModel.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider!.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
void _nextTap() {
Navigator.push(context, MaterialPageRoute(builder: (context) => TechnicalInspectionLinesListView()));
if (widget.deliveryTableModel.isContainsTechnicalInspection == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TechnicalInspectionLinesListView(
deliveryTableModel: widget.deliveryTableModel,
requestModel: widget.requestModel,
)));
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EndUserCostCenterLIstView(
deliveryTableModel: widget.deliveryTableModel,
requestModel: widget.requestModel,
)));
}
}
void _changeStatusTap() async {
_formKey.currentState!.save();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
model.assetDeliveryExternalDeliveryId = widget.deliveryTableModel.id;
await assetDeliveryProvider!.changeDeliveryStatus(requestPayload: model.toJson()).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider!.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
}

@ -0,0 +1,114 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/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/modules/asset_delivery_module/models/oracle_user_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/app_style/app_text_style.dart';
import 'package:test_sa/views/app_style/sizing.dart';
class OracleUserAutoCompleteField extends StatefulWidget {
final String initialValue;
final String label;
final bool clearAfterPick;
final Function(OracleUserModel) onPick;
final Function(String)? onChanged;
const OracleUserAutoCompleteField({Key? key, required this.initialValue, required this.label, required this.onPick, this.clearAfterPick = true, this.onChanged}) : super(key: key);
@override
_AutoCompletePartsFieldState createState() => _AutoCompletePartsFieldState();
}
class _AutoCompletePartsFieldState extends State<OracleUserAutoCompleteField> {
AssetDeliveryProvider? assetDeliveryProvider;
late TextEditingController _controller;
@override
void initState() {
_controller = TextEditingController(text: widget.initialValue);
super.initState();
}
@override
void didUpdateWidget(covariant OracleUserAutoCompleteField oldWidget) {
if (widget.initialValue != oldWidget.initialValue) {
_controller = TextEditingController(text: widget.initialValue);
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
assetDeliveryProvider ??= Provider.of<AssetDeliveryProvider>(context);
final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10));
return Container(
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
),
child: Autocomplete<OracleUserModel>(
optionsBuilder: (TextEditingValue textEditingValue) async {
if (textEditingValue.text.isEmpty) {
return const Iterable<OracleUserModel>.empty();
}
return await assetDeliveryProvider!.getOracleUserAutoCompleteDetails(query: textEditingValue.text);
},
displayStringForOption: (OracleUserModel option) => option.fullName ?? "",
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
return TextField(
controller: _controller,
focusNode: fieldFocusNode,
style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
textAlign: TextAlign.start,
decoration: InputDecoration(
border: border,
disabledBorder: border,
focusedBorder: border,
enabledBorder: border,
errorBorder: border,
contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth),
constraints: const BoxConstraints(),
suffixIconConstraints: const BoxConstraints(minWidth: 0),
filled: true,
fillColor: AppColor.fieldBgColor(context),
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60),
floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20),
labelText: widget.label,
labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)),
),
textInputAction: TextInputAction.search,
onChanged: (text) {
if (widget.onChanged != null) {
widget.onChanged!(text);
fieldTextEditingController.text = text;
}
},
onSubmitted: (String value) {
onFieldSubmitted();
},
);
},
onSelected: (OracleUserModel selection) {
if (widget.clearAfterPick) {
_controller.clear();
} else {
_controller.text = selection.fullName ?? '';
}
widget.onPick(selection);
},
),
);
}
}

@ -1,23 +1,26 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class CostCenterCard extends StatelessWidget {
///Need to replace with cost model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
class EndUserCostCenterCardView extends StatelessWidget {
CostCenterModel costModel;
VoidCallback? editPress;
bool isViewOnly;
VoidCallback ?editPress;
CostCenterCard({
EndUserCostCenterCardView({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
required this.costModel,
this.editPress,
required this.isViewOnly,
});
@override
@ -29,32 +32,30 @@ class CostCenterCard extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Item No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
Flexible(
child: Text(
'Cost Center Name: ${costModel.costCenterName ?? '-'}',
overflow: TextOverflow.ellipsis,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
8.width,
if (!isViewOnly)
'edit_icon'.toSvgAsset(height: 18, width: 18).onPress(() {
if (editPress != null) {
editPress!();
}
}),
],
),
Text(
'Asset Number: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Asset Type: ${deliveryDetails.assetName ?? '-'}',
'Accepted By: ${costModel.acceptedBy ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Replaced Asset No: ${deliveryDetails.assetName ?? '-'}',
),Text(
'Accepted By Email: ${costModel.acceptedByEmail ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Serial Number: ${deliveryDetails.assetName ?? '-'}',
),Text(
'Acceptance Date: ${costModel.acceptanceDate!=null? costModel.acceptanceDate.toString().toAssetDetailsFormat: '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],

@ -1,171 +0,0 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_child_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class EndUserAcceptanceFormView extends StatefulWidget {
EndUserAcceptanceFormView({
Key? key,
}) : super(key: key);
@override
State<EndUserAcceptanceFormView> createState() => _EndUserAcceptanceFormViewState();
}
class _EndUserAcceptanceFormViewState extends State<EndUserAcceptanceFormView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
Uint8List? newSignature;
String? endUserSignature;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'Item Details'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Status'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, RejectReasonProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Rejection Reason '.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTextFormField(
initialValue: '',
labelText: 'Description'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {},
onSaved: (value) {},
),
8.height,
ESignature(
title: 'End User Signature',
oldSignature: '',
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onChange: (signature) {
if (signature.isEmpty) return;
setState(() {
newSignature = signature;
endUserSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
onSaved: (signature) {
if (signature == null || signature.isEmpty) return;
setState(() {
newSignature = signature;
endUserSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
///Need to check which details show here...
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
}

@ -0,0 +1,116 @@
import 'package:flutter/material.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/modules/asset_delivery_module/models/end_user_asset_details_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class EndUserAssetDetailCard extends StatelessWidget {
EndUserAssetDetailsModel assetModel;
bool isViewOnly;
VoidCallback? editPress;
EndUserAssetDetailCard({
super.key,
required this.isViewOnly,
required this.assetModel,
this.editPress,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
assetModel.status != null
? StatusLabel(
label: assetModel.status?.name,
radius: 4,
textColor: getAssetStatusColor(context: context, status: assetModel.status?.name ?? '', isBackground: false),
backgroundColor: getAssetStatusColor(context: context, status: assetModel.status?.name ?? ''),
)
: const SizedBox(),
if (!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if (editPress != null) {
editPress!();
}
}),
],
),
8.height,
if (assetModel.type == 'Accessory') ...[
Text(
'Type: ${assetModel.type ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Item Number: ${assetModel.itemNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Received Quantity: ${assetModel.receivedQty ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Rejection Reason: ${assetModel.rejectionReason?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Rejected Quantity: ${assetModel.rejectedQty ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Description: ${assetModel.description ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
] else ...[
Text(
'Type: ${assetModel.type ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Item Number: ${assetModel.itemNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Asset Number: ${assetModel.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Serial No: ${assetModel.serialNo ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Replaced Asset No: ${assetModel.replacedAssetNo ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Rejection Reason: ${assetModel.rejectionReason?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Description: ${assetModel.description ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
Color getAssetStatusColor({required BuildContext context, required String status, bool? isBackground = true}) {
switch (status) {
case 'Accept':
return isBackground! ? AppColor.green70.withOpacity(0.4) : AppColor.green15;
case 'Reject':
return isBackground! ? AppColor.red30.withOpacity(0.4) : AppColor.red30;
default:
return Colors.blueGrey;
}
}
}

@ -1,26 +1,30 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/update_end_user_cost_center_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_technical_inspection_lines_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/update_end_user_cost_center_details_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class EndUserCostCenterLIstView extends StatefulWidget {
final AssetDeliveryTableModel deliveryTableModel;
final AssetDeliveryDataModel? requestModel;
EndUserCostCenterLIstView({
Key? key,
required this.deliveryTableModel,
this.requestModel,
}) : super(key: key);
@override
@ -31,12 +35,33 @@ class _EndUserCostCenterLIstViewState extends State<EndUserCostCenterLIstView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
List<CostCenterModel> costCenterList = [];
AssetDeliveryProvider? assetDeliveryProvider;
bool isLoading = false;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
isLoading = true;
if (widget.deliveryTableModel.status?.value != null && widget.deliveryTableModel.status!.value! > 4) {
viewOnly = true;
}
setState(() {});
costCenterList = (await assetDeliveryProvider?.getEndUserCostCenterList(
tableItemId: widget.deliveryTableModel.id,
)) ??
[];
isLoading = false;
setState(() {});
}
@override
void dispose() {
super.dispose();
@ -52,59 +77,45 @@ class _EndUserCostCenterLIstViewState extends State<EndUserCostCenterLIstView> {
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
child: isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
children: [
//Refactor this
SingleChildScrollView(padding: const EdgeInsets.all(16), child: linesList(context).toShadowContainer(context, borderRadius: 20, padding: 12)).expanded,
if (!viewOnly) ...[
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap),
),
),
],
),
8.height,
],
!viewOnly
? FooterActionButton.footerContainer(
context: context,
child: Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap).expanded,
],
))
: const SizedBox(),
],
),
),
);
}
//Need to refector don't use listview and singlechildview both @waseem.
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -115,17 +126,27 @@ class _EndUserCostCenterLIstViewState extends State<EndUserCostCenterLIstView> {
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
itemCount: costCenterList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return CostCenterCard(
deliveryDetails : AssetInventoryModel(),
return EndUserCostCenterCardView(
costModel: costCenterList[itemIndex],
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateEndUserCostCenterView()));
editPress: () async {
bool isRefresh = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateEndUserCostCenterDetailsView(
costCenterModel: costCenterList[itemIndex],
tableItemId: widget.deliveryTableModel.id,
isHmg: widget.requestModel?.isHMG,
)));
if (isRefresh) {
getInitialData();
}
},
);
},
@ -134,210 +155,38 @@ class _EndUserCostCenterLIstViewState extends State<EndUserCostCenterLIstView> {
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time To'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
],
);
}
Widget inspectionDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Inspected by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Approved by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time From'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time To'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
void _viewHistoryTap() async {
void _attachmentTap() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: widget.deliveryTableModel.id,
)));
}
void _cancelTap() async {
}
void _nextTap() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserCostCenterLIstView()));
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider?.changeDeliveryStatusToCancel(itemId: widget.deliveryTableModel.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider?.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
void _changeStatusTap() async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider?.changeDeliveryStatus(itemId: widget.deliveryTableModel.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider?.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
void _nextTap() async {
// Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserCostCenterLIstView()));
}
}

@ -0,0 +1,180 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/end_user_asset_details_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_rejection_reason_lookup_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_status_lookup_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class UpdateEndUserAssetDetailsView extends StatefulWidget {
EndUserAssetDetailsModel? assetDetailsModel;
String? costCenterName;
int? tableId;
UpdateEndUserAssetDetailsView({Key? key, this.assetDetailsModel, this.costCenterName, this.tableId}) : super(key: key);
@override
State<UpdateEndUserAssetDetailsView> createState() => _UpdateEndUserAssetDetailsViewState();
}
class _UpdateEndUserAssetDetailsViewState extends State<UpdateEndUserAssetDetailsView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
late AssetDeliveryProvider assetDeliveryProvider;
EndUserAssetDetailsModel model = EndUserAssetDetailsModel();
late TextEditingController quantityController;
late TextEditingController descriptionController;
@override
void initState() {
quantityController = TextEditingController();
descriptionController = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
@override
void dispose() {
super.dispose();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
if (widget.assetDetailsModel != null) {
model = EndUserAssetDetailsModel.fromJson(widget.assetDetailsModel!.toJson());
model.costCenterName = widget.costCenterName;
model.assetDeliveryExternalDeliveryId = widget.tableId;
model.status = widget.assetDetailsModel?.status;
model.rejectionReason = widget.assetDetailsModel?.rejectionReason;
}
quantityController.text = model.rejectedQty != null ? model.rejectedQty.toString() : '';
descriptionController.text = model.description ?? '';
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'Item Details'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleItemDropDownMenu<Lookup, EndUserStatusLookupProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Status'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
initialValue: model.status,
onSelect: (status) {
if (status != null) {
model.status = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, EndUserRejectionReasonLookupProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Rejection Reason '.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
initialValue: model.rejectionReason,
onSelect: (reason) {
if (reason != null) {
model.rejectionReason = reason;
setState(() {});
}
},
),
8.height,
if (model.type == 'Accessory') ...[
AppTextFormField(
labelText: 'Rejected Quantity'.addTranslation,
controller: quantityController,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onChange: (value) {
if (value.isNotEmpty) {
model.rejectedQty = model.rejectedQty = num.tryParse(value);
}
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
AppTextFormField(
controller: descriptionController,
labelText: 'Description'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
model.description = value;
},
onSaved: (value) {
model.description = value;
},
),
8.height,
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
///Need to check which details show here...
void _saveTap() async {
_formKey.currentState!.save();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.saveEndUserAssetDataData(model: model).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context, true);
}
});
}
}

@ -0,0 +1,317 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/end_user_asset_details_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_asset_detail_card.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/update_end_user_asset_details_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class UpdateEndUserCostCenterDetailsView extends StatefulWidget {
int? tableItemId;
CostCenterModel? costCenterModel;
bool? isHmg;
UpdateEndUserCostCenterDetailsView({
Key? key,
this.tableItemId,
this.costCenterModel,
this.isHmg,
}) : super(key: key);
@override
State<UpdateEndUserCostCenterDetailsView> createState() => _UpdateEndUserCostCenterDetailsViewState();
}
class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCenterDetailsView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
CostCenterModel model = CostCenterModel();
List<EndUserAssetDetailsModel> assetList = [];
late AssetDeliveryProvider assetDeliveryProvider;
Uint8List? newSignature;
String? endUserSignature;
bool isLoading = false;
late TextEditingController acceptedByController;
late TextEditingController acceptedByEmailController;
@override
void initState() {
acceptedByController = TextEditingController();
acceptedByEmailController = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
if (widget.costCenterModel != null) {
model = CostCenterModel.fromJson(widget.costCenterModel!.toEndUserAcceptanceFormJson());
_fillControllers();
}
setState(() {
isLoading = true;
});
assetList = await assetDeliveryProvider.getEndUserAssetList(tableItemId: widget.tableItemId, costCenterName: widget.costCenterModel?.costCenterName);
setState(() {
isLoading = false;
});
}
void _fillControllers() {
acceptedByController.text = model.acceptedBy ?? '';
acceptedByEmailController.text = model.acceptedByEmail ?? '';
}
@override
void dispose() {
acceptedByController.dispose();
acceptedByEmailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'End-User Acceptance'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
///Need to implement later as discuss with Ahmed.
// Text(
// "Acceptance Form",
// style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
// ),
// 6.height,
// Row(
// children: [
// 'warning_icon'.toSvgAsset(height: 16, width: 16),
// 6.width,
// Text(
// 'Review the acceptance form'.addTranslation,
// style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
// ),
// 6.width,
// 'web_link_icon'.toSvgAsset(height: 20, width: 20),
// ],
// ),
16.height,
Text(
"Items",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
endUserAssetList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
Widget endUserAssetList(BuildContext context) {
return isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: ListView.separated(
itemCount: assetList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
EndUserAssetDetailsModel model = assetList[itemIndex];
return EndUserAssetDetailCard(
assetModel: model,
isViewOnly: viewOnly,
editPress: () async {
bool isRefresh = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateEndUserAssetDetailsView(
assetDetailsModel: model,
costCenterName: widget.costCenterModel?.costCenterName,
tableId: widget.tableItemId,
)));
if (isRefresh) {
getInitialData();
}
},
);
},
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
ADatePicker(
label: 'Accepted Date'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
date: model.acceptanceDate,
from: DateTime(DateTime.now().year, 1, 1),
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
model.acceptanceDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
setState(() {});
}
});
},
),
8.height,
if (widget.isHmg == true) ...[
OracleUserAutoCompleteField(
clearAfterPick: false,
initialValue: model.acceptedBy ?? '',
label: 'Accepted By'.addTranslation,
onPick: (value) {
model.acceptedBy = value.fullName;
model.acceptedByEmail = value.employeeEmail;
acceptedByEmailController.text = value.employeeEmail ?? '';
setState(() {});
},
onChanged: (value) {},
),
8.height,
AppTextFormField(
labelText: 'Accepted By Email'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByEmailController,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
] else ...[
AppTextFormField(
labelText: 'Accepted By'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByController,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.acceptedBy = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Accepted By Email'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByEmailController,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.acceptedByEmail = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
],
8.height,
ESignature(
title: 'End User Signature',
oldSignature: model.acceptedBySignature,
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onChange: (signature) {
log('onChange called.');
updateSignature(signature: signature);
},
onSaved: (signature) {
log('onSaved called.');
updateSignature(signature: signature);
},
)
],
);
}
void updateSignature({Uint8List? signature}) {
if (signature == null || signature.isEmpty) {
model.acceptedBySignature = '';
return;
}
setState(() {
newSignature = signature;
model.acceptedBySignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
}
void _saveTap() async {
_formKey.currentState!.save();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
model.assetDeliveryExternalDetailId = widget.tableItemId;
await assetDeliveryProvider.saveEndUserFormData(model: model).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context, true);
}
});
}
}

@ -1,220 +0,0 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_acceptance_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class UpdateEndUserCostCenterView extends StatefulWidget {
UpdateEndUserCostCenterView({
Key? key,
}) : super(key: key);
@override
State<UpdateEndUserCostCenterView> createState() => _UpdateEndUserCostCenterViewState();
}
class _UpdateEndUserCostCenterViewState extends State<UpdateEndUserCostCenterView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'End-User Acceptance'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
Text(
"Acceptance Form",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
6.height,
Row(
children: [
'warning_icon'.toSvgAsset(height: 16, width: 16),
6.width,
Text(
'Review the acceptance form'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
6.width,
'web_link_icon'.toSvgAsset(height: 20, width: 20),
],
),
16.height,
assetList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap)),
],
),
),
);
}
Widget assetList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Asset",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionAssetCard(
assetModel: Asset(),
isViewOnly: viewOnly,
ischild: true,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserAcceptanceFormView()));
},
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
ADatePicker(
label: 'Accepted Date'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
],
);
}
void _viewHistoryTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
void _cancelTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
void _nextTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
void _changeStatusTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
}

@ -1,102 +1,114 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/models/history_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryHistoryLogView extends StatelessWidget {
const AssetDeliveryHistoryLogView({Key? key}) : super(key: key);
class AssetDeliveryHistoryLogView extends StatefulWidget {
final int? tableItemId;
const AssetDeliveryHistoryLogView({Key? key,this.tableItemId}) : super(key: key);
@override
State<AssetDeliveryHistoryLogView> createState() => _AssetDeliveryHistoryLogViewState();
}
class _AssetDeliveryHistoryLogViewState extends State<AssetDeliveryHistoryLogView> {
List<AssetDeliveryHistoryModel> history = [];
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
history = await Provider.of<AssetDeliveryProvider>(context, listen: false).getHistory(tableItemId: widget.tableItemId);
}
@override
Widget build(BuildContext context) {
///Replace with provider and data..
return Consumer<CMDetailProvider>(builder: (context, requestProvider, _) {
return requestProvider.isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: (requestProvider.currentWorkOrder == null || (requestProvider.currentWorkOrder?.data?.workOrderHistory.isEmpty ?? true)
? const NoDataFound()
: Stack(
children: [
Padding(
padding: EdgeInsets.only(left: 122.toScreenWidth),
child: const VerticalDivider(
color: AppColor.white40,
thickness: 2,
width: 20,
indent: 10,
endIndent: 10,
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'History Log'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: Consumer<AssetDeliveryProvider>(builder: (context, provider, _) {
return provider.isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Stack(
children: [
Padding(
padding: EdgeInsets.only(left: 122.toScreenWidth),
child: const VerticalDivider(
color: AppColor.white40,
thickness: 2,
width: 20,
indent: 10,
endIndent: 10,
),
),
),
SafeArea(
child: Builder(builder: (cxt) {
List<Widget> items = [];
String lastStatus = "";
DateTime? nextDate;
var workOrderHistory = requestProvider.currentWorkOrder!.data!.workOrderHistory;
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
if (isNurse) {
workOrderHistory.removeWhere((element) => element.step?.id == 5617);
}
for (int i = 0; i < workOrderHistory.length; i++) {
var object = workOrderHistory[i];
String currentStatus = object.workorderStatus!.name!;
if (lastStatus.isEmpty) {
lastStatus = currentStatus;
}
if (lastStatus == currentStatus) {
if (i + 1 < workOrderHistory.length) {
nextDate = workOrderHistory[i + 1].date;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.date!, nextDate!);
object.timeDifference = timeDifference;
} else {
object.timeDifference = ''; // Empty string for the last action
SafeArea(
child: Builder(builder: (cxt) {
List<Widget> items = [];
String lastStatus = "";
DateTime? nextDate;
for (int i = 0; i < history.length; i++) {
var object = history[i];
String currentStatus = object.status!.name!;
if (lastStatus.isEmpty) {
lastStatus = currentStatus;
}
items.add(historyLogCard(cxt, object));
} else {
items.add(statusCard(cxt, lastStatus));
lastStatus = currentStatus;
if (i + 1 < workOrderHistory.length) {
nextDate = workOrderHistory[i + 1].date;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.date!, nextDate!);
object.timeDifference = timeDifference;
if (lastStatus == currentStatus) {
if (i + 1 < history.length) {
nextDate = history[i + 1].createdDate;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.createdDate!, nextDate!);
object.timeDifference = timeDifference;
} else {
object.timeDifference = ''; // Empty string for the last action
}
items.add(historyLogCard(cxt, object));
} else {
object.timeDifference = ''; // Empty string for the last action
items.add(statusCard(cxt, lastStatus));
lastStatus = currentStatus;
if (i + 1 < history.length) {
nextDate = history[i + 1].createdDate;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.createdDate!, nextDate!);
object.timeDifference = timeDifference;
} else {
object.timeDifference = ''; // Empty string for the last action
}
items.add(historyLogCard(cxt, object));
}
items.add(historyLogCard(cxt, object));
}
}
items.add(statusCard(cxt, lastStatus));
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(children: items),
);
}),
),
],
));
});
}
Widget historyLogCard(BuildContext context, WorkOrderHistory object) {
String title = object.step!.name!;
items.add(statusCard(cxt, lastStatus));
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(children: items),
);
}),
),
],
);
}),
);}
if (object.step!.value == 18 || object.step!.value == 27 || object.step!.value == 28) {
title = object.activityStatus?.name ?? "";
}
Widget historyLogCard(BuildContext context, AssetDeliveryHistoryModel object) {
String title = object.status!.name!;
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
@ -105,40 +117,18 @@ class AssetDeliveryHistoryLogView extends StatelessWidget {
Align(
alignment: Alignment.centerLeft,
child: Text(
object.date.toString().toServiceRequestCardFormat,
object.createdDate.toString().toServiceRequestCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
).expanded,
Expanded(
flex: 2,
//....
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (object.assetVerificationType?.value == 4 && object.photoVerfication != null) ...[
Padding(
padding: EdgeInsets.symmetric(vertical: 12.toScreenWidth),
child: InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!, height: 143.toScreenHeight)),
).onPress(() async {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!)).center,
const ABackButton(),
],
),
),
),
),
);
}),
],
title.bodyText(context).custom(color: AppColor.textColor(context)),
object.timeDifference.isNotEmpty ? object.timeDifference.tinyFont(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120) : const SizedBox(),
// object.timeDifference.isNotEmpty ? object.timeDifference?.tinyFont(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120) : const SizedBox(),
],
),
),
@ -153,15 +143,15 @@ class AssetDeliveryHistoryLogView extends StatelessWidget {
radius: 4,
label: statusText(status.toLowerCase()),
labelInCenter: true,
textColor: AppColor.getHistoryLogStatusTextColorByName(status),
backgroundColor: AppColor.getHistoryLogStatusColorByName(status),
textColor: AppColor.neutral50,
backgroundColor: AppColor.orange30,
),
).paddingOnly(bottom: 16, start: 40);
}
// Need to check status text we have
String statusText(String status) {
if (status == "new" || status == "open") {
return "Open Request".addTranslation;
return "New".addTranslation;
} else if (status == "in progress") {
return "Status update to In Progress".addTranslation;
} else if (status == "closed") {
@ -176,12 +166,3 @@ class AssetDeliveryHistoryLogView extends StatelessWidget {
return status;
}
}
class HistoryLogModel {
String message;
DateTime date;
String? status;
Color? statusColor;
HistoryLogModel({required this.message, required this.date, this.status, this.statusColor});
}

@ -0,0 +1,18 @@
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
class AssetDeliveryUtils{
///This is static list for now if change in future backend provide Api as discuss with backend team
static List<InspectionChecklistItem> inspectionChecklist = [
InspectionChecklistItem(title: 'Physical Inspection As Per Manufacturer Instructions', value: 'flagphysicalInspection'),
InspectionChecklistItem(title: 'Functional Performance As Per Results Of Manufacturer Recommended Check List', value: 'flagFunctionPerformance'),
InspectionChecklistItem(title: 'Grounding Resistance: Ω', value: 'flagGroundingResistance'),
InspectionChecklistItem(title: 'Chassis Leakage Current: µA', value: 'flagChassiss'),
InspectionChecklistItem(title: 'Leads Leakage Current: µA', value: 'flagLeadsLeakage'),
InspectionChecklistItem(title: 'This Device Is Not Subject To Any Alert Or Recall Until The Date Of Preparation Of This Inspection Form', value: 'flagAlert'),
];
}

@ -0,0 +1,194 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/devices_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.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/device/model_definition.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inpection_asset_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/custom_app_bar.dart';
import 'package:test_sa/views/widgets/equipment/asset_item_listview.dart';
import 'package:test_sa/views/widgets/horizontal_list_widget.dart';
import 'package:test_sa/views/widgets/loaders/lazy_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class TechnicalInspectionSearchAssetView extends StatefulWidget {
/// add on route
static const String id = "search_asset_view";
final int? lineId;
const TechnicalInspectionSearchAssetView({
Key? key,
this.lineId,
}) : super(key: key);
@override
State<TechnicalInspectionSearchAssetView> createState() => _TechnicalInspectionSearchAssetViewState();
}
class _TechnicalInspectionSearchAssetViewState extends State<TechnicalInspectionSearchAssetView> {
int _selectedIndex = 0;
DeviceSearch? search;
late TextEditingController _searchController;
late AssetProvider _deviceProvider;
//check for this list if not need remove
final List<TechnicalInspectionAssetBasicInfoModel> _searchableList = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool _isFirst = true;
@override
void initState() {
_searchController = TextEditingController();
super.initState();
}
@override
void dispose() {
_searchController.dispose();
_deviceProvider.searchReset();
super.dispose();
}
@override
Widget build(BuildContext context) {
List<String> searchBy = [
context.translation.assetName,
context.translation.assetNumber,
'model'.addTranslation,
'manufacturer'.addTranslation,
// 'assetType'.addTranslation,
// 'assetOrigin'.addTranslation,
];
_deviceProvider = Provider.of<AssetProvider>(context, listen: false);
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: CustomAppBar(
title: context.translation.searchAsset,
),
body: Column(
children: [
HorizontalListWidget(
list: searchBy,
callBackFunction: (index) {
setState(() {
_selectedIndex = index;
});
},
).paddingOnly(top: 16, bottom: 0),
Form(
key: _formKey,
child: AppTextFormField(
controller: _searchController,
textInputAction: TextInputAction.search,
labelText: "${context.translation.searchBy} ${searchBy[_selectedIndex]}",
onAction: _search,
onChange: (text) {
_searchController.text = text;
_searchController.selection = TextSelection.fromPosition(TextPosition(offset: _searchController.text.length));
setState(() {});
},
onSaved: (value) {
setState(() {
search = DeviceSearch();
});
_setValue(value);
},
suffixIcon: IconButton(
icon: const Icon(Icons.search),
splashColor: Colors.transparent,
onPressed: _searchController.text.isNotEmpty ? _search : null,
color: AppColor.neutral20,
).paddingOnly(end: 0),
).paddingOnly(top: 16, start: 16, end: 16, bottom: 8)),
Expanded(
child: _searchableList.isEmpty
? _isFirst
? const SizedBox()
: NoDataFound(message: context.translation.noDeviceFound)
: LazyLoading(
nextPage: _deviceProvider.nextPage,
onLazyLoad: () async {
if (_searchController.text.isNotEmpty) {
await _deviceProvider.getAssetsForAssetDelivery(search: search, lineId: widget.lineId, isSearchBy: true);
setState(() {
_searchableList.clear();
_searchableList.addAll(_deviceProvider.technicalInspectionAsset);
});
}
},
child: ListView.separated(
itemCount: _searchableList.length,
separatorBuilder: (listContext, itemIndex) => 8.height,
padding: const EdgeInsets.all(16),
itemBuilder: (listContext, itemIndex) {
return AssetItemListView(
device: Asset(
id: _searchableList[itemIndex].id,
assetNumber: _searchableList[itemIndex].assetNumber,
assetSerialNo: _searchableList[itemIndex].assetNumber,
modelDefinition: ModelDefinition(assetName: _searchableList[itemIndex].assetName, modelName: _searchableList[itemIndex].model),
),
onPressed: (device) {
Navigator.of(context).pop(device);
},
);
},
),
),
)
],
));
}
void _search({bool loadMore = false}) async {
FocusScope.of(context).unfocus();
_formKey.currentState?.save();
_searchableList.clear();
_deviceProvider.technicalInspectionAsset.clear();
setState(() {});
_deviceProvider.searchReset();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await _deviceProvider.getAssetsForAssetDelivery(
search: search,
lineId: widget.lineId,
isSearchBy: true,
);
setState(() {
_searchableList.clear();
_searchableList.addAll(_deviceProvider.technicalInspectionAsset);
_isFirst = false;
});
Navigator.pop(context);
}
_setValue(String? value) {
search ??= DeviceSearch();
switch (_selectedIndex) {
case 0:
search!.assetName = value;
break;
case 1:
search!.assetNo = value;
break;
case 2:
search!.model = value;
break;
case 3:
search!.manufacturer = value;
break;
}
}
}

@ -0,0 +1,137 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/asset_delivery_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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/default_app_bar.dart';
class InspectionChecklistBottomSheet extends StatefulWidget {
final List<InspectionChecklistItem>? initialValues;
const InspectionChecklistBottomSheet({super.key, this.initialValues});
@override
State<InspectionChecklistBottomSheet> createState() =>
_InspectionChecklistBottomSheetState();
}
class _InspectionChecklistBottomSheetState
extends State<InspectionChecklistBottomSheet> {
late List<InspectionChecklistItem> checklist;
@override
void initState() {
super.initState();
/// Create local copy (no shared mutation)
checklist = AssetDeliveryUtils.inspectionChecklist
.map((e) => InspectionChecklistItem(title: e.title))
.toList();
/// Apply initial values only if provided
if (widget.initialValues != null && widget.initialValues!.isNotEmpty) {
for (final item in checklist) {
final matched = widget.initialValues!.firstWhere(
(e) => e.title == item.title,
orElse: () => InspectionChecklistItem(),
);
item.status = matched.status; // null-safe
}
}
}
void updateStatus(int index, String value) {
setState(() {
checklist[index].status = value;
});
}
List<InspectionChecklistItem> get selectedValues =>
checklist.where((e) => e.status != null).toList();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.white10,
appBar: DefaultAppBar(
title: 'Asset Check List'.addTranslation,
showBackButton: false,
titleStyle: AppTextStyles.heading3.copyWith(
fontWeight: FontWeight.w500,
color: context.isDark
? AppColor.neutral30
: AppColor.neutral50,
),
),
body: Column(
children: [
12.height,
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: checklist.length,
padding: const EdgeInsets.symmetric(horizontal: 12),
itemBuilder: (context, index) {
final item = checklist[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.title ?? '',
style: AppTextStyles.heading6.copyWith(
color: context.isDark
? AppColor.neutral30
: AppColor.black10,
),
),
Row(
children: [
Expanded(
child: RadioListTile<String>(
title: const Text('Pass'),
value: 'PASS',
groupValue: item.status,
onChanged: (v) =>
updateStatus(index, v!),
),
),
Expanded(
child: RadioListTile<String>(
title: const Text('Fail'),
value: 'FAIL',
groupValue: item.status,
onChanged: (v) =>
updateStatus(index, v!),
),
),
],
),
],
);
},
).expanded,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Save'.addTranslation,
maxWidth: true,
onPressed: () {
Navigator.pop(context, selectedValues);
},
),
),
],
),
);
}
}

@ -1,21 +1,16 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class TechnicalInspectionAssetCard extends StatelessWidget {
Asset assetModel;
///if include in model skip this
TechnicalInspectionAssetModel assetModel;
bool isViewOnly;
bool ischild;
VoidCallback? editPress;
@ -33,16 +28,15 @@ class TechnicalInspectionAssetCard extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
///Need to give specific colors
if (!ischild) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: 'Pass',
label: getAssetStatus(),
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, 1),
backgroundColor: AppColor.getPriorityStatusColor(context, 1),
textColor: getAssetStatusColor(context: context, status: getAssetStatus(), isBackground: false),
backgroundColor: getAssetStatusColor(context: context, status: getAssetStatus()),
),
if (!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
@ -70,40 +64,67 @@ class TechnicalInspectionAssetCard extends StatelessWidget {
}),
],
),
2.height,
],
Text(
'Asset Name: ${assetModel.modelDefinition?.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Asset Number: ${assetModel.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Model: ${assetModel.modelDefinition ?? '-'}',
'Serial Number: ${assetModel.serialNo ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Serial Number: ${assetModel.assetSerialNo ?? '-'}',
'System ID: ${assetModel.systemId ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'System ID: ${assetModel.systemID ?? '-'}',
'Medical Department: ${assetModel.department?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Installation Date: ${assetModel.installationDate ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Asset Type: ${assetModel.assetType?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Medical Department: ${assetModel.department ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Installation Date: ${assetModel.deliveryInspectionDate ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Asset Type: ${assetModel.assetType ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
Color getAssetStatusColor({required BuildContext context, required String status, bool? isBackground = true}) {
switch (status) {
case 'PASS':
return isBackground! ? AppColor.green70.withOpacity(0.4) : AppColor.green15;
case 'FAIL':
return isBackground! ? AppColor.red30.withOpacity(0.4) : AppColor.red30;
default:
return Colors.white10;
}
}
String getAssetStatus() {
final flags = [
assetModel.flagphysicalInspection,
assetModel.flagFunctionPerformance,
assetModel.flagGroundingResistance,
assetModel.flagChassiss,
assetModel.flagLeadsLeakage,
assetModel.flagAlert,
];
if (flags.any((f) => f == false)) {
return 'FAIL';
}
if (flags.every((f) => f == true)) {
return 'PASS';
}
return 'FAIL';
}
}

@ -1,25 +1,26 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class TechnicalInspectionCostCard extends StatelessWidget {
///Need to replace with Cost model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
CostCenterModel costModel;
VoidCallback? editPress;
bool isViewOnly;
VoidCallback ?editPress;
TechnicalInspectionCostCard({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
required this.costModel,
this.editPress,
required this.isViewOnly,
});
@override
@ -31,44 +32,24 @@ class TechnicalInspectionCostCard extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Item No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
Flexible(
child: Text(
'Cost Center Name: ${costModel.costCenterName ?? '-'}',
overflow: TextOverflow.ellipsis,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
8.width,
if (!isViewOnly)
'edit_icon'.toSvgAsset(height: 18, width: 18).onPress(() {
if (editPress != null) {
editPress!();
}
}),
],
),
Text(
'Cost Center: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Power Supply Type: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Cost Center: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Power Reading: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Max Current: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Voltage: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Frequency: ${deliveryDetails.assetName ?? '-'}',
'Quantity: ${costModel.quantity ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],

@ -1,25 +1,38 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_technical_inspection_lines_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class TechnicalInspectionLinesListView extends StatefulWidget {
final AssetDeliveryTableModel deliveryTableModel;
final AssetDeliveryDataModel? requestModel;
TechnicalInspectionLinesListView({
Key? key,
required this.deliveryTableModel,
this.requestModel,
}) : super(key: key);
@override
@ -29,13 +42,33 @@ class TechnicalInspectionLinesListView extends StatefulWidget {
class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLinesListView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = true;
bool viewOnly = false;
bool isLoading = false;
AssetDeliveryProvider? assetDeliveryProvider;
List<DeliveryLineModel> technicalInspectionLinesList = [];
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
viewOnly = widget.deliveryTableModel.status?.value != 3;
isLoading = true;
setState(() {});
technicalInspectionLinesList = await assetDeliveryProvider!.getTechnicalInspectionLinesListById(
//TODO uncommit this after testing @waseem
itemId: widget.deliveryTableModel.id,
// itemId: 2,
);
isLoading = false;
setState(() {});
}
@override
void dispose() {
super.dispose();
@ -53,20 +86,13 @@ class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLi
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
Expanded(
child: linesList(context).toShadowContainer(context, borderRadius: 20, padding: 12),
),
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap),
),
8.height,
],
@ -85,16 +111,10 @@ class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLi
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
),
: AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap),
),
],
),
@ -103,180 +123,51 @@ class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLi
}
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryLineCard(
deliveryDetails: AssetInventoryModel(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateTechnicalInspectionLinesView()));
},
);
},
),
],
);
}
if (isLoading) {
return SizedBox.expand(
child: const CircularProgressIndicator(color: AppColor.primary10).center,
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time To'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
if (technicalInspectionLinesList.isEmpty) {
return const NoDataFound().center;
}
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: technicalInspectionLinesList.length + 1, // +1 for the header
separatorBuilder: (_, __) => 8.height,
itemBuilder: (context, index) {
if (index == 0) {
return Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
);
}
final DeliveryLineModel model = technicalInspectionLinesList[index - 1];
return AssetDeliveryLineCard(
deliveryLineModel: model,
isViewOnly: viewOnly,
isTechnical: true,
editPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateTechnicalInspectionLinesView(
requestModel: widget.requestModel,
deliveryTableModel: widget.deliveryTableModel,
deliveryLineModel: model,
),
),
);
},
),
],
);
);
},
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
//May be need to show data.
Widget inspectionDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -324,13 +215,44 @@ class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLi
);
}
void _viewHistoryTap() async {}
void _changeStatusTap() async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider?.changeDeliveryStatus(itemId: widget.deliveryTableModel.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider?.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
void _attachmentTap() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: widget.deliveryTableModel.id,
)));
}
void _cancelTap() async {}
void _cancelTap() async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider?.changeDeliveryStatusToCancel(itemId: widget.deliveryTableModel.id).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
await assetDeliveryProvider?.getAssetDeliveryTableListById(requestId: widget.requestModel?.id);
}
});
}
void _nextTap() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserCostCenterLIstView()));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EndUserCostCenterLIstView(
requestModel: widget.requestModel,
deliveryTableModel: widget.deliveryTableModel,
)));
}
void _changeStatusTap() async {}
}

@ -1,19 +1,28 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_parent_asset_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class TechnicalInspectionParentAssetListView extends StatefulWidget {
final int? costCenterId;
final int? tableItemId;
final int? lineId;
TechnicalInspectionParentAssetListView({
Key? key,
this.costCenterId,
this.tableItemId,
this.lineId,
}) : super(key: key);
@override
@ -24,12 +33,35 @@ class _TechnicalInspectionParentAssetListViewState extends State<TechnicalInspec
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
AssetDeliveryProvider? assetDeliveryProvider;
List<TechnicalInspectionAssetModel> assetList = [];
bool isLoading = false;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
void getInitialData() async {
setState(() {
isLoading = true;
});
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
//TODO replace static id's after testing...
assetList = await assetDeliveryProvider!.getParentAssetList(
costCenterId: widget.costCenterId,
tableItemId: widget.tableItemId,
lineId: widget.lineId,
);
setState(() {
isLoading = false;
});
}
@override
void dispose() {
super.dispose();
@ -43,45 +75,59 @@ class _TechnicalInspectionParentAssetListViewState extends State<TechnicalInspec
title: 'Technical Inspection'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
body:Form(
key: _formKey,
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: parentAssetList(context).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
child: parentAssetList(context), // parentAssetList already returns a ListView
),
);
}
Widget parentAssetList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Parents",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionAssetCard(
assetModel: Asset(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateParentAssetView()));
},
if (isLoading) {
return SizedBox.expand(
child: const CircularProgressIndicator(color: AppColor.primary10).center,
);
}
if (assetList.isEmpty) {
return const NoDataFound().center;
}
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: assetList.length + 1, // +1 for the "Parents" header
separatorBuilder: (_, __) => 8.height,
itemBuilder: (context, index) {
if (index == 0) {
return Text(
"Parents",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
);
}
final asset = assetList[index - 1];
return TechnicalInspectionAssetCard(
assetModel: asset,
isViewOnly: viewOnly,
editPress: () async {
bool isRefreshed = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateParentAssetView(
assetModel: asset,
lineId: widget.lineId,
tableItemId: widget.tableItemId,
costCenterItemId: widget.costCenterId,
),
),
);
if (isRefreshed) {
getInitialData();
}
},
),
],
);
},
);
}
}

@ -1,46 +1,42 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/asset_delivery_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/search_asset_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/status_checklist_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_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/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../models/new_models/department.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
///convert this to stateless no state needed when impleminting api's
//TODO need to refactor this screen when done ...
class UpdateChildAssetView extends StatefulWidget {
///Need to pass model here...
final TechnicalInspectionAssetModel assetModel;
final int? lineId;
final int index;
UpdateChildAssetView({
Key? key,
required this.assetModel,
required this.index,
this.lineId,
}) : super(key: key);
@override
@ -50,15 +46,48 @@ class UpdateChildAssetView extends StatefulWidget {
class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = false;
List<InspectionChecklistItem> checkList = [];
late SiteProvider siteProvider;
late AssetDeliveryProvider assetDeliveryProvider;
late TextEditingController assetNumberCtrl;
late TextEditingController serialNoCtrl;
late TextEditingController systemIdCtrl;
@override
void initState() {
siteProvider = Provider.of<SiteProvider>(context, listen: false);
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
assetNumberCtrl = TextEditingController();
serialNoCtrl = TextEditingController();
systemIdCtrl = TextEditingController();
WidgetsBinding.instance.addPostFrameCallback((_) {
populateForm();
});
super.initState();
}
void populateForm() async {
assetDeliveryProvider.isChildAssetDataLoading = true;
assetDeliveryProvider.setChildModel(widget.assetModel);
if (widget.assetModel.site != null) {
await assetDeliveryProvider.getSiteData(siteId: widget.assetModel.site?.id, model: assetDeliveryProvider.childFormModel);
}
populateTextFields(model: assetDeliveryProvider.childFormModel);
assetDeliveryProvider.isChildAssetDataLoading = false;
}
void populateTextFields({required TechnicalInspectionAssetModel model}) {
assetNumberCtrl.text = model.assetNumber ?? '';
serialNoCtrl.text = model.serialNo ?? '';
systemIdCtrl.text = model.systemId ?? '';
setState(() {});
}
@override
void dispose() {
assetNumberCtrl.dispose();
serialNoCtrl.dispose();
systemIdCtrl.dispose();
super.dispose();
}
@ -72,74 +101,328 @@ class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Asset Number'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTextFormField(
labelText: 'Model'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'System ID'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
child: Consumer<AssetDeliveryProvider>(builder: (context, provider, child) {
return provider.isChildAssetDataLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
inspectionDetailsForm(
lineId: widget.lineId,
provider: provider,
),
8.height,
const Divider().defaultStyle(context),
8.height,
testLines(
context: context,
)
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
);
}),
),
);
}
Widget testLines({required BuildContext context}) {
return Row(
children: [
Text(
"Test List",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.width,
'web_link_icon'.toSvgAsset().onPress(() {
openInspectionChecklist(context);
}),
],
);
}
/// Need to make reuseable as used in parent and child both.
Widget inspectionDetailsForm({
int? lineId,
required AssetDeliveryProvider provider,
}) {
TechnicalInspectionAssetModel model = provider.childFormModel;
return Column(
children: [
AppTextFormField(
labelText: 'Asset Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: assetNumberCtrl,
initialValue: model.assetNumber,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
).onPress(() async {
var data = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TechnicalInspectionSearchAssetView(
lineId: lineId,
)));
if (data != null) {
TechnicalInspectionAssetModel? assetModel = await provider.getAssetDetails(assetId: data?.id);
if (assetModel != null) {
provider.setChildModel(assetModel);
if (assetModel.site != null) {
await provider.getSiteData(siteId: assetModel.site?.id, model: provider.childFormModel);
}
provider.setParentModel(assetModel);
log('child list length ${assetModel.childAssetList?.length}');
populateTextFields(model: provider.childFormModel);
}
}
}),
8.height,
AppTextFormField(
labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: serialNoCtrl,
initialValue: model.serialNo ?? '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onSaved: (value) {
model.serialNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'System ID'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: systemIdCtrl,
initialValue: model.systemId ?? '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onSaved: (value) {
model.systemId = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: 'Site',
initialValue: model.site,
loading: provider.isSiteLoading,
showAsBottomSheet: true,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
// enabled: false,
onSelect: (value) {
if (value == null) {
return;
}
model.site = value;
model.building = null;
model.floor = null;
model.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
context: context,
title: 'Building',
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
loading: provider.isSiteLoading,
showShadow: false,
initialValue: model.building,
enabled: model.site?.buildings?.isNotEmpty ?? false,
staticData: model.site?.buildings ?? [],
onSelect: (value) {
if (value == null) {
return;
}
model.building = value;
model.floor = null;
model.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
context: context,
showAsBottomSheet: true,
backgroundColor: AppColor.fieldBgColor(context),
loading: provider.isSiteLoading,
showShadow: false,
title: 'Floor',
initialValue: model.floor,
enabled: model.building?.floors?.isNotEmpty ?? false,
staticData: model.building?.floors ?? [],
onSelect: (value) {
if (value == null) {
return;
}
model.floor = value;
model.department = null;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
context: context,
title: 'Department',
backgroundColor: AppColor.fieldBgColor(context),
loading: provider.isSiteLoading,
showAsBottomSheet: true,
showShadow: false,
initialValue: model.department,
enabled: model.floor?.departments?.isNotEmpty ?? false,
staticData: model.floor?.departments ?? [],
onSelect: (value) {
if (value == null) {
return;
}
model.department = value;
model.room = null;
setState(() {});
},
),
8.height,
ADatePicker(
label: 'Installation Date'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
date: model.installationDate,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
model.installationDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
setState(() {});
}
});
},
),
8.height,
],
);
}
///Need to check which details show here...
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
//Need to check if not auto update.
// assetDeliveryProvider.parentFormModel.childAssetList?[widget.index]= assetDeliveryProvider.childFormModel;
Navigator.pop(context);
}
Future<void> openInspectionChecklist(BuildContext context) async {
applyInspectionFlagsToChecklist(model: assetDeliveryProvider.childFormModel);
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InspectionChecklistBottomSheet(
initialValues: checkList,
)));
if (result != null) {
checkList = result;
setState(() {});
}
buildInspectionPayload(checkList);
}
bool _isPass(List<InspectionChecklistItem> list, String title) {
return list
.firstWhere(
(e) => e.title == title,
orElse: () => InspectionChecklistItem(status: 'FAIL'),
)
.status ==
'PASS';
}
buildInspectionPayload(List<InspectionChecklistItem> checklist) {
assetDeliveryProvider.childFormModel.flagphysicalInspection = _isPass(checklist, 'Physical Inspection As Per Manufacturer Instructions');
assetDeliveryProvider.childFormModel.flagFunctionPerformance = _isPass(checklist, 'Functional Performance As Per Results Of Manufacturer Recommended Check List');
assetDeliveryProvider.childFormModel.flagGroundingResistance = _isPass(checklist, 'Grounding Resistance: Ω');
assetDeliveryProvider.childFormModel.flagChassiss = _isPass(checklist, 'Chassis Leakage Current: µA');
assetDeliveryProvider.childFormModel.flagLeadsLeakage = _isPass(checklist, 'Leads Leakage Current: µA');
assetDeliveryProvider.childFormModel.flagAlert = _isPass(checklist, 'This Device Is Not Subject To Any Alert Or Recall Until The Date Of Preparation Of This Inspection Form');
}
void applyInspectionFlagsToChecklist({
required TechnicalInspectionAssetModel model,
}) {
if (checkList.isEmpty) {
checkList = AssetDeliveryUtils.inspectionChecklist;
}
for (final item in checkList) {
switch (item.value) {
case 'flagphysicalInspection':
item.status = _statusFromBool(model.flagphysicalInspection);
break;
case 'flagFunctionPerformance':
item.status = _statusFromBool(model.flagFunctionPerformance);
break;
case 'flagGroundingResistance':
item.status = _statusFromBool(model.flagGroundingResistance);
break;
case 'flagChassiss':
item.status = _statusFromBool(model.flagChassiss);
break;
case 'flagLeadsLeakage':
item.status = _statusFromBool(model.flagLeadsLeakage);
break;
case 'flagAlert':
item.status = _statusFromBool(model.flagAlert);
break;
}
}
}
String _statusFromBool(bool? value) {
return value == true ? 'PASS' :value==false? 'FAIL':'';
}
}

@ -1,44 +1,41 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/power_supply_type_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class UpdateTechnicalInspectionLinesView extends StatefulWidget {
static const String id = "/technical-inspection-form";
final AssetDeliveryTableModel deliveryTableModel;
final AssetDeliveryDataModel? requestModel;
final DeliveryLineModel? deliveryLineModel;
UpdateTechnicalInspectionLinesView({
Key? key,
required this.deliveryTableModel,
this.requestModel,
this.deliveryLineModel,
}) : super(key: key);
@override
@ -48,9 +45,15 @@ class UpdateTechnicalInspectionLinesView extends StatefulWidget {
class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInspectionLinesView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TechnicalInspectionFormModel model = TechnicalInspectionFormModel();
AssetDeliveryProvider? assetDeliveryProvider;
bool isLoading = false;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
@ -59,6 +62,18 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
super.dispose();
}
void getInitialData() async {
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
isLoading = true;
setState(() {});
model = await assetDeliveryProvider!.getTechnicalInspectionData(
lineId: widget.deliveryLineModel?.id,
tableId: widget.deliveryTableModel.id,
);
isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -69,53 +84,87 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
costCenterList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
child: isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
itemDetails(context: context, itemNo: widget.deliveryLineModel?.itemNumber, itemDescription: widget.deliveryLineModel?.itemDescription),
12.height,
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
Text(
"Cost Centers",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
costCenterList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
Widget costCenterList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
List<CostCenterModel> costCenterList = model.costCenters ?? [];
return costCenterList.isEmpty
? const NoDataFound().center
: ListView.separated(
itemCount: costCenterList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionCostCard(
costModel: costCenterList[itemIndex],
editPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TechnicalInspectionParentAssetListView(
costCenterId: costCenterList[itemIndex].id,
tableItemId: widget.deliveryTableModel.id,
lineId: widget.deliveryLineModel?.id,
)));
},
isViewOnly: false,
);
},
);
}
Widget itemDetails({required BuildContext context, String? itemNo, String? itemDescription}) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Cost Centers",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
'Item No'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionCostCard(
deliveryDetails: AssetInventoryModel(),
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => TechnicalInspectionParentAssetListView()));
},
isViewOnly: false,
);
},
Text(
itemNo ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Item Description'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
itemDescription ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
@ -124,81 +173,60 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
Widget inspectionDetailsForm() {
return Column(
children: [
AppTextFormField(
labelText: 'Item No'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '232434',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Item Description',
backgroundColor: AppColor.fieldBgColor(context),
initialValue: 'test decription abc',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
SingleItemDropDownMenu<Lookup, PowerSupplyTypeProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Power Supply Type'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
initialValue: model.powerSupplyType,
onSelect: (value) {
if (value != null) {
model.powerSupplyType = value;
setState(() {});
}
},
),
// 8.height,
// LookUpAutoCompleteField(
// clearAfterPick: false,
// forAssetName: true,
// onChanged: (value) {},
// initialValue: '',
// label: 'Cost Center'.addTranslation,
// onPick: (value) {},
// ),
8.height,
AppTextFormField(
labelText: 'Power Reading'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
initialValue: model.powerReading != null ? model.powerReading.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onSaved: (value) {
model.powerReading = int.tryParse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Max Current'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
initialValue: model.maxCurrent != null ? model.maxCurrent.toString() : '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
onSaved: (value) {
model.maxCurrent = int.tryParse(value);
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Voltage'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textInputType: TextInputType.number,
initialValue: model.voltage != null ? model.voltage.toString() : '',
textAlign: TextAlign.center,
onSaved: (value) {
model.voltage = int.tryParse(value);
},
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
@ -207,8 +235,12 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
AppTextFormField(
labelText: 'Frequency'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
initialValue: model.frequency != null ? model.frequency.toString() : '',
textInputType: TextInputType.number,
textAlign: TextAlign.center,
onSaved: (value) {
model.frequency = int.tryParse(value);
},
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
@ -218,7 +250,15 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
}
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
model.tableItemId = widget.deliveryTableModel.id;
model.lineId = widget.deliveryLineModel?.id;
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider?.saveTechnicalInspection(model: model).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
}
});
}
}

@ -1,294 +1,267 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.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_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/module_permissions_model.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_engineer_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/session_model.dart';
import '../../../models/service_request/search_work_order.dart';
import '../../../models/service_request/wo_call_request.dart';
import '../../../models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/room_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/end_user_asset_details_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/history_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_form_model.dart';
import '../../../models/new_models/department.dart';
import '../../../models/new_models/site.dart';
import '../models/oracle_user_model.dart';
class AssetDeliveryProvider extends ChangeNotifier {
final pageItemNumber = 10;
final searchPageItemNumber = 10;
int pageNo = 1;
List<AssetInventoryModel> _devices = [];
List<AssetInventoryModel> _searchDevices = [];
List<AssetInventoryModel> get devices => _devices;
List<AssetInventoryModel> get searchDevices => _searchDevices;
SessionModel? sessionModel;
//TODO need to check i think don't need to create this obj
AssetInventoryResponse? assetInventoryResponse;
AssetInventoryResponse? siteFilterAssetResponse;
List<AssetInventoryModel> sessionAssetList = [];
List<AssetInventoryModel> siteFilterAssetList = [];
AssetDeliveryDataModel? assetDeliveryDataModel;
List<AssetDeliveryTableModel> assetDeliveryTableList = [];
List<DeliveryLineModel> deliveryLinesList = [];
ModulesPermissionsModel? modelPermission;
TechnicalInspectionAssetModel parentFormModel = TechnicalInspectionAssetModel();
TechnicalInspectionAssetModel childFormModel = TechnicalInspectionAssetModel();
void reset() {
pageNo = 1;
modelPermission = null;
assetInventoryResponse = null;
sessionModel = null;
sessionAssetList = [];
stateCode = null;
}
int? stateCode;
bool isDetailLoading = false;
bool nextPage = false;
bool isNextPageLoading = false;
bool isLoading = false;
bool isAllAssetLoading = false;
bool isSiteLoading = false;
bool isDeliveryTableListLoading = false;
bool isDeliveryLineListLoading = false;
bool isChildAssetDataLoading = false;
void searchReset() {
stateCode = null;
_searchDevices = [];
void setParentModel(TechnicalInspectionAssetModel m) {
parentFormModel = m;
notifyListeners();
}
void setChildModel(TechnicalInspectionAssetModel m) {
childFormModel = m;
notifyListeners();
}
Future<void> getSessionById({required int id}) async {
Future<AssetDeliveryDataModel?> getAssetDeliveryDetailById({int? requestId}) async {
try {
sessionModel = SessionModel();
assetDeliveryDataModel = AssetDeliveryDataModel();
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(URLs.getAssetInventoryById + "?assetInventoryId=$id");
final response = await ApiManager.instance.get(URLs.getAssetDeliveryDetailsById + "?Id=$requestId");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
sessionModel = SessionModel.fromJson(json.decode(response.body)["data"]);
assetDeliveryDataModel = AssetDeliveryDataModel.fromJson(json.decode(response.body)["data"]);
} else {
sessionModel = null;
assetDeliveryDataModel = null;
}
isLoading = false;
notifyListeners();
return assetDeliveryDataModel;
} catch (e) {
log("getSessionError [error] : $e");
log("getdelivery details [error] : $e");
isLoading = false;
sessionModel = null;
assetDeliveryDataModel = null;
notifyListeners();
return null;
return assetDeliveryDataModel;
}
}
Future<int> getAssetsInSession({
required int sessionId,
bool loadMore = false,
}) async {
if (isLoading || isNextPageLoading) return -2;
if (loadMore) {
isNextPageLoading = true;
pageNo += 1;
} else {
isLoading = true;
pageNo = 1; // reset pagination
}
notifyListeners();
Future<void> getAssetDeliveryTableListById({int? requestId}) async {
try {
final payload = {
"pageSize": pageItemNumber,
"pageNumber": pageNo,
"sessionId": sessionId,
};
final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
assetDeliveryTableList.clear();
isDeliveryTableListLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getAssetDeliveryTableListById}?assetDeliveryExternalMasterId=$requestId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final newResponse = AssetInventoryResponse.fromJson(jsonData);
if (loadMore) {
assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
assetInventoryResponse?.totalRows = newResponse.totalRows;
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
assetDeliveryTableList = jsonData.map((e) => AssetDeliveryTableModel.fromJson(e)).toList();
} else {
assetInventoryResponse = newResponse;
assetDeliveryTableList = [];
}
nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
} else {
nextPage = false;
assetDeliveryTableList = [];
}
isLoading = false;
isNextPageLoading = false;
isDeliveryTableListLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
isNextPageLoading = false;
stateCode = -1;
nextPage = false;
} catch (e) {
log("get Delivery Table details [error] : $e");
isDeliveryTableListLoading = false;
assetDeliveryTableList = [];
notifyListeners();
return -1;
}
}
///older code
// Future<int> getAssetsInSession({
// required int sessionId,
// bool loadMore = false,
// }) async {
// // if (isLoading || nextPage) return -2;
//
// if (loadMore) {
// nextPage = true;
// pageNo += 1;
// } else {
// isLoading = true;
// pageNo = 1; // reset pagination
// }
//
// notifyListeners();
// log('Fetching page: $pageNo');
//
// try {
// final payload = {
// "pageSize": pageItemNumber,
// "pageNumber": pageNo,
// "sessionId": sessionId,
// };
//
// final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
// stateCode = response.statusCode;
//
// if (response.statusCode >= 200 && response.statusCode < 300) {
// final Map<String, dynamic> jsonData = json.decode(response.body);
// final newResponse = AssetInventoryResponse.fromJson(jsonData);
//
// if (loadMore) {
// assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
// assetInventoryResponse?.totalRows = newResponse.totalRows;
// } else {
// assetInventoryResponse = newResponse;
// }
//
// nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
// }
//
// isLoading = false;
// nextPage = false;
// notifyListeners();
// return response.statusCode;
// } catch (error) {
// isLoading = false;
// nextPage = false;
// stateCode = -1;
// notifyListeners();
// return -1;
// }
// }
Future<int> getInventoryDetailsByFilter({
required Map<String, dynamic> payload,
bool loadMore = false,
}) async {
if (isLoading || isNextPageLoading) return -2;
if (loadMore) {
isNextPageLoading = true;
pageNo += 1;
} else {
isLoading = true;
pageNo = 1;
Future<void> getDeliveryLinesListById({int? itemId}) async {
try {
deliveryLinesList.clear();
isDeliveryLineListLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getLineFromExternalPo}?assetDeliveryExternalDeliveryId=$itemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
deliveryLinesList = jsonData.map((e) => DeliveryLineModel.fromJson(e)).toList();
} else {
deliveryLinesList = [];
}
} else {
deliveryLinesList = [];
}
isDeliveryLineListLoading = false;
notifyListeners();
} catch (e) {
log("get Delivery Lines List [error] : $e");
isDeliveryLineListLoading = false;
deliveryLinesList = [];
notifyListeners();
}
}
notifyListeners();
log('Fetching inventory page: $pageNo');
Future<List<DeliveryLineModel>> getTechnicalInspectionLinesListById({int? itemId}) async {
List<DeliveryLineModel> linesList = [];
try {
final paginatedPayload = {
...payload,
"pageSize": pageItemNumber,
"pageNumber": pageNo,
};
final response = await ApiManager.instance.post(URLs.getInventoryDetailsByFilter, body: paginatedPayload);
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getLineFromTechnicalInspection}?assetDeliveryExternalDeliveryId=$itemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final newResponse = AssetInventoryResponse.fromJson(jsonData);
if (loadMore) {
siteFilterAssetList.addAll(newResponse.assetList ?? []);
siteFilterAssetResponse?.totalRows = newResponse.totalRows;
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
linesList = jsonData.map((e) => DeliveryLineModel.fromJson(e)).toList();
} else {
siteFilterAssetResponse = newResponse;
siteFilterAssetList = newResponse.assetList ?? [];
assetDeliveryTableList = [];
}
nextPage = (siteFilterAssetList.length) < (siteFilterAssetResponse?.totalRows ?? 0);
} else {
siteFilterAssetList = [];
nextPage = false;
linesList = [];
}
isLoading = false;
notifyListeners();
return linesList;
} catch (e) {
log("get Delivery Lines List [error] : $e");
isLoading = false;
linesList = [];
notifyListeners();
return linesList;
}
}
Future<List<CostCenterModel>> getAssetDeliveryCostCenterListForLines({int? lineId, int? tableItemId}) async {
List<CostCenterModel> costCenterList = [];
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getCostCenterListToLineDeliveryInspection}?AssetDeliveryExternalDetailId=$lineId&AssetDeliveryExternalDeliveryId=$tableItemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
costCenterList = jsonData.map((e) => CostCenterModel.fromJson(e)).toList();
}
} else {
costCenterList = [];
}
isLoading = false;
isNextPageLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
return costCenterList;
} catch (e) {
log("get Delivery Lines List [error] : $e");
isLoading = false;
isNextPageLoading = false;
nextPage = false;
stateCode = -1;
costCenterList = [];
notifyListeners();
return -1;
return costCenterList;
}
}
Future<AssetInventoryModel?> searchAsset({
required Map<String, dynamic> payload,
Future<bool> addNewDelivery({
int? requestId,
}) async {
isDeliveryTableListLoading = true;
Map<String, dynamic> payload = {
'assetDeliveryExternalMasterId': requestId,
};
try {
final response = await ApiManager.instance.post(URLs.addNewDelivery, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isDeliveryTableListLoading = false;
notifyListeners();
return true;
} else {
isDeliveryTableListLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isDeliveryTableListLoading = false;
notifyListeners();
return false;
}
}
Future<bool> saveTechnicalInspection({
required TechnicalInspectionFormModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.searchAsset, body: payload);
final response = await ApiManager.instance.post(URLs.saveTechnicalInspection, body: model.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body)["data"];
AssetInventoryModel model = AssetInventoryModel.fromJson(jsonData);
log('model json ${model.toJson()}');
isLoading = false;
notifyListeners();
return model;
return true;
} else {
isLoading = false;
notifyListeners();
return null;
return false;
}
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return null;
return false;
}
}
Future<bool> saveAssetInSession({
AssetInventoryModel? model,
Future<bool> saveCostCenterToLineDeliveryInspection({
int? tableItemId,
int? lineId,
List<CostCenterModel>? list,
}) async {
isLoading = true;
Map<String, dynamic> payload = {
"assetDeliveryExternalDeliveryId": tableItemId,
"assetDeliveryExternalDetailId": lineId,
"costCenters": list?.map((x) => x.toJson()).toList(),
};
try {
final response = await ApiManager.instance.post(URLs.saveAssetInSession, body: model?.toJson() ?? {});
final response = await ApiManager.instance.post(URLs.saveCostCenterToLineDeliveryInspection, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
@ -306,151 +279,435 @@ class AssetDeliveryProvider extends ChangeNotifier {
}
}
Future<String?> getClassification({
required Map<String, dynamic> payload,
}) async {
Future<bool> changeDeliveryStatusToCancel({int? itemId}) async {
isLoading = true;
String? classification;
try {
final response = await ApiManager.instance.post(URLs.getClassification, body: payload);
final response = await ApiManager.instance.get(
"${URLs.changeDeliveryStatusToCancel}?assetDeliveryExternalDeliveryId=$itemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
log('classifcation on response ${json.decode(response.body)["data"]['classification']}');
classification = json.decode(response.body)["data"]['classification'];
isLoading = false;
notifyListeners();
return classification;
return true;
} else {
isLoading = false;
notifyListeners();
return classification;
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return classification;
return false;
}
}
Future<bool> deleteAssetISession({required num id}) async {
Future<bool> changeDeliveryStatus({
int? itemId,
Map<String, dynamic>? requestPayload,
}) async {
isLoading = true;
Map<String, dynamic> payload = {
'assetDeliveryExternalDeliveryId': itemId,
};
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(URLs.deleteAssetInSession + "?id=$id");
final response = await ApiManager.instance.post(URLs.changeDeliveryStatus, body: requestPayload ?? payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
}
Future<DeliveryInspectionFormModel> getAssetDeliveryInspectionData({int? itemId}) async {
isLoading = true;
DeliveryInspectionFormModel deliveryInspectionFormModel = DeliveryInspectionFormModel();
try {
final response = await ApiManager.instance.get(
"${URLs.getAssetDeliveryInspectionData}?assetDeliveryExternalDeliveryId=$itemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
deliveryInspectionFormModel = DeliveryInspectionFormModel.fromJson(json.decode(response.body)["data"]);
}
isLoading = false;
notifyListeners();
return deliveryInspectionFormModel;
} catch (e) {
log("Delete Asset [error] : $e");
log("getAssetDeliveryInspectionData details [error] : $e");
isLoading = false;
notifyListeners();
return false;
return deliveryInspectionFormModel;
}
}
Future<List<Lookup>> getAutoCompleteDetails({
bool? isManufacturer,
String? query,
int type = 0,
}) async {
Future<TechnicalInspectionFormModel> getTechnicalInspectionData({int? lineId, int? tableId}) async {
isLoading = true;
TechnicalInspectionFormModel technicalInspectionFormModel = TechnicalInspectionFormModel();
try {
String url = '';
switch (type) {
//for model and manufacturer..
case 0:
url = URLs.getManufacturerOrModelAutoComplete;
break;
//for asset name..
case 1:
url = URLs.searchAssetName;
break;
//for supplier...
case 2:
url = URLs.getSuppliersAutoCompleteInventory;
break;
default:
url = URLs.getManufacturerOrModelAutoComplete;
}
final queryParams = <String, String>{};
if (isManufacturer != null && type == 0) {
queryParams['isManufacturer'] = isManufacturer.toString();
final response = await ApiManager.instance.get(
"${URLs.getTechnicalInspectionByDetailId}?assetDeliveryExternalDetailId=$lineId&assetDeliveryExternalDeliveryId=$tableId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
technicalInspectionFormModel = TechnicalInspectionFormModel.fromJson(json.decode(response.body)["data"]);
}
if (query != null && query.isNotEmpty) {
queryParams['searchText'] = query;
isLoading = false;
notifyListeners();
return technicalInspectionFormModel;
} catch (e) {
log("getTechnicalInspectionByDetailId details [error] : $e");
isLoading = false;
notifyListeners();
return technicalInspectionFormModel;
}
}
Future<DeliveryInspectionFormModel> getDeliveryHistories({int? itemId}) async {
isLoading = true;
DeliveryInspectionFormModel deliveryInspectionFormModel = DeliveryInspectionFormModel();
try {
final response = await ApiManager.instance.get(
"${URLs.getAssetDeliveryInspectionData}?assetDeliveryExternalDeliveryId=$itemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
deliveryInspectionFormModel = DeliveryInspectionFormModel.fromJson(json.decode(response.body)["data"]);
}
if (queryParams.isNotEmpty) {
url += '?${Uri(queryParameters: queryParams).query}';
isLoading = false;
notifyListeners();
return deliveryInspectionFormModel;
} catch (e) {
log("getAssetDeliveryInspectionData details [error] : $e");
isLoading = false;
notifyListeners();
return deliveryInspectionFormModel;
}
}
Future<List<OracleUserModel>> getOracleUserAutoCompleteDetails({
String? query,
}) async {
try {
isLoading = true;
final response = await ApiManager.instance.post(URLs.getOracleUserList, body: {'employeeName': query});
List<OracleUserModel> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
final data = json.decode(response.body)["data"];
list = (data as List).map((e) => OracleUserModel.fromJson(e)).toList();
}
final response = await ApiManager.instance.get(url);
isLoading = false;
notifyListeners();
return list;
} catch (error) {
log('error $error');
isLoading = false;
notifyListeners();
return [];
}
}
List<Lookup> list = [];
Future<List<GenericAttachmentModel>> getAttachments({
num? tableItemId,
}) async {
try {
isLoading = true;
final response = await ApiManager.instance.get("${URLs.getAttachments}?assetDeliveryExternalDeliveryId=$tableItemId");
List<GenericAttachmentModel> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
final data = json.decode(response.body)["data"];
list = (data as List).map((e) => Lookup.fromJson(e)).toList();
list = (data as List).map((e) => GenericAttachmentModel.fromJson(e)).toList();
}
isLoading = false;
notifyListeners();
return list;
} catch (error) {
log('error $error');
isLoading = false;
notifyListeners();
return [];
}
}
Future<int> getAssets({DeviceSearch? search, bool isQr = false, bool isSearchBy = false, num? sessionId}) async {
if (isLoading == true) return -2;
Future<List<TechnicalInspectionAssetModel>> getParentAssetList({int? costCenterId, int? tableItemId, int? lineId}) async {
List<TechnicalInspectionAssetModel> parentAssetList = [];
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getTechnicalInspectionParentData}?assetDeliveryExternalDeliveryId=$tableItemId&assetDeliveryExternalDetailId=$lineId&costCenterId=$costCenterId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
parentAssetList = jsonData.map((e) => TechnicalInspectionAssetModel.fromJson(e)).toList();
}
} else {
parentAssetList = [];
}
isLoading = false;
notifyListeners();
return parentAssetList;
} catch (e) {
log("get parent List [error] : $e");
isLoading = false;
parentAssetList = [];
notifyListeners();
return parentAssetList;
}
}
Future<TechnicalInspectionAssetModel> getSiteData({
required num? siteId,
required TechnicalInspectionAssetModel model,
}) async {
isSiteLoading = true;
notifyListeners();
try {
final response = await ApiManager.instance.get(
"${URLs.getSiteAutoCompleteWithoutConditionSites}?id=$siteId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final List? siteData = json.decode(response.body)["data"];
if (siteData != null && siteData.isNotEmpty) {
model.site = Site.fromJson(siteData.first);
}
model.building = model.site?.buildings?.firstWhere(
(e) => e.value == model.building?.value,
orElse: () => Building(),
);
model.floor = model.building?.floors?.firstWhere(
(e) => e.value == model.floor?.value,
orElse: () => Floor(),
);
model.department = model.floor?.departments?.firstWhere(
(e) => e.departmentName == model.department?.departmentName,
orElse: () => Department(),
);
model.room = model.department?.rooms?.firstWhere(
(e) => e.value == model.room?.value,
orElse: () => Rooms(),
);
}
isSiteLoading = false;
notifyListeners();
return model;
} catch (e) {
isSiteLoading = false;
stateCode = -1;
notifyListeners();
return model;
}
}
Future<TechnicalInspectionAssetModel?> getAssetDetails({required num? assetId}) async {
isLoading = true;
notifyListeners();
late Response response;
try {
final Map<String, dynamic> body = {
"pageSize": isSearchBy ? searchPageItemNumber : pageItemNumber,
"pageNumber": isSearchBy ? (searchDevices.length / searchPageItemNumber).ceil() + 1 : devices.length ~/ pageItemNumber + 1,
"sessionId": sessionId ?? 0,
"assetSerialNo": search?.assetSerialNumber ?? '',
"assetName": search?.assetName ?? '',
"model": search?.model ?? '',
"manufacturer": search?.manufacturer ?? '',
"supplier": search?.supplier ?? '',
"siteName": search?.site ?? '',
// "buildingName":search?.??'',
// "floorName": search?.f??'',
"departmentName": search?.department ?? '',
// "roomName": search?.room
};
// if (search != null) body.addAll(search.toJson());
response = await ApiManager.instance.post(URLs.getAssetsTemp, body: body);
Response response = await ApiManager.instance.get(URLs.getAssetDetailsByAssetId + "?AssetDeliveryInternalDetailAssetId=$assetId");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = json.decode(response.body)["data"];
TechnicalInspectionAssetModel assetModel = TechnicalInspectionAssetModel.fromJson(data);
isLoading = false;
notifyListeners();
return assetModel;
} else {
return null;
}
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return -1;
return null;
}
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
List equipmentListJson = json.decode(response.body)["data"];
var dList = equipmentListJson.map<AssetInventoryModel>((asset) => AssetInventoryModel.fromJson(asset)).toList() ?? [];
isSearchBy ? _searchDevices.addAll(dList) : _devices.addAll(dList);
nextPage = true;
} else {
nextPage = false;
}
Future<bool> saveTechnicalInspectionAssetData({
required TechnicalInspectionAssetModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.saveTechnicalInspectionAsset, body: model.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
isLoading = false;
notifyListeners();
return response.statusCode;
}
Future<bool> markAsComplete({
Future<bool> saveAttachment({
required Map<String, dynamic> payload,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.convertDetailToComplete, body: payload);
final response = await ApiManager.instance.post(URLs.saveAttachments, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
}
Future<List<AssetDeliveryHistoryModel>> getHistory({
num? tableItemId,
}) async {
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get("${URLs.getDeliveryHistories}?assetDeliveryExternalDeliveryId=$tableItemId");
List<AssetDeliveryHistoryModel> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
final data = json.decode(response.body)["data"];
list = (data as List).map((e) => AssetDeliveryHistoryModel.fromJson(e)).toList();
}
isLoading = false;
notifyListeners();
return list;
} catch (error) {
log('error $error');
isLoading = false;
notifyListeners();
return [];
}
}
//End user
Future<List<CostCenterModel>> getEndUserCostCenterList({int? tableItemId}) async {
List<CostCenterModel> costCenterList = [];
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getEndUserAcceptanceCostCenter}?assetDeliveryExternalDeliveryId=$tableItemId",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
costCenterList = jsonData.map((e) => CostCenterModel.fromJson(e)).toList();
}
} else {
costCenterList = [];
}
isLoading = false;
notifyListeners();
return costCenterList;
} catch (e) {
log("get costCenter for End user [error] : $e");
isLoading = false;
costCenterList = [];
notifyListeners();
return costCenterList;
}
}
Future<List<EndUserAssetDetailsModel>> getEndUserAssetList({int? tableItemId, String? costCenterName}) async {
List<EndUserAssetDetailsModel> assetList = [];
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(
"${URLs.getCostCenterAssetList}?assetDeliveryExternalDeliveryId=$tableItemId&costCenterName=$costCenterName",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
if (jsonData is List) {
assetList = jsonData.map((e) => EndUserAssetDetailsModel.fromJson(e)).toList();
}
} else {
assetList = [];
}
isLoading = false;
notifyListeners();
return assetList;
} catch (e) {
log("get End User AssetList [error] : $e");
isLoading = false;
assetList = [];
notifyListeners();
return assetList;
}
}
Future<bool> saveEndUserFormData({
required CostCenterModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.saveEndUserFormData, body: model.toEndUserAcceptanceFormJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
}
Future<bool> saveEndUserAssetDataData({
required EndUserAssetDetailsModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.saveEndUserAssetData, body: model.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;

@ -0,0 +1,45 @@
import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/loan_module/models/medical_department_model.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class CostCenterProvider extends LoadingListNotifier<Lookup> {
@override
Future<void> getData({int? id}) async {
if (loading) return;
loading = true;
notifyListeners();
try {
final response = await ApiManager.instance.get(
URLs.getCostCenterToPo + "?assetDeliveryExternalMasterId=$id",
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final List list = json.decode(response.body)['data'];
final Set<String> seenNames = {};
int index = 0;
items =
list.where((e) => e is Map && e['name'] != null && e['name'].toString().trim().isNotEmpty).map((e) => e['name'].toString().trim()).where((name) => seenNames.add(name)).map<Lookup>((name) {
final lookup = Lookup(
id: index,
value: index + 1,
name: name,
);
index++;
return lookup;
}).toList();
}
} catch (e, s) {
log('getData error', error: e, stackTrace: s);
stateCode = -1;
} finally {
loading = false;
notifyListeners();
}
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class EndUserRejectionReasonLookupProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.endUserRejectionReasonLookup);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class EndUserStatusLookupProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.endUserStatusLookup);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class PowerSupplyTypeProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.powerSupplyTypeLookUp);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -385,7 +385,7 @@ class ServiceRequestBottomSheet {
],
);
},
).toShimmer(isShow: snapshot.loading,context: context);
).toShimmer(isShow: snapshot.loading, context: context);
});
}
@ -645,7 +645,7 @@ class ServiceRequestBottomSheet {
borderRadius: BorderRadius.circular(14), // Circular border radius
),
// color: AppColor.neutral80,
color: AppColor.background(context),
color: AppColor.background(context),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start, // Align items at the top
children: [
@ -1191,30 +1191,26 @@ class ServiceRequestBottomSheet {
10.height,
StatefulBuilder(
builder: (context, setState) {
return Column(
children: [
ESignature(
title: '',
oldSignature: '',
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onChange: (signature) {
if (signature.isEmpty) return;
setState(() {
newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
onSaved: (signature) {
if (signature == null || signature.isEmpty) return;
setState(() {
newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
),
],
return ESignature(
title: '',
oldSignature: '',
newSignature: newSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onChange: (signature) {
if (signature.isEmpty) return;
setState(() {
newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
onSaved: (signature) {
if (signature == null || signature.isEmpty) return;
setState(() {
newSignature = signature;
nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
);
},
),

@ -0,0 +1,295 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/models/new_models/task_request/task_type_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_form_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_supplier_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/item_type_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_inspection_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_supplier_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/order_type_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/gas_request_providers/site_provider.dart';
import '../../../../../../new_views/common_widgets/default_app_bar.dart';
class CreateMedicalGasRequestPage extends StatefulWidget {
static const String id = "/create-medical-gas";
final MedicalGasDataModel? dataModel;
CreateMedicalGasRequestPage({Key? key, this.dataModel}) : super(key: key);
@override
_CreateMedicalGasRequestPageState createState() => _CreateMedicalGasRequestPageState();
}
class _CreateMedicalGasRequestPageState extends State<CreateMedicalGasRequestPage> with TickerProviderStateMixin {
final List<GenericAttachmentModel> attachments = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TaskType? selectedType;
MedicalGasFormModel _medicalGasFormModel = MedicalGasFormModel();
MedicalGasSupplierModel? medicalGasInfo;
late MedicalGasInspectionProvider medicalGasInspectionProvider;
bool isGasInfoLoading = false;
@override
void initState() {
super.initState();
// Provider.of<MedicalGasSupplierProvider>(context, listen: false).reset();
medicalGasInspectionProvider = Provider.of<MedicalGasInspectionProvider>(context, listen: false);
_populateFormData();
}
_populateFormData() {
if (widget.dataModel != null) {
MedicalGasDataModel dataModel = widget.dataModel!;
_medicalGasFormModel = MedicalGasFormModel(
id: dataModel.id,
orderType: Lookup(id: dataModel.requestOrderTypeId, name: dataModel.requestOrderType),
itemType: Lookup(id: dataModel.itemTypeId, name: dataModel.itemType),
site: Site(id: dataModel.siteId, custName: dataModel.site),
supplier: MedicalGasSupplierModel(id: dataModel.supplierId, supplier: dataModel.supplier),
);
List<AttributeInfo> attributeInfo = [];
dataModel.requestDetailDtos.forEach((v) {
attributeInfo.add(AttributeInfo.fromJson(v.toJson()));
});
medicalGasInfo = MedicalGasSupplierModel(
supplierContact: dataModel.contact,
supplierEmail: dataModel.email,
attributeInfo: attributeInfo,
);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(title: 'Medical Gas Inspection'.addTranslation),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
SingleItemDropDownMenu<Lookup, MedicalGasOrderTypeProvider>(
context: context,
title: "Order Type",
validator: (value) {
if (value == null) return "Mandatory";
return null;
},
initialValue: _medicalGasFormModel.orderType,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
_medicalGasFormModel.orderType = value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, MedicalGasItemTypeProvider>(
context: context,
title: "Item Type",
validator: (value) {
if (value == null) return "Mandatory";
return null;
},
initialValue: _medicalGasFormModel.itemType,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
_medicalGasFormModel.itemType = value;
setState(() {});
setGasInfo();
},
),
8.height,
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: context.translation.site,
initialValue: _medicalGasFormModel.site,
showShadow: false,
validator: (value) {
if (value == null) return "Please select a site";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
_medicalGasFormModel.site = value;
setState(() {});
setGasInfo();
},
),
8.height,
// 8.height,
// SingleItemDropDownMenu<MedicalDepartmentModel, MedicalDepartmentProvider>(
// context: context,
// title: context.translation.department,
// showShadow: false,
// validator: (value) {
// if (value == null) return "Please select a department";
// return null;
// },
// showAsBottomSheet: true,
// initialValue: _medicalGasFormModel.department,
// requestById: context.userProvider.user?.clientId,
// backgroundColor: AppColor.fieldBgColor(context),
// onSelect: (value) {
// _medicalGasFormModel.department = value;
// setState(() {});
// },
// ),
// 8.height,
SingleItemDropDownMenu<MedicalGasSupplierModel, MedicalGasSupplierProvider>(
context: context,
title: context.translation.supplier,
initialValue: _medicalGasFormModel.supplier,
showAsBottomSheet: true,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
onSelect: (value) {
setState(() {
_medicalGasFormModel.supplier = value;
});
setGasInfo();
},
),
if (medicalGasInfo != null) medicalGasInfoWidget(),
],
).toShadowContainer(context, borderRadius: 20),
).expanded,
FooterActionButton.footerContainer(
context: context,
child: Row(
children: [
AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Save'.addTranslation,
onPressed: () {
_update(isSubmitted: false);
},
// buttonColor: AppColor.primary10,
).expanded,
8.width,
AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Submit'.addTranslation,
onPressed: () {
_update(isSubmitted: true);
},
// buttonColor: AppColor.primary10,
).expanded,
],
),
),
],
),
),
);
}
void setGasInfo() async {
if (_medicalGasFormModel.itemType != null && _medicalGasFormModel.site != null && _medicalGasFormModel.supplier != null) {
setState(() {
isGasInfoLoading = true;
});
medicalGasInfo =
await medicalGasInspectionProvider.getMedicalGasInfo(itemTypeId: _medicalGasFormModel.itemType!.id, supplierId: _medicalGasFormModel.supplier!.id, siteId: _medicalGasFormModel.site!.id);
setState(() {
isGasInfoLoading = false;
});
}
}
Widget medicalGasInfoWidget() {
return isGasInfoLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
8.height,
'Supplier Contact: ${medicalGasInfo?.supplierContact ?? "-"}'.bodyText(context).custom(color: AppColor.black10),
8.height,
'Supplier Email: ${medicalGasInfo?.supplierEmail ?? "-"}'.bodyText(context).custom(color: AppColor.black10),
8.height,
'Items'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)),
8.height,
// MedicalGasItemsListView(
// itemsList: medicalGasInfo?.attributeInfo ?? [],
// ),
if (medicalGasInfo!.attributeInfo!.isNotEmpty)
ListView.separated(
separatorBuilder: (_, __) => 12.height,
itemCount: medicalGasInfo!.attributeInfo!.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
AttributeInfo model = medicalGasInfo!.attributeInfo![index];
return AppTextFormField(
labelText: model.itemName,
hintText: 'Enter Quantity'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.requestedQuantity != null ? model.requestedQuantity.toString() : '',
textAlign: TextAlign.center,
enable: true,
textInputType: TextInputType.number,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
if (value.isNotEmpty) {
model.requestedQuantity = int.tryParse(value);
}
},
style: Theme.of(context).textTheme.titleMedium,
);
},
)
],
);
}
Future<void> _update({bool isSubmitted = false}) async {
if (medicalGasInfo != null && medicalGasInfo!.attributeInfo!.isNotEmpty) {
_medicalGasFormModel.gasRequestDetail = [];
for (var item in medicalGasInfo!.attributeInfo!) {
_medicalGasFormModel.gasRequestDetail?.add(MedicalGasFormDetailModel(
id: widget.dataModel != null ? item.id : 0,
medicalGasAttributeId: item.medicalGasAttributeId ?? item.id,
requestedQuantity: item.requestedQuantity,
));
}
}
_medicalGasFormModel.isSubmitted = isSubmitted;
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await medicalGasInspectionProvider.saveMedicalGas(model: _medicalGasFormModel).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context, true);
}
});
}
}

@ -0,0 +1,152 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/medical_gas_inspection/create_medical_gas_request_page.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_inspection_provider.dart';
import 'package:test_sa/modules/medical_gas_inspection/update_delivery_notes_page.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/default_app_bar.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class MedicalGasInspectionDetailPage extends StatefulWidget {
static const String id = "/medical-gas-inspection-detail-page";
final int inspectionId;
final String? prority;
MedicalGasInspectionDetailPage({Key? key, required this.inspectionId, this.prority}) : super(key: key);
@override
State<MedicalGasInspectionDetailPage> createState() => _MedicalGasInspectionDetailPageState();
}
class _MedicalGasInspectionDetailPageState extends State<MedicalGasInspectionDetailPage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadData();
});
}
MedicalGasDataModel? model;
bool _isLoading = true;
Future<void> _loadData() async {
final result = await context.read<MedicalGasInspectionProvider>().getMedicalGasById(requestId: widget.inspectionId);
setState(() {
model = result;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const DefaultAppBar(title: "Request Details"),
body: SafeArea(
child: _isLoading
? SizedBox.expand(child: const CircularProgressIndicator(color: AppColor.primary10).center)
: model == null
? const NoDataFound().center
: Column(
children: [
ListView(
padding: const EdgeInsets.all(16),
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//Need to return the status form api backend
Row(
children: [
if (widget.prority != null) ...[
StatusLabel(
label: widget.prority,
textColor: AppColor.getRequestStatusTextColorByName(context, widget.prority),
backgroundColor: AppColor.getRequestStatusColorByName(context, widget.prority),
),
8.width,
],
StatusLabel(
label: model?.requestStatus?.name,
textColor: AppColor.getHistoryLogStatusTextColorByName(model?.requestStatus?.name ?? ''),
backgroundColor: AppColor.getHistoryLogStatusColorByName(model?.requestStatus?.name ?? ''),
),
1.width.expanded,
Text(model!.requestedDate!.toServiceRequestCardFormat,
textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50))
],
),
8.height,
Text("Request Details", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'${context.translation.requestNo}: ${model?.requestNumber ?? '-'}'.bodyText(context),
'Order Type: ${model?.requestOrderType ?? '-'}'.bodyText(context),
'Item Type: ${model?.itemType ?? '-'}'.bodyText(context),
'Site: ${model?.site ?? '-'}'.bodyText(context),
'Supplier Name: ${model?.supplier ?? '-'}'.bodyText(context),
'Supplier Contact: ${model?.contact ?? '-'}'.bodyText(context),
'Supplier Email: ${model?.email ?? '-'}'.bodyText(context),
if (model!.deliveryNoteAttachmentDto.isNotEmpty) ...[
const Divider().defaultStyle(context),
Text(
"Attachments".addTranslation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
FilesList(images: model!.deliveryNoteAttachmentDto.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context, padding: 12),
],
).expanded,
if (model?.requestStatus?.value != null && model!.requestStatus!.value! < 3)
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: model?.isSubmitted == true ? "Upload Delivery Note" : 'Update',
onPressed: () async {
if (model?.isSubmitted == true) {
bool? isRefresh = await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateDeliveryNotes(dataModel: model)));
if (isRefresh == true) {
_loadData();
}
return;
}
bool? isRefresh = await Navigator.of(context).push(MaterialPageRoute(
builder: (_) => CreateMedicalGasRequestPage(
dataModel: model,
)));
if (isRefresh == true) {
_loadData();
}
}),
),
],
),
));
}
Widget labelValueText(BuildContext context, String label, String? value) {
if (value == null || value.isEmpty) return const SizedBox.shrink();
return Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Text(
'$label: $value',
style: AppTextStyles.bodyText.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral120,
),
),
);
}
}

@ -0,0 +1,130 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/all_requests_and_count_model.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class MedicalGasInspectionItemView extends StatelessWidget {
final Data? requestData;
final RequestsDetails? requestDetails;
final bool showShadow;
const MedicalGasInspectionItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key);
@override
Widget build(BuildContext context) {
if (requestData != null) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (requestData!.priorityName != null) ...[
StatusLabel(
label: requestData!.priorityName!,
textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.priorityName!),
backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.priorityName!),
),
8.width,
],
StatusLabel(
label: requestData!.statusName!,
textColor: AppColor.getHistoryLogStatusTextColorByName(requestData!.statusName!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(requestData!.statusName!),
),
1.width.expanded,
Text(requestData!.transactionDate!.toServiceRequestCardFormat,
textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50)),
],
),
(requestData?.typeTransaction ?? 'Medical Gas Request').heading5(context),
infoWidget(label: 'Request Number'.addTranslation, value: requestData?.requestNo ?? '-', context: context),
infoWidget(label: 'Request Type'.addTranslation, value: requestData?.requestType ?? '-', context: context),
// infoWidget(label: 'Site'.addTranslation, value: requestData?.si ?? '-', context: context),
// infoWidget(label: 'Gas Type'.addTranslation, value: requestDetails?.gasType ?? '-', context: context),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewDetails,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => MedicalGasInspectionDetailPage(
inspectionId: requestData!.id!,
prority: requestData?.priorityName,
)));
});
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (requestDetails!.priority != null) ...[
StatusLabel(
label: requestDetails!.priority!,
textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails!.priority!),
backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails!.priority!),
),
8.width,
],
StatusLabel(
label: requestDetails!.status!,
textColor: AppColor.getHistoryLogStatusTextColorByName(requestDetails!.status!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(requestDetails!.status!),
),
1.width.expanded,
Text(requestDetails!.date!.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50)),
],
),
(requestDetails?.nameOfType ?? 'Medical Gas Request').heading5(context),
infoWidget(label: 'Request Number'.addTranslation, value: requestDetails?.requestNo ?? '-', context: context),
infoWidget(label: 'Request Type'.addTranslation, value: requestDetails?.requestType ?? '-', context: context),
infoWidget(label: 'Site'.addTranslation, value: requestDetails?.site ?? '-', context: context),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translation.viewDetails,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
4.width,
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
],
),
],
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => MedicalGasInspectionDetailPage(
inspectionId: requestDetails!.id!,
prority: requestDetails?.priority,
)));
});
}
Widget infoWidget({required String label, String? value, required BuildContext context}) {
if (value != null && value.isNotEmpty) {
return '$label: $value'.bodyText(context);
}
return const SizedBox();
}
}

@ -0,0 +1,94 @@
// import 'dart:developer';
//
// import 'package:flutter/material.dart';
// import 'package:provider/provider.dart';
// import 'package:test_sa/extensions/context_extension.dart';
// import 'package:test_sa/extensions/enum_extensions.dart';
// import 'package:test_sa/extensions/int_extensions.dart';
// import 'package:test_sa/extensions/string_extensions.dart';
// import 'package:test_sa/extensions/text_extensions.dart';
// import 'package:test_sa/extensions/widget_extensions.dart';
// import 'package:test_sa/models/lookup.dart';
// import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
// import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
// import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
// import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
// import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_supplier_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/new_views/common_widgets/app_text_form_field.dart';
// import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
// import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
//
// class MedicalGasItemsListView extends StatelessWidget {
// final List<AttributeInfo> itemsList;
//
// MedicalGasItemsListView({
// super.key,
// required this.itemsList,
// });
//
// late AssetDeliveryProvider assetDeliveryProvider;
//
// @override
// Widget build(BuildContext context) {
// // return ListView.separated(
// // separatorBuilder: (_, __) => 12.height,
// // itemCount: itemsList.length,
// // shrinkWrap: true,
// // itemBuilder: (context, index) {
// // AttributeInfo model = itemsList[index];
// // return AppTextFormField(
// // labelText: model.itemName,
// // hintText: 'Enter Quantity'.addTranslation,
// // backgroundColor: AppColor.fieldBgColor(context),
// // initialValue: model.requestedQuantity != null ? model.requestedQuantity.toString() : '',
// // textAlign: TextAlign.center,
// // enable: true,
// // textInputType: TextInputType.number,
// // labelStyle: AppTextStyles.textFieldLabelStyle,
// // showShadow: false,
// // onChange: (value) {
// // if (value.isNotEmpty) {
// // model.requestedQuantity = int.tryParse(value);
// // }
// // },
// // style: Theme.of(context).textTheme.titleMedium,
// // );
// // },
// // );
// }
// }
//
// // class ItemCard extends StatelessWidget {
// // final AttributeInfo model;
// // final int index;
// //
// // const ItemCard({
// // super.key,
// // required this.model,
// // required this.index,
// // });
// //
// // @override
// // Widget build(BuildContext context) {
// // return AppTextFormField(
// // labelText: model.itemName,
// // hintText: 'Enter Quantity'.addTranslation,
// // backgroundColor: AppColor.fieldBgColor(context),
// // initialValue: model.requestedQuantity != null ? model.requestedQuantity.toString() : '',
// // textAlign: TextAlign.center,
// // enable: true,
// // textInputType: TextInputType.number,
// // labelStyle: AppTextStyles.textFieldLabelStyle,
// // showShadow: false,
// // onChange: (value) {
// // if (value.isNotEmpty) {
// // model.requestedQuantity = int.tryParse(value);
// // }
// // },
// // style: Theme.of(context).textTheme.titleMedium,
// // );
// // }
// // }

@ -0,0 +1,92 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
class DeliveryNotesFormModel {
int? id;
DateTime? deliveredDate;
String? deliveryNoteNumber;
bool? isPressureChecked;
bool? isInspectedGasLeak;
bool? isSubmitted;
List<GasDeliveredQuantityModel> gasDeliveredQuantityDtos = [];
List<MedicalGasRequestDetailModel> deliveredItemList = [];
List<GenericAttachmentModel> attachments = [];
DeliveryNotesFormModel({
this.id,
this.deliveredDate,
this.deliveryNoteNumber,
this.isPressureChecked,
this.isInspectedGasLeak,
this.isSubmitted,
List<GasDeliveredQuantityModel>? gasDeliveredQuantityDtos,
List<MedicalGasRequestDetailModel>? deliveredItemList,
List<GenericAttachmentModel>? attachments,
}) {
this.gasDeliveredQuantityDtos = gasDeliveredQuantityDtos ?? [];
this.deliveredItemList = deliveredItemList ?? [];
this.attachments = attachments ?? [];
}
DeliveryNotesFormModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
deliveredDate = json['deliveredDate'] != null ? DateTime.parse(json['deliveredDate']) : null;
deliveryNoteNumber = json['deliveryNoteNumber'];
isPressureChecked = json['isPressureChecked'];
isInspectedGasLeak = json['isInspectedGasLeak'];
isSubmitted = json['isSubmitted'];
if (json['gasDeliveredQuantityDtos'] != null) {
gasDeliveredQuantityDtos = [];
json['gasDeliveredQuantityDtos'].forEach((v) {
gasDeliveredQuantityDtos.add(GasDeliveredQuantityModel.fromJson(v));
});
}
if (json['cUMedicalGasDeliveryNoteAttachmentDtos'] != null) {
attachments = [];
json['cUMedicalGasDeliveryNoteAttachmentDtos'].forEach((v) {
attachments.add(GenericAttachmentModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
return {
'id': id,
'deliveredDate': deliveredDate?.toIso8601String(),
'deliveryNoteNumber': deliveryNoteNumber,
'isPressureChecked': isPressureChecked,
'isInspectedGasLeak': isInspectedGasLeak,
'isSubmitted': isSubmitted,
'gasDeliveredQuantityDtos': gasDeliveredQuantityDtos.map((e) => e.toJson()).toList(),
'cUMedicalGasDeliveryNoteAttachmentDtos': attachments.map((e) => e.toJson()).toList(),
};
}
}
class GasDeliveredQuantityModel {
int? id;
num? medicalGasAttributeId;
num? deliveredQuantity;
GasDeliveredQuantityModel({
this.id,
this.medicalGasAttributeId,
this.deliveredQuantity,
});
GasDeliveredQuantityModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
medicalGasAttributeId = json['medicalGasAttributeId'];
deliveredQuantity = json['deliveredQuantity'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'medicalGasAttributeId': medicalGasAttributeId,
'deliveredQuantity': deliveredQuantity,
};
}
}

@ -0,0 +1,169 @@
import 'package:test_sa/models/base.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
class MedicalGasDataModel {
int? id;
String? requestNumber;
String? requestedBy;
String? requestedDate;
int? requestOrderTypeId;
String? requestOrderType;
int? itemTypeId;
String? itemType;
int? siteId;
String? site;
int? supplierId;
String? supplier;
String? contact;
String? email;
bool? isSubmitted;
String? requestOrderStatus;
bool? isPressureChecked;
bool? isInspectedGasLeak;
Lookup? requestStatus;
DateTime? deliveredDate;
String? deliveryNote;
/// non-nullable lists
List<MedicalGasRequestDetailModel> requestDetailDtos = [];
List<GenericAttachmentModel> deliveryNoteAttachmentDto = [];
MedicalGasDataModel({
this.id,
this.requestNumber,
this.requestedBy,
this.requestedDate,
this.requestOrderTypeId,
this.requestOrderType,
this.itemTypeId,
this.itemType,
this.siteId,
this.site,
this.requestStatus,
this.supplierId,
this.supplier,
this.contact,
this.email,
this.isSubmitted,
this.requestOrderStatus,
this.isPressureChecked,
this.isInspectedGasLeak,
this.deliveredDate,
this.deliveryNote,
List<MedicalGasRequestDetailModel>? requestDetailDtos,
List<GenericAttachmentModel>? deliveryNoteAttachmentDto,
}) {
this.requestDetailDtos = requestDetailDtos ?? [];
this.deliveryNoteAttachmentDto = deliveryNoteAttachmentDto ?? [];
}
MedicalGasDataModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
requestNumber = json['requestNumber'];
requestedBy = json['requestedBy'];
requestedDate = json['requestedDate'];
requestOrderTypeId = json['requestOrderTypeId'];
requestOrderType = json['requestOrderType'];
itemTypeId = json['itemTypeId'];
itemType = json['itemType'];
siteId = json['siteId'];
site = json['site'];
supplierId = json['supplierId'];
supplier = json['supplier'];
contact = json['contact'];
email = json['email'];
isSubmitted = json['isSubmitted'];
deliveryNote = json['deliveryNote'];
requestOrderStatus = json['requestOrderStatus'];
isPressureChecked = json['isPressureChecked'];
isInspectedGasLeak = json['isInspectedGasLeak'];
deliveredDate = json['deliveredDate'] != null ? DateTime.parse(json['deliveredDate']) : null;
requestStatus = json['requestOrderStatusDto'] != null ? Lookup.fromJson(json['requestOrderStatusDto']) : null;
if (json['requestDetailDtos'] != null) {
requestDetailDtos = [];
json['requestDetailDtos'].forEach((v) {
requestDetailDtos.add(MedicalGasRequestDetailModel.fromJson(v));
});
}
if (json['deliveryNoteAttachmentDto'] != null) {
deliveryNoteAttachmentDto = [];
json['deliveryNoteAttachmentDto'].forEach((v) {
deliveryNoteAttachmentDto.add(GenericAttachmentModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
return {
'id': id,
'requestNumber': requestNumber,
'requestedBy': requestedBy,
'requestedDate': requestedDate,
'requestOrderTypeId': requestOrderTypeId,
'requestOrderType': requestOrderType,
'itemTypeId': itemTypeId,
'itemType': itemType,
'siteId': siteId,
'site': site,
'supplierId': supplierId,
'deliveryNote': deliveryNote,
'supplier': supplier,
'contact': contact,
'email': email,
'isSubmitted': isSubmitted,
'requestOrderStatus': requestOrderStatus,
'isPressureChecked': isPressureChecked,
'isInspectedGasLeak': isInspectedGasLeak,
'deliveredDate': deliveredDate?.toIso8601String(),
'requestDetailDtos': requestDetailDtos.map((e) => e.toJson()).toList(),
'requestOrderStatusDto': requestStatus?.toJson(),
'deliveryNoteAttachmentDto': deliveryNoteAttachmentDto.map((e) => e.toJson()).toList(),
};
}
}
class MedicalGasRequestDetailModel extends Base {
int? id;
int? medicalGasAttributeId;
String? itemName;
String? oracleName;
String? oracleCode;
num? requestedQuantity;
num? deliveredQuantity;
MedicalGasRequestDetailModel({
this.id,
this.medicalGasAttributeId,
this.itemName,
this.oracleName,
this.oracleCode,
this.requestedQuantity,
this.deliveredQuantity,
}) : super(identifier: id?.toString(), name: itemName);
MedicalGasRequestDetailModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
medicalGasAttributeId = json['medicalGasAttributeId'];
itemName = json['itemName'];
identifier = id.toString();
name = itemName;
oracleName = json['oracleName'];
oracleCode = json['oracleCode'];
requestedQuantity = json['requestedQuantity'];
deliveredQuantity = json['deliveredQuantity'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'medicalGasAttributeId': medicalGasAttributeId,
'itemName': itemName,
'oracleName': oracleName,
'oracleCode': oracleCode,
'requestedQuantity': requestedQuantity,
'deliveredQuantity': deliveredQuantity,
};
}
}

@ -0,0 +1,87 @@
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/modules/loan_module/models/medical_department_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_supplier_model.dart';
class MedicalGasFormModel {
int? id;
int? requestOrderTypeId;
Lookup? orderType;
Lookup? itemType;
int? itemTypeId;
int? siteId;
Site? site;
MedicalDepartmentModel? department;
MedicalGasSupplierModel? supplier;
int? supplierId;
bool? isSubmitted;
List<MedicalGasFormDetailModel>? gasRequestDetail;
MedicalGasFormModel({
this.id,
this.requestOrderTypeId,
this.itemTypeId,
this.siteId,
this.supplierId,
this.supplier,
this.isSubmitted,
this.orderType,
this.itemType,
this.site,
this.department,
this.gasRequestDetail,
});
MedicalGasFormModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
requestOrderTypeId = json['requestOrderTypeId'];
itemTypeId = json['itemTypeId'];
siteId = json['siteId'];
supplierId = json['supplierId'];
isSubmitted = json['isSubmitted'];
if (json['gasRequestDetailDtos'] != null) {
gasRequestDetail = [];
json['gasRequestDetailDtos'].forEach((v) {
gasRequestDetail!.add(MedicalGasFormDetailModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
return {
'id': id ?? 0,
'requestOrderTypeId': orderType?.id,
'itemTypeId': itemType?.id,
'siteId': site?.id,
'supplierId': supplier?.id,
'isSubmitted': isSubmitted,
'gasRequestDetailDtos': gasRequestDetail?.map((e) => e.toJson()).toList(),
};
}
}
class MedicalGasFormDetailModel {
int? id;
int? medicalGasAttributeId;
num? requestedQuantity;
MedicalGasFormDetailModel({
this.id,
this.medicalGasAttributeId,
this.requestedQuantity,
});
MedicalGasFormDetailModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
medicalGasAttributeId = json['medicalGasAttributeId'];
requestedQuantity = json['requestedQuantity'];
}
Map<String, dynamic> toJson() {
return {
'id': id,
'medicalGasAttributeId': medicalGasAttributeId,
'requestedQuantity': requestedQuantity??0,
};
}
}

@ -0,0 +1,72 @@
import 'package:test_sa/models/base.dart';
class MedicalGasSupplierModel extends Base {
int? id;
String? supplier;
String? supplierEmail;
String? supplierContact;
List<AttributeInfo>? attributeInfo;
MedicalGasSupplierModel({this.id, this.supplier, this.supplierContact, this.supplierEmail, this.attributeInfo}) : super(identifier: id?.toString() ?? '', name: supplier);
MedicalGasSupplierModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
identifier = id?.toString() ?? '';
supplier = json['supplier'];
name=supplier;
supplierEmail = json['supplierEmail'];
supplierContact = json['supplierContact'];
if (json['attributeInfoDtos'] != null) {
attributeInfo = [];
json['attributeInfoDtos'].forEach((v) {
attributeInfo!.add(AttributeInfo.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
return {
'id': id,
'supplier': supplier,
'supplierEmail': supplierEmail,
'supplierContact': supplierContact,
'attributeInfoDtos': attributeInfo?.map((e) => e.toJson()).toList(),
};
}
}
class AttributeInfo {
int? id;
int? medicalGasAttributeId;
num? requestedQuantity;
String? itemName;
String? oracleName;
String? oracleCode;
AttributeInfo({this.id, this.medicalGasAttributeId, this.requestedQuantity, this.itemName, this.oracleName, this.oracleCode});
AttributeInfo.fromJson(Map<String, dynamic> json) {
id = json['id'];
medicalGasAttributeId = json['medicalGasAttributeId'];
requestedQuantity = json['requestedQuantity'];
itemName = json['itemName'];
oracleName = json['oracleName'];
oracleCode = json['oracleCode'];
}
Map<String, dynamic> toJson() {
//{
// "id": 0,
// "medicalGasAttributeId": 0,
// "requestedQuantity": 0
// }
return {
'id': id,
'medicalGasAttributeId': medicalGasAttributeId,
'requestedQuantity': requestedQuantity,
// 'oracleCode': oracleCode,
};
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class MedicalGasItemTypeProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.itemTypeLookUp);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -0,0 +1,119 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/delivery_notes_form_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_form_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_supplier_model.dart';
class MedicalGasInspectionProvider extends ChangeNotifier {
final pageItemNumber = 10;
final searchPageItemNumber = 10;
int pageNo = 1;
void reset() {
pageNo = 1;
stateCode = null;
}
int? stateCode;
bool isDetailLoading = false;
bool nextPage = false;
bool isLoading = false;
bool isGasInfoLoading = false;
Future<MedicalGasDataModel?> getMedicalGasById({int? requestId}) async {
MedicalGasDataModel? assetDeliveryDataModel = MedicalGasDataModel();
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(URLs.getMedicalGasById + "?medicalGasRequestId=$requestId");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
assetDeliveryDataModel = MedicalGasDataModel.fromJson(json.decode(response.body)["data"]);
} else {
assetDeliveryDataModel = null;
}
isLoading = false;
notifyListeners();
return assetDeliveryDataModel;
} catch (e) {
log("getMedicalGas details [error] : $e");
isLoading = false;
assetDeliveryDataModel = null;
notifyListeners();
return assetDeliveryDataModel;
}
}
Future<bool> saveMedicalGas({
required MedicalGasFormModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.addMedicalGasRequest, body: model.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
}
Future<MedicalGasSupplierModel?> getMedicalGasInfo({int? supplierId, int? itemTypeId, num? siteId}) async {
MedicalGasSupplierModel? supplierInfo;
Map<String, dynamic> payload = {"supplierId": supplierId, "itemTypeId": itemTypeId, "siteId": siteId};
try {
isGasInfoLoading = true;
notifyListeners();
final response = await ApiManager.instance.post("${URLs.getMedicalGasInfoBySupplier}", body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"];
supplierInfo = MedicalGasSupplierModel.fromJson(jsonData);
}
isGasInfoLoading = false;
notifyListeners();
return supplierInfo;
} catch (e) {
log("get Supplier List [error] : $e");
isGasInfoLoading = false;
notifyListeners();
return supplierInfo;
}
}
Future<bool> updatedDeliveryNotes({
required DeliveryNotesFormModel model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.updateDeliveryNote, body: model.toJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
} else {
isLoading = false;
notifyListeners();
return false;
}
} catch (error) {
isLoading = false;
notifyListeners();
return false;
}
}
}

@ -0,0 +1,34 @@
import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_supplier_model.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class MedicalGasSupplierProvider extends LoadingListNotifier<MedicalGasSupplierModel> {
@override
Future getData({int? id}) async {
loading = true;
notifyListeners();
Response response;
try {
response = await ApiManager.instance.get(URLs.getMedicalGasSupplierList);
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List listJson = json.decode(response.body)["data"];
items = listJson.map((supplier) => MedicalGasSupplierModel.fromJson(supplier)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
}
}

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
class MedicalGasOrderTypeProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
loading = true;
notifyListeners();
try {
Response response = await ApiManager.instance.get(URLs.orderTypeLookUp);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
List categoriesListJson = json.decode(response.body)["data"];
items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList();
}
loading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
loading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
}

@ -0,0 +1,288 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/delivery_notes_form_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
import 'package:test_sa/modules/medical_gas_inspection/providers/medical_gas_inspection_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/multiple_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
class UpdateDeliveryNotes extends StatefulWidget {
final MedicalGasDataModel? dataModel;
UpdateDeliveryNotes({Key? key, required this.dataModel}) : super(key: key);
@override
_UpdateDeliveryNotesState createState() {
return _UpdateDeliveryNotesState();
}
}
class _UpdateDeliveryNotesState extends State<UpdateDeliveryNotes> {
DeliveryNotesFormModel formModel = DeliveryNotesFormModel();
late MedicalGasInspectionProvider medicalGasInspectionProvider;
bool pressureTestAcknowledgement = false;
bool leakTestAcknowledgement = false;
List<MedicalGasRequestDetailModel> selectedItemList = [];
@override
void initState() {
super.initState();
medicalGasInspectionProvider = Provider.of<MedicalGasInspectionProvider>(context, listen: false);
_populateFormData();
}
@override
void dispose() {
super.dispose();
}
_populateFormData() {
if (widget.dataModel != null) {
MedicalGasDataModel dataModel = widget.dataModel!;
formModel = DeliveryNotesFormModel(
id: dataModel.id,
deliveredItemList: dataModel.requestDetailDtos,
isInspectedGasLeak: dataModel.isInspectedGasLeak,
isPressureChecked: dataModel.isPressureChecked,
deliveredDate: dataModel.deliveredDate,
attachments: dataModel.deliveryNoteAttachmentDto,
isSubmitted: dataModel.isSubmitted,
deliveryNoteNumber: dataModel.deliveryNote);
//Need to Confirm this condition
selectedItemList = dataModel.requestDetailDtos.where((item) => item.deliveredQuantity != null && item.deliveredQuantity! > 0).toList();
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const DefaultAppBar(
title: "Upload Delivery Note",
// onWillPopScope: () {
// _update(context: context);
// },
),
body: SafeArea(
child: Column(
children: [
ListView(
padding: const EdgeInsets.all(16),
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ADatePicker(
label: "Delivered Date",
hideShadow: true,
backgroundColor: AppColor.fieldBgColor(context),
from: DateTime.now().subtract(const Duration(days: 365 * 3)),
date: formModel.deliveredDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
if (selectedTime != null) {
formModel.deliveredDate = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
setState(() {});
}
});
},
),
16.height,
MultipleItemDropDownMenu<MedicalGasRequestDetailModel, NullableLoadingProvider>(
context: context,
showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
showCancel: true,
requestById: context.userProvider.user?.clientId,
title: 'Delivered Items'.addTranslation,
staticData: formModel.deliveredItemList,
initialValue: selectedItemList,
onSelect: (value) {
if ((value ?? []).isNotEmpty) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
setState(() {
selectedItemList = value ?? [];
});
});
}
},
),
if (selectedItemList.isNotEmpty) ...[
8.height,
ListView.separated(
separatorBuilder: (_, __) => 12.height,
itemCount: selectedItemList.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
MedicalGasRequestDetailModel model = selectedItemList[index];
return AppTextFormField(
labelText: '${model.name} (Req Qty =${model.requestedQuantity})',
hintText: 'Enter Delivered Quantity'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.deliveredQuantity != null ? model.deliveredQuantity?.toInt().toString() : '',
textAlign: TextAlign.center,
enable: true,
textInputType: TextInputType.number,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
if (value.isNotEmpty) {
model.deliveredQuantity = double.tryParse(value);
}
},
style: Theme.of(context).textTheme.titleMedium,
);
},
)
],
16.height,
AppTextFormField(
initialValue: formModel.deliveryNoteNumber,
labelText: "Delivery Notes",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
textInputType: TextInputType.multiline,
makeMultiLinesNull: true,
onChange: (value) {
formModel.deliveryNoteNumber = value;
},
),
16.height,
AttachmentPicker(
label: 'Upload Attachment',
attachment: formModel.attachments,
buttonColor: AppColor.primary10,
// showAsListView: true,
onlyImages: false,
buttonIcon: 'attachment_icon'.toSvgAsset(
color: AppColor.primary10,
),
),
16.height,
//should create a reusable widget.
Row(
children: [
Checkbox(
value: formModel.isPressureChecked,
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
activeColor: AppColor.blueStatus(context),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (value) {
setState(() {
formModel.isPressureChecked = value!;
});
}),
12.width,
"I Acknowledge that the received medical gases cylinders have been tested for pressure."
.addTranslation
.bodyText(context)
.custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120)
.expanded,
],
),
8.height,
Row(
// mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Checkbox(
value: formModel.isInspectedGasLeak,
visualDensity: const VisualDensity(horizontal: -4.0, vertical: -4.0),
activeColor: AppColor.blueStatus(context),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onChanged: (value) {
setState(() {
formModel.isInspectedGasLeak = value!;
});
}),
12.width,
"I Acknowledge that the received medical gases cylinders have been inspected for leak test."
.addTranslation
.bodyText(context)
.custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral120)
.expanded,
],
),
],
).toShadowContainer(context, padding: 12),
],
).expanded,
FooterActionButton.footerContainer(
context: context,
child: Row(
children: [
AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Save'.addTranslation,
onPressed: () {
_update(context: context);
},
// buttonColor: AppColor.primary10,
).expanded,
8.width,
AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Submit'.addTranslation,
onPressed: () {
_update(context: context, isSubmitted: true);
},
// buttonColor: AppColor.primary10,
).expanded,
],
),
),
],
),
));
// .handlePopScope(
// cxt: context,
// onSave: () {
// _update(context: context);
// });
}
void _update({required BuildContext context, bool isSubmitted = false}) async {
formModel.gasDeliveredQuantityDtos = [];
formModel.isSubmitted = isSubmitted;
for (var item in selectedItemList) {
formModel.gasDeliveredQuantityDtos.add(GasDeliveredQuantityModel(
id: widget.dataModel != null ? item.id : 0,
medicalGasAttributeId: item.medicalGasAttributeId ?? item.id,
deliveredQuantity: item.deliveredQuantity,
));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await medicalGasInspectionProvider.updatedDeliveryNotes(model: formModel).then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context, true);
}
});
}
}

@ -69,7 +69,7 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData),
requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty
requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms != null && requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty
? Column(
children: [
8.height,

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
@ -119,6 +121,8 @@ class AppColor {
return orange60;
case "high priority":
return white10;
case "emergency":
return white10;
case "yes":
return white10;
case "low priority":
@ -134,6 +138,8 @@ class AppColor {
switch ((status).toLowerCase()) {
case "in progress":
return white936;
case "waiting for delivery":
return white936;
case "new":
return primary63;
case "open":
@ -193,6 +199,14 @@ class AppColor {
return red30;
case "returned":
return red30;
case "waiting for delivery":
return orange30;
case "waiting for medical gas specialist review":
return orange30;
case "reviewed":
return orange30;
case "returned for correction":
return orange30;
default:
return Colors.white;
}
@ -210,6 +224,8 @@ class AppColor {
return greenStatus(context);
case "high priority":
return redStatus(context);
case "emergency":
return redStatus(context);
case "yes":
return redStatus(context);
case "low priority":

@ -13,10 +13,11 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
final List<Widget>? actions;
final Function? onBackPress;
final bool showHomeActionButton;
final bool showBackButton;
final VoidCallback? onWillPopScope;
final TextStyle? titleStyle;
const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions,this.titleStyle, this.showHomeActionButton = false, Key? key}) : super(key: key);
const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions,this.titleStyle, this.showHomeActionButton = false, this.showBackButton = true, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -42,6 +43,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
titleSpacing: 16,
title: Row(
children: [
if(showBackButton)
const Icon(Icons.arrow_back_ios).onPress(() {
if (onWillPopScope != null) {
showDialog(

@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/enum_extensions.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_text_style.dart';
@ -32,6 +33,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
final int? requestById;
final String? Function(T?)? validator;
final AutovalidateMode? autovalidateMode;
final DropDownMatchType matchBy;
/// To use a static data (without calling API)
/// just send [NullableLoadingProvider] as generic data type and fill the [staticData]
@ -55,6 +57,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
this.requestById,
this.validator,
this.autovalidateMode,
this.matchBy = DropDownMatchType.identifier,
}) : super(key: key);
@override
@ -67,41 +70,97 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
@override
void initState() {
super.initState();
if (X != NullableLoadingProvider) {
provider = Provider.of<X>(widget.context);
}
if (widget.initialValue != null) {
final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
if (result?.isNotEmpty ?? false) _selectedItem = result!.first as T?;
if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
widget.onSelect!(_selectedItem); // Non-null assertion after null check
}
if (widget.initialValue == null) return;
final List<T>? items = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.cast<T>();
if (items == null || items.isEmpty) return;
final Iterable<T> matches = items.where((e) => _isSameItem(e, widget.initialValue!));
if (matches.isNotEmpty) {
_selectedItem = matches.first;
} else {
_selectedItem = null;
}
if (widget.onSelect != null && !_isSameItem(widget.initialValue!, _selectedItem ?? widget.initialValue!)) {
widget.onSelect!(_selectedItem);
}
super.initState();
}
// @override
// void initState() {
// if (X != NullableLoadingProvider) {
// provider = Provider.of<X>(widget.context);
// }
// if (widget.initialValue != null) {
// final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
// if (result?.isNotEmpty ?? false) _selectedItem = result!.first as T?;
// if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
// widget.onSelect!(_selectedItem); // Non-null assertion after null check
// }
// }
// super.initState();
// }
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(fn);
}
bool _isSameItem(Base a, Base b) {
switch (widget.matchBy) {
case DropDownMatchType.name:
return (a.name ?? '') == (b.name ?? '');
case DropDownMatchType.identifier:
default:
return (a.identifier ?? '') == (b.identifier ?? '');
}
}
// @override
// void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) {
// if (widget.initialValue != null) {
// final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
//
// if (result?.isNotEmpty ?? false) {
// _selectedItem = result?.first as T?;
// } else {
// _selectedItem = null;
// }
// if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
// widget.onSelect!(_selectedItem); // Non-null assertion after null check
// }
// } else {
// _selectedItem = null;
// }
// super.didUpdateWidget(oldWidget);
// }
@override
void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) {
if (widget.initialValue != null) {
final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
super.didUpdateWidget(oldWidget);
if (result?.isNotEmpty ?? false) {
_selectedItem = result?.first as T?;
} else {
_selectedItem = null;
}
if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
widget.onSelect!(_selectedItem); // Non-null assertion after null check
}
} else {
if (oldWidget.initialValue == widget.initialValue) return;
if (widget.initialValue == null) {
_selectedItem = null;
return;
}
final List<T>? items = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.cast<T>();
T? matchedItem;
if (items != null && items.isNotEmpty) {
final Iterable<T> matches = items.where((e) => _isSameItem(e, widget.initialValue!));
if (matches.isNotEmpty) matchedItem = matches.first;
}
_selectedItem = matchedItem;
if (widget.onSelect != null && !_isSameItem(widget.initialValue!, _selectedItem ?? widget.initialValue!)) {
widget.onSelect!(_selectedItem);
}
super.didUpdateWidget(oldWidget);
}
@override
@ -148,11 +207,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
children: [
Text(
widget.title,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: context.isDark
? null
: widget.titleTextColor ?? AppColor.neutral20,
fontWeight: FontWeight.w500),
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : widget.titleTextColor ?? AppColor.neutral20, fontWeight: FontWeight.w500),
),
DropdownButton<T>(
value: _selectedItem,

@ -13,6 +13,7 @@ import 'package:test_sa/modules/cm_module/create_cm_request.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/create_equipment_internal_audit_form.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart';
import 'package:test_sa/modules/loan_module/pages/create_loan_request_page.dart';
import 'package:test_sa/modules/medical_gas_inspection/create_medical_gas_request_page.dart';
import 'package:test_sa/modules/tm_module/device_transfer/create_device_transfer_request.dart';
import 'package:test_sa/modules/tm_module/tasks/create_task_view.dart';
import 'package:test_sa/modules/traf_module/create_traf_request_page.dart';
@ -121,8 +122,13 @@ class CreateRequestModel {
if (Provider.of<SettingProvider>(context, listen: false).engineerCanCreateCM) {
list.add(CreateRequestModel(context.translation.correctiveMaintenance, "add_icon", CreateCMRequest.id));
}
//TODO uncommit this to enable task.
list.add(CreateRequestModel(context.translation.task, "add_icon", CreateTaskView.id));
//Need to add check from permission Api.
// if (Provider.of<SettingProvider>(context, listen: false).engineerCanCreateCM) {
list.add(CreateRequestModel('Medical Gas'.addTranslation, "add_icon", CreateMedicalGasRequestPage.id));
// }
} else {
list.add(CreateRequestModel(context.translation.correctiveMaintenance, "add_icon", CreateCMRequest.id));
list.add(CreateRequestModel(context.translation.gasRefill, "add_icon", GasRefillRequestForm.routeName));

@ -68,7 +68,9 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
if (context.userProvider.isEngineer) {
requestsList.add(Request(10, 'Equipment Internal Audit'));
requestsList.add(Request(11, 'System Internal Audit'));
requestsList.add(Request(12, "Asset Delivery"));
//Need to be added for new user role commissioning engineer
requestsList.add(Request(13, "Asset Delivery"));
requestsList.add(Request(14, "Medical Gas Inspection"));
}
requestsList.add(Request(12, "Loan Equipment"));

@ -6,6 +6,7 @@ import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_a
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_item_view.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_item_view.dart';
import 'package:test_sa/modules/loan_module/pages/loan_equipment_item_view.dart';
import 'package:test_sa/modules/medical_gas_inspection/medical_gas_inspection_item_view.dart';
import 'package:test_sa/modules/tm_module/tasks/task_request_item_view.dart';
import 'package:test_sa/modules/traf_module/traf_request_item_view.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@ -78,6 +79,8 @@ class RequestPaginatedListview extends StatelessWidget {
return LoanEquipmentItemView(requestData: request);
case 13:
return AssetDeliveryItemView(requestData: request);
case 14:
return MedicalGasInspectionItemView(requestData: request);
default:
return Container(
height: 100,

@ -11,6 +11,7 @@ import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_a
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_item_view.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_item_view.dart';
import 'package:test_sa/modules/loan_module/pages/loan_equipment_item_view.dart';
import 'package:test_sa/modules/medical_gas_inspection/medical_gas_inspection_item_view.dart';
import 'package:test_sa/modules/tm_module/tasks/task_request_item_view.dart';
import 'package:test_sa/modules/traf_module/traf_request_item_view.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@ -70,11 +71,12 @@ class RequestItemViewList extends StatelessWidget {
return EquipmentInternalAuditItemView(requestDetails: list[index]);
case 11:
return SystemInternalAuditItemView(requestDetails: list[index]);
//Need to use correct value ....
case 12:
return AssetDeliveryItemView(requestDetails: list[index]);
case 12:
return LoanEquipmentItemView(requestDetails: list[index]);
case 13:
return AssetDeliveryItemView(requestDetails: list[index]);
case 14:
return MedicalGasInspectionItemView(requestDetails: list[index]);
default:
Container(

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/text_extensions.dart';

Loading…
Cancel
Save