Merge branch 'design_3.0_medical_gas' into design_3.0_demo_module
# Conflicts: # lib/controllers/api_routes/urls.dart # lib/main.dart # lib/modules/medical_gas_inspection/create_medical_gas_request_page.dart # lib/modules/medical_gas_inspection/medical_gas_inspection_detail_page.dart # lib/new_views/pages/land_page/create_request_type_bottom_sheet.dartdesign_3.0_demo_module
commit
9eaae96c84
File diff suppressed because one or more lines are too long
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12.8288 8.68721C13.6685 5.56426 11.8033 2.34682 8.65315 1.50569C6.30567 0.878883 3.91271 1.75062 2.49819 3.52772C2.39645 3.65553 2.41199 3.83848 2.5275 3.954L3.19897 4.62547C3.28768 4.71417 3.29587 4.86091 3.28768 4.99544C3.26581 5.35459 2.95694 5.62802 2.59779 5.60615L0.962417 5.50659C0.755718 5.49401 0.567312 5.38391 0.454883 5.21001C0.342453 5.03611 0.319393 4.81911 0.392762 4.62547C1.68326 1.21934 5.3844 -0.715769 8.98929 0.24678C12.829 1.27203 15.1157 5.20026 14.0871 9.02556C13.0588 12.85 9.10916 15.1116 5.27027 14.0866C2.41806 13.325 0.424623 10.963 0.00755845 8.23213C-0.0467641 7.87644 0.197544 7.54406 0.553237 7.48974C0.90893 7.43541 1.24131 7.67972 1.29564 8.03541C1.63682 10.2694 3.26872 12.2035 5.60641 12.8277C8.75742 13.669 11.9888 11.811 12.8288 8.68721Z" fill="#5A5E79"/>
|
||||||
|
<path d="M7.83333 4.5C7.83333 4.13181 7.53486 3.83333 7.16667 3.83333C6.79848 3.83333 6.5 4.13181 6.5 4.5V7.16667C6.5 7.34348 6.57024 7.51305 6.69526 7.63807L8.0286 8.9714C8.28895 9.23175 8.71106 9.23175 8.9714 8.9714C9.23175 8.71105 9.23175 8.28894 8.9714 8.0286L7.83333 6.89052V4.5Z" fill="#5A5E79"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.10204 2C9.65432 1.99901 10.1012 1.55048 10.1002 0.998201C10.0992 0.445917 9.65072 -0.000991314 9.09843 1.65146e-06C7.29011 0.00325987 5.81796 0.025199 4.63875 0.216071C3.43031 0.411675 2.4215 0.799884 1.61095 1.61043C0.735156 2.48623 0.353343 3.59229 0.173677 4.92863C-4.21107e-05 6.22073 -2.31424e-05 7.86717 5.77522e-07 9.92565V10.0738C-2.38577e-05 12.1323 -4.33922e-05 13.7787 0.173675 15.0709C0.353341 16.4072 0.735154 17.5133 1.61095 18.3891C2.48675 19.2648 3.59281 19.6467 4.92915 19.8263C6.22125 20 7.86769 20 9.92618 20H10.0744C12.1328 20 13.7793 20 15.0714 19.8263C16.4077 19.6467 17.5138 19.2649 18.3896 18.3891C19.2001 17.5785 19.5883 16.5697 19.7839 15.3613C19.9748 14.182 19.9967 12.7099 20 10.9016C20.001 10.3493 19.5541 9.90077 19.0018 9.89977C18.4495 9.89878 18.001 10.3457 18 10.898C17.9967 12.7393 17.9705 14.0476 17.8096 15.0417C17.6534 16.0066 17.3862 16.564 16.9754 16.9748C16.5331 17.4171 15.9194 17.6943 14.8049 17.8442C13.6616 17.9979 12.1499 18 10.0003 18C7.85061 18 6.33897 17.9979 5.19564 17.8442C4.08108 17.6943 3.46742 17.4171 3.02517 16.9748C2.58291 16.5326 2.30569 15.9189 2.15584 14.8044C2.00212 13.661 2 12.1494 2 9.99974C2 7.85009 2.00213 6.33845 2.15584 5.19512C2.30569 4.08056 2.58291 3.4669 3.02517 3.02464C3.43598 2.61383 3.99343 2.34656 4.95832 2.19038C5.95244 2.02946 7.26069 2.00332 9.10204 2Z" fill="#3DA5E5"/>
|
||||||
|
<path d="M14.6278 0.059696C15.5062 0.00814169 17.2561 -0.0671266 18.3023 0.118154C18.7322 0.194283 19.1066 0.401014 19.3861 0.698737L19.3948 0.708123C19.6424 0.975433 19.8141 1.31484 19.882 1.69821C20.067 2.74418 19.9919 4.49371 19.9404 5.37215C19.8724 6.53179 18.4836 7.007 17.698 6.22141L16.4671 4.99058L13.7317 7.70515C13.712 7.72477 13.6916 7.7434 13.6707 7.76105L9.70554 11.7087C9.31415 12.0983 8.68099 12.0969 8.29133 11.7055C7.90167 11.3142 7.90307 10.681 8.29446 10.2913L12.149 6.45379C12.1907 6.38574 12.2412 6.32154 12.3003 6.26282L15.0302 3.55371L13.7786 2.3021C12.9931 1.51658 13.4682 0.127754 14.6278 0.059696Z" fill="#3DA5E5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.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/attachment_view.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_type_provider.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/views/widgets/loaders/no_data_found.dart';
|
||||||
|
|
||||||
|
class HelperFunction {
|
||||||
|
static void attachmentTap({required BuildContext context, bool viewOnly = false, required AssetDeliveryProvider assetDeliveryProvider, required dynamic deliveryTableItemId}) async {
|
||||||
|
Lookup? result;
|
||||||
|
result = await showAttachmentTypeBottomSheet(context);
|
||||||
|
List<GenericAttachmentModel> list = [];
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (_) => const AppLazyLoading(),
|
||||||
|
);
|
||||||
|
list = await assetDeliveryProvider.getAttachments(tableItemId: deliveryTableItemId, attachmentType: result.value);
|
||||||
|
Navigator.pop(context);
|
||||||
|
// if (list.isNotEmpty) {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => AssetDeliveryAttachmentView(
|
||||||
|
tableItemId: deliveryTableItemId,
|
||||||
|
attachmentType: result!.value,
|
||||||
|
viewOnly: viewOnly,
|
||||||
|
attachmentList: list,
|
||||||
|
)));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Lookup?> showAttachmentTypeBottomSheet(BuildContext context) {
|
||||||
|
return showModalBottomSheet<Lookup?>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
|
),
|
||||||
|
builder: (_) {
|
||||||
|
return SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProvider>(
|
||||||
|
context: context,
|
||||||
|
title: context.translation.reason,
|
||||||
|
onSelect: (value) {
|
||||||
|
Navigator.pop(context, value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
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) {
|
||||||
|
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 = {};
|
||||||
|
|
||||||
|
data['id'] = id ?? 0;
|
||||||
|
data['qty'] = quantity;
|
||||||
|
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,53 @@
|
|||||||
|
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
|
||||||
|
|
||||||
|
class CostCenterSerialNoFormModel {
|
||||||
|
List<CostCenterModel>? costCenters;
|
||||||
|
List<SerialNoModel>? serialNos;
|
||||||
|
|
||||||
|
CostCenterSerialNoFormModel({
|
||||||
|
this.costCenters,
|
||||||
|
this.serialNos,
|
||||||
|
});
|
||||||
|
|
||||||
|
// From JSON
|
||||||
|
CostCenterSerialNoFormModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
if (json['costCenters'] != null) {
|
||||||
|
costCenters = List<CostCenterModel>.from((json['costCenters'] as List).map((e) => CostCenterModel.fromJson(e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json['serialNos'] != null) {
|
||||||
|
serialNos = List<SerialNoModel>.from((json['serialNos'] as List).map((e) => SerialNoModel.fromJson(e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To JSON
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'costCenters': costCenters?.map((e) => e.toJson()).toList() ?? [],
|
||||||
|
'serialNos': serialNos?.map((e) => e.toJson()).toList() ?? [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SerialNoModel {
|
||||||
|
int? id;
|
||||||
|
String? serialNo;
|
||||||
|
SerialNoModel({
|
||||||
|
this.id,
|
||||||
|
this.serialNo,
|
||||||
|
});
|
||||||
|
SerialNoModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'] ?? json['costCenterId'];
|
||||||
|
serialNo = json['serialNo'];
|
||||||
|
}
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id ?? 0;
|
||||||
|
data['serialNo'] = serialNo;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import 'package:test_sa/modules/asset_delivery_module/models/inspection_person_model.dart';
|
||||||
|
|
||||||
|
class DeliveryInspectionFormModel {
|
||||||
|
int? assetDeliveryExternalDeliveryId;
|
||||||
|
String? deliveryInspectionInspectedBy;
|
||||||
|
InspectionPersonModel? inspectedByModel;
|
||||||
|
InspectionPersonModel? approvedByModel;
|
||||||
|
InspectionPersonModel? thirdApprovalModel;
|
||||||
|
DateTime? deliveryInspectionInspectedDateFrom;
|
||||||
|
DateTime? deliveryInspectionInspectedDateTo;
|
||||||
|
num? totalTime;
|
||||||
|
String? deliveryInspectionApprovedBy;
|
||||||
|
|
||||||
|
DeliveryInspectionFormModel({
|
||||||
|
this.assetDeliveryExternalDeliveryId,
|
||||||
|
this.deliveryInspectionInspectedBy,
|
||||||
|
this.inspectedByModel,
|
||||||
|
this.approvedByModel,
|
||||||
|
this.thirdApprovalModel,
|
||||||
|
this.deliveryInspectionInspectedDateFrom,
|
||||||
|
this.deliveryInspectionInspectedDateTo,
|
||||||
|
this.totalTime,
|
||||||
|
this.deliveryInspectionApprovedBy,
|
||||||
|
});
|
||||||
|
|
||||||
|
DeliveryInspectionFormModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
assetDeliveryExternalDeliveryId = json['assetDeliveryExternalDeliveryId'];
|
||||||
|
deliveryInspectionInspectedBy = json['deliveryInspectionInspectedBy'];
|
||||||
|
inspectedByModel = InspectionPersonModel(name: json['deliveryInspectionInspectedBy'], email: json['deliveryInspectionInspectedByEmail'], signature: json['deliveryInspectionInspectedBySignature']);
|
||||||
|
approvedByModel = InspectionPersonModel(name: json['deliveryInspectionApprovedBy'], email: json['deliveryInspectionApprovedByEmail'], signature: json['deliveryInspectionApprovedBySignature']);
|
||||||
|
thirdApprovalModel =
|
||||||
|
InspectionPersonModel(name: json['deliveryInspectionThirdApproverBy'], email: json['deliveryInspectionThirdApproverByEmail'], signature: json['deliveryInspectionThirdApproverBySignature']);
|
||||||
|
deliveryInspectionInspectedDateFrom = json['deliveryInspectionInspectedDateFrom'] != null ? DateTime.tryParse(json['deliveryInspectionInspectedDateFrom']) : null;
|
||||||
|
deliveryInspectionInspectedDateTo = json['deliveryInspectionInspectedDateTo'] != null ? DateTime.tryParse(json['deliveryInspectionInspectedDateTo']) : null;
|
||||||
|
totalTime = json['totalTime'];
|
||||||
|
deliveryInspectionApprovedBy = json['deliveryInspectionApprovedBy'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO need to set payload..
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'assetDeliveryExternalDeliveryId': assetDeliveryExternalDeliveryId,
|
||||||
|
'deliveryInspectionInspectedDateFrom': deliveryInspectionInspectedDateFrom?.toIso8601String(),
|
||||||
|
'deliveryInspectionInspectedDateTo': deliveryInspectionInspectedDateTo?.toIso8601String(),
|
||||||
|
'totalTime': totalTime,
|
||||||
|
'deliveryInspectionInspectedBy': inspectedByModel?.name,
|
||||||
|
"deliveryInspectionInspectedBySignature": inspectedByModel?.signature,
|
||||||
|
"deliveryInspectionInspectedByEmail": inspectedByModel?.email,
|
||||||
|
'deliveryInspectionApprovedBy': approvedByModel?.name,
|
||||||
|
"deliveryInspectionApprovedBySignature": approvedByModel?.signature,
|
||||||
|
"deliveryInspectionApprovedByEmail": approvedByModel?.email,
|
||||||
|
"deliveryInspectionThirdApproverBy": thirdApprovalModel?.name,
|
||||||
|
"deliveryInspectionThirdApproverBySignature": thirdApprovalModel?.signature,
|
||||||
|
"deliveryInspectionThirdApproverByEmail": thirdApprovalModel?.email,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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,15 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class InspectionPersonModel {
|
||||||
|
String? name;
|
||||||
|
String? email;
|
||||||
|
String? signature;
|
||||||
|
Uint8List? localSignature;
|
||||||
|
|
||||||
|
InspectionPersonModel({
|
||||||
|
this.name,
|
||||||
|
this.email,
|
||||||
|
this.signature,
|
||||||
|
this.localSignature,
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -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'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 ?? 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
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/asset_delivery_module/pages/asset_delivery_page.dart';
|
||||||
|
import 'package:test_sa/modules/asset_inventory_module/pages/asset_inventory_page.dart';
|
||||||
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||||
|
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||||
|
|
||||||
|
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
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (requestData != null) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
8.height,
|
||||||
|
(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(
|
||||||
|
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: (_) => AssetDeliveryPage(
|
||||||
|
requestId: requestData!.id!,
|
||||||
|
poInternal: requestData?.poInternal,
|
||||||
|
poExternal: requestData?.poExternal,
|
||||||
|
)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
8.height,
|
||||||
|
(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,
|
||||||
|
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: (_) => AssetDeliveryPage(
|
||||||
|
requestId: requestDetails!.id!,
|
||||||
|
poInternal: requestDetails?.poInternal,
|
||||||
|
poExternal: requestDetails?.poExternal,
|
||||||
|
)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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,86 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.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/delivery_line_model.dart';
|
||||||
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||||
|
|
||||||
|
class AssetDeliveryLineCard extends StatelessWidget {
|
||||||
|
DeliveryLineModel deliveryLineModel;
|
||||||
|
bool isViewOnly;
|
||||||
|
VoidCallback? editPress;
|
||||||
|
bool isTechnical;
|
||||||
|
|
||||||
|
AssetDeliveryLineCard({
|
||||||
|
super.key,
|
||||||
|
required this.isViewOnly,
|
||||||
|
required this.deliveryLineModel,
|
||||||
|
this.isTechnical = false,
|
||||||
|
this.editPress,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
//need to check this @waseem.
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'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!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Item No: ${deliveryLineModel.itemNumber ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Item Description: ${deliveryLineModel.itemDescription ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'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(
|
||||||
|
'Measure Unit: ${deliveryLineModel.unitOfMeasure ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Unit price: ${deliveryLineModel.unitPrice ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Line Type: ${deliveryLineModel.lineType ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Total: ${deliveryLineModel.total ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20, padding: 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,364 @@
|
|||||||
|
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/models/asset_delivery_data_model.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_stage_tab_page.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_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_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';
|
||||||
|
|
||||||
|
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
|
||||||
|
State<AssetDeliveryPage> createState() => _AssetDeliveryPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AssetDeliveryPageState extends State<AssetDeliveryPage> {
|
||||||
|
AssetDeliveryDataModel? dataModel;
|
||||||
|
AssetDeliveryProvider? assetDeliveryProvider;
|
||||||
|
bool loading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
getDetailsById();
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getDetailsById() async {
|
||||||
|
setState(() {
|
||||||
|
loading = true;
|
||||||
|
});
|
||||||
|
final futures = <Future>[
|
||||||
|
assetDeliveryProvider!.getAssetDeliveryDetailById(requestId: widget.requestId).then((value) => dataModel = value),
|
||||||
|
assetDeliveryProvider!.getAssetDeliveryTableListById(requestId: widget.requestId),
|
||||||
|
];
|
||||||
|
|
||||||
|
await Future.wait(futures);
|
||||||
|
setState(() {
|
||||||
|
loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Asset Delivery'.addTranslation,
|
||||||
|
onBackPress: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
body: Consumer<AssetDeliveryProvider>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
final dataModel = provider.assetDeliveryDataModel;
|
||||||
|
if (loading) {
|
||||||
|
return const CircularProgressIndicator(color: AppColor.primary10).center;
|
||||||
|
}
|
||||||
|
if (dataModel == null) {
|
||||||
|
return const NoDataFound().center;
|
||||||
|
}
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
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),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle infoTextStyle(context) => AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120);
|
||||||
|
|
||||||
|
Widget requestDetailCard(BuildContext context) {
|
||||||
|
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(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
// Checkbox(
|
||||||
|
// value: dataModel!.isHMG,
|
||||||
|
// activeColor: AppColor.neutral120,
|
||||||
|
// materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
// visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
|
||||||
|
// onChanged: (value) {},
|
||||||
|
// ),
|
||||||
|
// 8.width,
|
||||||
|
// Text(
|
||||||
|
// 'HMG'.addTranslation,
|
||||||
|
// style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
8.height,
|
||||||
|
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.'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
//Need to verify this with backend ...
|
||||||
|
// widget.poInternal?? '-',
|
||||||
|
Text(
|
||||||
|
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,
|
||||||
|
Text(
|
||||||
|
'Warranty Period'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
dataModel?.warrentyPeriod != null ? dataModel!.warrentyPeriod.toString() : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
'Payment Term'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
dataModel?.paymentTerm != null ? dataModel!.paymentTerm!.name.toString() : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
|
||||||
|
Text(
|
||||||
|
'Payment Terms Amount'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
dataModel?.paymentTermAmount != null ? dataModel!.paymentTermAmount.toString() : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
//Removed as request by Ahmed backend...
|
||||||
|
// Text(
|
||||||
|
// 'EDD (Estimated Delivery Date)'.addTranslation,
|
||||||
|
// style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
// ),
|
||||||
|
// 8.height,
|
||||||
|
// Text(
|
||||||
|
// dataModel?.edd != null ? dataModel!.edd!.toAssetDetailsFormat : '-',
|
||||||
|
// style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
// ),
|
||||||
|
// 8.height,
|
||||||
|
Text(
|
||||||
|
'Total'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
dataModel?.total != null ? dataModel!.total.toString() : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
'Total Invoice'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
dataModel?.totalInvoice != null ? dataModel!.totalInvoice.toString() : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
// ),
|
||||||
|
// ));
|
||||||
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (_) => AssetDeliveryStageTabPage(
|
||||||
|
title: 'Delivery Inspection'.addTranslation,
|
||||||
|
detailWidget: DeliveryInspectionFormView(
|
||||||
|
deliveryTableModel: model,
|
||||||
|
requestModel: dataModel,
|
||||||
|
),
|
||||||
|
tableId: model.id,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onViewHistoryTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => AssetDeliveryHistoryLogView(
|
||||||
|
tableItemId: model.id,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
import 'package:flutter/material.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/modules/asset_delivery_module/pages/history_log_view.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 AssetDeliveryStageTabPage extends StatefulWidget {
|
||||||
|
String title;
|
||||||
|
Widget detailWidget;
|
||||||
|
int? tableId;
|
||||||
|
|
||||||
|
AssetDeliveryStageTabPage({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.detailWidget,
|
||||||
|
this.tableId,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_AssetDeliveryStageTabPageState createState() {
|
||||||
|
return _AssetDeliveryStageTabPageState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AssetDeliveryStageTabPageState extends State<AssetDeliveryStageTabPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: widget.title,
|
||||||
|
),
|
||||||
|
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(
|
||||||
|
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)),
|
||||||
|
tabs: [
|
||||||
|
Tab(text: context.translation.details, height: 57.toScreenHeight),
|
||||||
|
Tab(text: context.translation.historyLogs, height: 57.toScreenHeight),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 12.height,
|
||||||
|
TabBarView(
|
||||||
|
children: [
|
||||||
|
widget.detailWidget,
|
||||||
|
AssetDeliveryHistoryLogView(
|
||||||
|
tableItemId: widget.tableId,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).expanded,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String getPageTitle({AssetDeliveryStageEnum? deliveryStage}) {
|
||||||
|
if (deliveryStage == AssetDeliveryStageEnum.deliveryInspection) {
|
||||||
|
return 'Delivery Inspection'.addTranslation;
|
||||||
|
}
|
||||||
|
if (deliveryStage == AssetDeliveryStageEnum.technicalInspection) {
|
||||||
|
return 'Technical Inspection'.addTranslation;
|
||||||
|
}
|
||||||
|
if (deliveryStage == AssetDeliveryStageEnum.endUserAcceptance) {
|
||||||
|
return 'End-User Acceptance'.addTranslation;
|
||||||
|
} else {
|
||||||
|
return 'Details'.addTranslation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
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_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 {
|
||||||
|
AssetDeliveryTableModel deliveryTableModel;
|
||||||
|
VoidCallback onCardTap;
|
||||||
|
VoidCallback onViewHistoryTap;
|
||||||
|
|
||||||
|
AssetDeliveryTableCard({
|
||||||
|
super.key,
|
||||||
|
required this.deliveryTableModel,
|
||||||
|
required this.onCardTap,
|
||||||
|
required this.onViewHistoryTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: deliveryTableModel.status?.name,
|
||||||
|
textColor: AppColor.neutral50,
|
||||||
|
backgroundColor: AppColor.orange30,
|
||||||
|
),
|
||||||
|
// Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
// children: [
|
||||||
|
// StatusLabel(
|
||||||
|
// label: deliveryTableModel.status?.name,
|
||||||
|
// textColor: AppColor.neutral50,
|
||||||
|
// backgroundColor: AppColor.orange30,
|
||||||
|
// ),
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// 'history_icon'.toSvgAsset(height: 14, width: 14),
|
||||||
|
// 8.width,
|
||||||
|
// Text(
|
||||||
|
// 'View History'.addTranslation,
|
||||||
|
// style: AppTextStyles.bodyText.copyWith(color: AppColor.primary10),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ).onPress(() {
|
||||||
|
// onViewHistoryTap();
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
'Delivery Number: ${deliveryTableModel.number ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Delivery Amount: ${deliveryTableModel.deliveryAmount ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Invoice Amount: ${deliveryTableModel.invoiceAmount ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20).onPress(() {
|
||||||
|
onCardTap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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,152 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
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/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/files_list.dart';
|
||||||
|
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||||
|
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
|
||||||
|
|
||||||
|
class AssetDeliveryAttachmentView extends StatefulWidget {
|
||||||
|
final int? tableItemId;
|
||||||
|
final int? attachmentType;
|
||||||
|
bool viewOnly = false;
|
||||||
|
final List<GenericAttachmentModel> attachmentList;
|
||||||
|
|
||||||
|
AssetDeliveryAttachmentView({
|
||||||
|
super.key,
|
||||||
|
required this.attachmentList,
|
||||||
|
this.viewOnly=false,
|
||||||
|
this.attachmentType,
|
||||||
|
this.tableItemId,
|
||||||
|
});
|
||||||
|
|
||||||
|
@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 = widget.attachmentList;
|
||||||
|
// await assetDeliveryProvider.getAttachments(tableItemId: widget.tableItemId, attachmentType: widget.attachmentType);
|
||||||
|
// isLoading = false;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
log('value ${widget.attachmentType}');
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Attachments'.addTranslation,
|
||||||
|
onBackPress: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
body: widget.attachmentList.isEmpty
|
||||||
|
? const NoDataFound().center
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.loose, // ✅ expands only as much as needed
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
widget.attachmentType == 5 && !widget.viewOnly
|
||||||
|
? AttachmentPicker(
|
||||||
|
label: context.translation.attachments,
|
||||||
|
attachment: _attachments,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onlyImages: false,
|
||||||
|
showAsListView: true,
|
||||||
|
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
|
||||||
|
onChange: (attachment) {},
|
||||||
|
).toShadowContainer(
|
||||||
|
context,
|
||||||
|
borderRadius: 20,
|
||||||
|
padding: 12,
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
)
|
||||||
|
: FilesList(images: _attachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []).toShadowContainer(
|
||||||
|
context,
|
||||||
|
borderRadius: 20,
|
||||||
|
padding: 12,
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: 'Save'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
onPressed: _onSavePressed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onSavePressed() async {
|
||||||
|
final List<GenericAttachmentModel> attachmentPayload = _attachments.map((item) {
|
||||||
|
final String name = CMRequestUtils.isLocalUrl(item.name ?? '') ? '${item.name?.split("/").last}|${base64Encode(File(item.name!).readAsBytesSync())}' : item.name ?? '';
|
||||||
|
|
||||||
|
return GenericAttachmentModel(
|
||||||
|
id: item.id ?? 0,
|
||||||
|
name: name,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (_) => const AppLazyLoading(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final payload = {
|
||||||
|
'assetDeliveryExternalDeliveryId': widget.tableItemId,
|
||||||
|
'attachments': attachmentPayload,
|
||||||
|
};
|
||||||
|
|
||||||
|
final status = await assetDeliveryProvider.saveAttachment(payload: payload);
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
import 'package:flutter/material.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/new_views/app_style/app_color.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
|
||||||
|
|
||||||
|
class AssetDeliveryBottomSheet {
|
||||||
|
static buildBottomSheetParent({required BuildContext context, required Widget childWidget, bool? isDismissible}) {
|
||||||
|
return showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
useSafeArea: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
isDismissible: isDismissible ?? true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
builder: (context) => SingleChildScrollView(
|
||||||
|
child: SafeArea(child: childWidget),
|
||||||
|
).bottomSheetContainer(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future changeStatusBottomSheet({required BuildContext context, required VoidCallback cancelStatusTap, required VoidCallback statusChangeTap}) {
|
||||||
|
return buildBottomSheetParent(
|
||||||
|
context: context,
|
||||||
|
childWidget: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox().indicatorWidget(),
|
||||||
|
8.height,
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
child: Text(
|
||||||
|
'Change Status'.addTranslation,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 21.toScreenWidth,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontStyle: FontStyle.normal,
|
||||||
|
decoration: TextDecoration.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(
|
||||||
|
label: 'Cancel'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
buttonColor: Colors.white,
|
||||||
|
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
|
||||||
|
textColor: AppColor.red30,
|
||||||
|
showBorder: true,
|
||||||
|
onPressed: () async {
|
||||||
|
cancelStatusTap();
|
||||||
|
},
|
||||||
|
).expanded,
|
||||||
|
12.width,
|
||||||
|
AppFilledButton(
|
||||||
|
buttonColor: AppColor.green70,
|
||||||
|
label: 'Change Status'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
onPressed: () {
|
||||||
|
statusChangeTap();
|
||||||
|
}).expanded,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,457 @@
|
|||||||
|
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/models/cost_center_serial_no_form_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/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 CostCenterFormView extends StatefulWidget {
|
||||||
|
final List<CostCenterModel>? costCenterList;
|
||||||
|
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.lineId,
|
||||||
|
this.requestId,
|
||||||
|
this.tableItemId,
|
||||||
|
this.itemNo,
|
||||||
|
this.isHmg,
|
||||||
|
this.itemDescription,
|
||||||
|
this.cardPadding,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CostCenterFormView> createState() => _CostCenterFormViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CostCenterFormViewState extends State<CostCenterFormView> {
|
||||||
|
CostCenterSerialNoFormModel formModel = CostCenterSerialNoFormModel(costCenters: [], serialNos: []);
|
||||||
|
late AssetDeliveryProvider assetDeliveryProvider;
|
||||||
|
CostCenterType _selectedType = CostCenterType.costCenter;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
assetDeliveryProvider = Provider.of<AssetDeliveryProvider>(context, listen: false);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
getInitialData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getInitialData() async {
|
||||||
|
formModel = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines(
|
||||||
|
lineId: widget.lineId,
|
||||||
|
tableItemId: widget.tableItemId,
|
||||||
|
);
|
||||||
|
if (formModel.costCenters!.isEmpty) {
|
||||||
|
formModel.costCenters!.add(CostCenterModel(
|
||||||
|
id: 0,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// if (formModel.serialNos!.isEmpty) {
|
||||||
|
// formModel.serialNos!.add(SerialNoModel(
|
||||||
|
// 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 addItem<T>(List<T> list, T Function() creator) {
|
||||||
|
setState(() {
|
||||||
|
list.add(creator());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeItem<T>(List<T> list, int index) {
|
||||||
|
setState(() {
|
||||||
|
list.removeAt(index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateItem<T>(List<T> list, int index, void Function(T item) updater) {
|
||||||
|
setState(() {
|
||||||
|
updater(list[index]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Cost Center for Item'.addTranslation,
|
||||||
|
// onBackPress: () {
|
||||||
|
// Navigator.pop(context);
|
||||||
|
// },
|
||||||
|
),
|
||||||
|
body: Consumer<AssetDeliveryProvider>(builder: (context, provider, child) {
|
||||||
|
return provider.isLoading
|
||||||
|
? const CircularProgressIndicator(color: AppColor.primary10).center
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
itemDetails(),
|
||||||
|
selectionButton(),
|
||||||
|
_selectedType == CostCenterType.costCenter ? _buildCostCenterList() : _buildSerialNumberList(),
|
||||||
|
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: formModel.costCenters, serialNoList: formModel.serialNos)
|
||||||
|
.then((status) async {
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (status) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
assetDeliveryProvider.getDeliveryLinesListById(
|
||||||
|
itemId: widget.tableItemId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCostCenterList() {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: formModel.costCenters!.length + 1,
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == formModel.costCenters!.length) {
|
||||||
|
return 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: () {
|
||||||
|
addItem(formModel.costCenters!, () => CostCenterModel(costCenter: Lookup()));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CostCenterItemCard(
|
||||||
|
model: formModel.costCenters![index],
|
||||||
|
index: index,
|
||||||
|
isReadOnly: false,
|
||||||
|
isHmg: widget.isHmg,
|
||||||
|
requestId: widget.requestId,
|
||||||
|
onUpdate: (update) {
|
||||||
|
updateItem<CostCenterModel>(formModel.costCenters!, index, update);
|
||||||
|
},
|
||||||
|
onRemove: () {
|
||||||
|
removeItem<CostCenterModel>(formModel.costCenters!, index);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSerialNumberList() {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: formModel.serialNos!.length + 1,
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == formModel.serialNos!.length) {
|
||||||
|
return AppFilledButton(
|
||||||
|
label: "Add Serial Number".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: () {
|
||||||
|
addItem(formModel.serialNos!, () => SerialNoModel());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SerialNumberItemCard(
|
||||||
|
model: formModel.serialNos![index],
|
||||||
|
onUpdate: (update) {
|
||||||
|
updateItem<SerialNoModel>(formModel.serialNos!, index, update);
|
||||||
|
},
|
||||||
|
onRemove: () {
|
||||||
|
removeItem<SerialNoModel>(formModel.serialNos!, index);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget selectionButton() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: _radioItem(
|
||||||
|
value: CostCenterType.costCenter,
|
||||||
|
groupValue: _selectedType,
|
||||||
|
title: 'Cost Center',
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_selectedType = CostCenterType.costCenter;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: _radioItem(
|
||||||
|
value: CostCenterType.serialNumber,
|
||||||
|
groupValue: _selectedType,
|
||||||
|
title: 'Serial Number',
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_selectedType = CostCenterType.serialNumber;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _radioItem({
|
||||||
|
required CostCenterType value,
|
||||||
|
required CostCenterType groupValue,
|
||||||
|
required String title,
|
||||||
|
required VoidCallback onTap,
|
||||||
|
}) {
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: onTap,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Radio<CostCenterType>(
|
||||||
|
value: value,
|
||||||
|
groupValue: groupValue,
|
||||||
|
onChanged: (_) => onTap(),
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
4.width,
|
||||||
|
title.addTranslation.bodyText(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget itemDetails() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Item No'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Text(
|
||||||
|
widget.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(
|
||||||
|
widget.itemDescription ?? '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(
|
||||||
|
context,
|
||||||
|
borderRadius: 20,
|
||||||
|
padding: 12,
|
||||||
|
showShadow: false,
|
||||||
|
margin: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 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;
|
||||||
|
|
||||||
|
const CostCenterItemCard({
|
||||||
|
super.key,
|
||||||
|
required this.model,
|
||||||
|
this.requestId,
|
||||||
|
this.isHmg,
|
||||||
|
required this.index,
|
||||||
|
required this.isReadOnly,
|
||||||
|
required this.onUpdate,
|
||||||
|
required this.onRemove,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
if (!isReadOnly)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
'Cost Center'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)),
|
||||||
|
if (!isReadOnly)
|
||||||
|
Container(
|
||||||
|
height: 28,
|
||||||
|
width: 28,
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
child: "trash".toSvgAsset(height: 20, width: 20),
|
||||||
|
).onPress(onRemove),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
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: 'Quantity'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.quantity != null ? model.quantity.toString() : '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: true,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
onChange: (value) {
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
model.quantity = double.tryParse(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 12, vertical: 12)).paddingOnly(bottom: 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SerialNumberItemCard extends StatelessWidget {
|
||||||
|
final SerialNoModel model;
|
||||||
|
final VoidCallback onRemove;
|
||||||
|
final void Function(void Function(SerialNoModel model)) onUpdate;
|
||||||
|
|
||||||
|
const SerialNumberItemCard({
|
||||||
|
super.key,
|
||||||
|
required this.model,
|
||||||
|
required this.onRemove,
|
||||||
|
required this.onUpdate,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
'Serial Number'.addTranslation.bodyText(context),
|
||||||
|
Container(
|
||||||
|
height: 28,
|
||||||
|
width: 28,
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
child: "trash".toSvgAsset(height: 20, width: 20),
|
||||||
|
).onPress(onRemove),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Serial Number'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.serialNo ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
showShadow: false,
|
||||||
|
onChange: (value) {
|
||||||
|
model.serialNo = value;
|
||||||
|
},
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.toShadowContainer(
|
||||||
|
context,
|
||||||
|
paddingObject: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||||
|
)
|
||||||
|
.paddingOnly(bottom: 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,726 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
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/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/helper_function.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/models/inspection_person_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/asset_delivery_stage_tab_page.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/inpection_bottomsheet.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_delivery_module/provider/asset_delivery_provider.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_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/default_app_bar.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.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';
|
||||||
|
|
||||||
|
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
|
||||||
|
State<DeliveryInspectionFormView> createState() => _DeliveryInspectionFormViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
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(
|
||||||
|
formatInspectionDuration(model.totalTime),
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(
|
||||||
|
color: context.isDark ? AppColor.neutral30 : AppColor.neutral120,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: !viewOnly
|
||||||
|
? Column(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: 'Attachments'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
onPressed: () {
|
||||||
|
HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
}),
|
||||||
|
16.height,
|
||||||
|
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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(
|
||||||
|
buttonColor: AppColor.white60,
|
||||||
|
label: 'Attachments'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
textColor: AppColor.black10,
|
||||||
|
onPressed: () {
|
||||||
|
HelperFunction.attachmentTap(context: context, viewOnly: true, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
}).expanded,
|
||||||
|
8.width,
|
||||||
|
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget linesList(BuildContext context) {
|
||||||
|
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() {
|
||||||
|
final from = model.deliveryInspectionInspectedDateFrom;
|
||||||
|
final to = model.deliveryInspectionInspectedDateTo;
|
||||||
|
|
||||||
|
if (from == null || to == null) {
|
||||||
|
model.totalTime = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final diffInSeconds = to.difference(from).inSeconds;
|
||||||
|
|
||||||
|
if (diffInSeconds < 0) {
|
||||||
|
model.totalTime = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final hours = diffInSeconds / 3600;
|
||||||
|
model.totalTime = num.parse(hours.toStringAsFixed(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget inspectionDetailsForm() {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
_inspectionTile(
|
||||||
|
title: 'Inspected by'.addTranslation,
|
||||||
|
model: model.inspectedByModel,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
onTap: () async {
|
||||||
|
final result = await showInspectionBottomSheet(
|
||||||
|
context,
|
||||||
|
title: 'Inspected by'.addTranslation,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
initialModel: model.inspectedByModel ?? InspectionPersonModel(),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
setState(() => model.inspectedByModel = result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
8.height,
|
||||||
|
_inspectionTile(
|
||||||
|
title: 'Approved by'.addTranslation,
|
||||||
|
model: model.approvedByModel,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
onTap: () async {
|
||||||
|
final result = await showInspectionBottomSheet(
|
||||||
|
context,
|
||||||
|
title: 'Approved by'.addTranslation,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
initialModel: model.approvedByModel ?? InspectionPersonModel(),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
setState(() => model.approvedByModel = result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (widget.requestModel?.paymentTerm?.value == 2) ...[
|
||||||
|
8.height,
|
||||||
|
_inspectionTile(
|
||||||
|
title: 'Third Approved by'.addTranslation,
|
||||||
|
model: model.thirdApprovalModel,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
onTap: () async {
|
||||||
|
final result = await showInspectionBottomSheet(
|
||||||
|
context,
|
||||||
|
title: 'Third Approved by'.addTranslation,
|
||||||
|
isHmg: widget.requestModel?.isHMG == true,
|
||||||
|
initialModel: model.thirdApprovalModel ?? InspectionPersonModel(),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
setState(() => model.thirdApprovalModel = result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
// if (widget.requestModel?.isHMG == true) ...[
|
||||||
|
// OracleUserAutoCompleteField(
|
||||||
|
// clearAfterPick: false,
|
||||||
|
// initialValue: model.deliveryInspectionInspectedBy ?? '',
|
||||||
|
// label: 'Inspected by'.addTranslation,
|
||||||
|
// onPick: (value) {
|
||||||
|
// model.deliveryInspectionInspectedBy = value.fullName;
|
||||||
|
// setState(() {});
|
||||||
|
// },
|
||||||
|
// 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: model.deliveryInspectionInspectedDateFrom,
|
||||||
|
from: DateTime(DateTime.now().year, 1, 1),
|
||||||
|
formatDateWithTime: true,
|
||||||
|
onDatePicker: (selectedDate) async {
|
||||||
|
final selectedTime = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
builder: _timePickerThemeBuilder,
|
||||||
|
);
|
||||||
|
if (selectedTime == null) return;
|
||||||
|
|
||||||
|
final fromDateTime = DateTime(
|
||||||
|
selectedDate.year,
|
||||||
|
selectedDate.month,
|
||||||
|
selectedDate.day,
|
||||||
|
selectedTime.hour,
|
||||||
|
selectedTime.minute,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!_validateInspectionDates(from: fromDateTime, to: model.deliveryInspectionInspectedDateTo)) {
|
||||||
|
return; // invalid, do not assign
|
||||||
|
}
|
||||||
|
|
||||||
|
model.deliveryInspectionInspectedDateFrom = fromDateTime;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
8.height,
|
||||||
|
ADatePicker(
|
||||||
|
label: 'Inspected Date/Time To'.addTranslation,
|
||||||
|
hideShadow: true,
|
||||||
|
height: 56.toScreenHeight,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
date: model.deliveryInspectionInspectedDateTo,
|
||||||
|
from: model.deliveryInspectionInspectedDateFrom,
|
||||||
|
formatDateWithTime: true,
|
||||||
|
onDatePicker: (selectedDate) async {
|
||||||
|
if (model.deliveryInspectionInspectedDateFrom == null) {
|
||||||
|
"Please select time to first".showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final selectedTime = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
builder: _timePickerThemeBuilder,
|
||||||
|
);
|
||||||
|
if (selectedTime == null) return;
|
||||||
|
|
||||||
|
final toDateTime = DateTime(
|
||||||
|
selectedDate.year,
|
||||||
|
selectedDate.month,
|
||||||
|
selectedDate.day,
|
||||||
|
selectedTime.hour,
|
||||||
|
selectedTime.minute,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!_validateInspectionDates(from: model.deliveryInspectionInspectedDateFrom, to: toDateTime)) {
|
||||||
|
return; // invalid, do not assign
|
||||||
|
}
|
||||||
|
|
||||||
|
model.deliveryInspectionInspectedDateTo = toDateTime;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _validateInspectionDates({DateTime? from, DateTime? to}) {
|
||||||
|
if (from == null && to == null) return true;
|
||||||
|
if (from != null) {
|
||||||
|
if (from.isAfter(DateTime.now())) {
|
||||||
|
"Time From cannot be in the future".showToast;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (to != null && from.isAfter(to)) {
|
||||||
|
"Time To cannot be after Time From".showToast;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (to != null) {
|
||||||
|
if (to.isAfter(DateTime.now())) {
|
||||||
|
"Time To cannot be in the future".showToast;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (from != null && to.isBefore(from)) {
|
||||||
|
"Timer To cannot be before from time".showToast;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from != null && to != null) {
|
||||||
|
final diffInSeconds = to.difference(from).inSeconds;
|
||||||
|
if (diffInSeconds < 0) {
|
||||||
|
model.totalTime = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final hours = diffInSeconds / 3600.0;
|
||||||
|
model.totalTime = num.parse(hours.toStringAsFixed(3));
|
||||||
|
} else {
|
||||||
|
model.totalTime = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatInspectionDuration(num? hours) {
|
||||||
|
if (hours == null) return '-';
|
||||||
|
|
||||||
|
if (hours < 1) {
|
||||||
|
final minutes = (hours * 60).round();
|
||||||
|
return '$minutes minutes';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '${hours.toStringAsFixed(2)} hours';
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _timePickerThemeBuilder(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!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
model.deliveryInspectionInspectedBy ?? '-',
|
||||||
|
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(
|
||||||
|
model.deliveryInspectionApprovedBy ?? '-',
|
||||||
|
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(
|
||||||
|
model.deliveryInspectionInspectedDateFrom != null ? model.deliveryInspectionInspectedDateFrom!.toString().toServiceRequestDetailsFormat : '-',
|
||||||
|
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(
|
||||||
|
model.deliveryInspectionInspectedDateTo != null ? model.deliveryInspectionInspectedDateTo!.toString().toServiceRequestDetailsFormat : '-',
|
||||||
|
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _inspectionTile({
|
||||||
|
required String title,
|
||||||
|
InspectionPersonModel? model,
|
||||||
|
required bool isHmg,
|
||||||
|
required VoidCallback onTap,
|
||||||
|
}) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.fieldBgColor(context),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title, style: AppTextStyles.textFieldLabelStyle),
|
||||||
|
6.height,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
model?.name?.isNotEmpty == true ? model!.name! : 'Tap to add'.addTranslation,
|
||||||
|
style: AppTextStyles.bodyText,
|
||||||
|
),
|
||||||
|
|
||||||
|
///Need to display other info as well
|
||||||
|
// Text(
|
||||||
|
// model?.email?.isNotEmpty == true
|
||||||
|
// ? model!.email!
|
||||||
|
// : '',
|
||||||
|
// style: AppTextStyles.bodyText,
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Lookup?> showAttachmentTypePicker() {
|
||||||
|
return showDialog<Lookup>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) {
|
||||||
|
return AlertDialog(
|
||||||
|
content: SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProvider>(
|
||||||
|
context: context,
|
||||||
|
title: context.translation.reason,
|
||||||
|
showAsFullScreenDialog: false,
|
||||||
|
onSelect: (value) {
|
||||||
|
Navigator.pop(context, value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
if (widget.deliveryTableModel.isContainsTechnicalInspection == true) {
|
||||||
|
// Navigator.push(
|
||||||
|
// context,
|
||||||
|
// MaterialPageRoute(
|
||||||
|
// builder: (context) => TechnicalInspectionLinesListView(
|
||||||
|
// deliveryTableModel: widget.deliveryTableModel,
|
||||||
|
// requestModel: widget.requestModel,
|
||||||
|
// ))
|
||||||
|
// );
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => AssetDeliveryStageTabPage(
|
||||||
|
title: 'Technical Inspection'.addTranslation,
|
||||||
|
detailWidget: TechnicalInspectionLinesListView(
|
||||||
|
deliveryTableModel: widget.deliveryTableModel,
|
||||||
|
requestModel: widget.requestModel,
|
||||||
|
),
|
||||||
|
tableId: widget.deliveryTableModel.id,
|
||||||
|
)));
|
||||||
|
} else {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => AssetDeliveryStageTabPage(
|
||||||
|
title: 'End-User Acceptance'.addTranslation,
|
||||||
|
detailWidget: EndUserCostCenterLIstView(
|
||||||
|
deliveryTableModel: widget.deliveryTableModel,
|
||||||
|
requestModel: widget.requestModel,
|
||||||
|
),
|
||||||
|
tableId: widget.deliveryTableModel.id,
|
||||||
|
)));
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<InspectionPersonModel?> showInspectionBottomSheet(
|
||||||
|
BuildContext context, {
|
||||||
|
required String title,
|
||||||
|
required bool isHmg,
|
||||||
|
required InspectionPersonModel initialModel,
|
||||||
|
}) {
|
||||||
|
return showModalBottomSheet<InspectionPersonModel>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
|
),
|
||||||
|
builder: (_) {
|
||||||
|
if (initialModel.localSignature == null && initialModel.signature != null) {
|
||||||
|
initialModel.localSignature = signatureFromString(initialModel.signature);
|
||||||
|
}
|
||||||
|
return InspectionPersonBottomSheet(
|
||||||
|
title: title,
|
||||||
|
isHmg: isHmg,
|
||||||
|
model: InspectionPersonModel(
|
||||||
|
name: initialModel.name,
|
||||||
|
email: initialModel.email,
|
||||||
|
signature: initialModel.signature,
|
||||||
|
localSignature: initialModel.localSignature,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8List? signatureFromString(String? value) {
|
||||||
|
if (value == null || !value.contains('|')) return null;
|
||||||
|
final base64Part = value.split('|').last;
|
||||||
|
return base64Decode(base64Part);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.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/modules/asset_delivery_module/models/inspection_person_model.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.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_text_form_field.dart';
|
||||||
|
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
|
||||||
|
|
||||||
|
class InspectionPersonBottomSheet extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
bool isHmg;
|
||||||
|
final InspectionPersonModel model;
|
||||||
|
|
||||||
|
InspectionPersonBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.isHmg,
|
||||||
|
required this.model,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InspectionPersonBottomSheet> createState() => _InspectionPersonBottomSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InspectionPersonBottomSheetState extends State<InspectionPersonBottomSheet> {
|
||||||
|
late InspectionPersonModel _model;
|
||||||
|
|
||||||
|
late TextEditingController nameController;
|
||||||
|
late TextEditingController emailController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_model = InspectionPersonModel(name: widget.model.name, email: widget.model.email, signature: widget.model.signature, localSignature: widget.model.localSignature);
|
||||||
|
nameController = TextEditingController(text: _model.name ?? '');
|
||||||
|
emailController = TextEditingController(text: _model.email ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
nameController.dispose();
|
||||||
|
emailController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: 16,
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(widget.title, style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
16.height,
|
||||||
|
if (widget.isHmg)
|
||||||
|
OracleUserAutoCompleteField(
|
||||||
|
clearAfterPick: false,
|
||||||
|
initialValue: _model.name ?? '',
|
||||||
|
label: 'Name'.addTranslation,
|
||||||
|
onPick: (value) {
|
||||||
|
_model.name = value.fullName;
|
||||||
|
nameController.text = value.fullName ?? '';
|
||||||
|
emailController.text = value.employeeEmail ?? '';
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Name'.addTranslation,
|
||||||
|
controller: nameController,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
showShadow: false,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
onChange: (v) {
|
||||||
|
_model.name = v;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
12.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Email'.addTranslation,
|
||||||
|
controller: emailController,
|
||||||
|
textInputType: TextInputType.emailAddress,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
showShadow: false,
|
||||||
|
enable: widget.isHmg?false:true,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
onChange: (v) {
|
||||||
|
setState(() {
|
||||||
|
_model.email = v;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
12.height,
|
||||||
|
ESignature(
|
||||||
|
title: '',
|
||||||
|
oldSignature: _model.localSignature == null ? _model.signature : null,
|
||||||
|
newSignature: _model.localSignature,
|
||||||
|
backgroundColor: AppColor.neutral100,
|
||||||
|
showShadow: false,
|
||||||
|
onChange: (signature) {
|
||||||
|
if (signature.isEmpty) return;
|
||||||
|
setState(() {
|
||||||
|
_model.localSignature = signature;
|
||||||
|
_model.signature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSaved: (signature) {
|
||||||
|
if (signature == null || signature.isEmpty) return;
|
||||||
|
setState(() {
|
||||||
|
_model.localSignature = signature;
|
||||||
|
_model.signature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
20.height,
|
||||||
|
AppFilledButton(
|
||||||
|
label: context.translation.save,
|
||||||
|
maxWidth: true,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onPressed: () async {
|
||||||
|
_model.name = nameController.text.trim();
|
||||||
|
_model.email = emailController.text.trim();
|
||||||
|
Navigator.pop(context, _model);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
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>(
|
||||||
|
key: ValueKey(widget.initialValue),
|
||||||
|
optionsBuilder: (TextEditingValue textEditingValue) async {
|
||||||
|
if (textEditingValue.text.isEmpty) {
|
||||||
|
return const Iterable<OracleUserModel>.empty();
|
||||||
|
}
|
||||||
|
return await assetDeliveryProvider!.getOracleUserAutoCompleteDetails(query: textEditingValue.text);
|
||||||
|
},
|
||||||
|
initialValue: TextEditingValue(text: widget.initialValue),
|
||||||
|
displayStringForOption: (OracleUserModel option) => option.fullName ?? "",
|
||||||
|
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
|
||||||
|
return TextField(
|
||||||
|
controller: fieldTextEditingController,
|
||||||
|
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) {
|
||||||
|
// fieldTextEditingController.clear();
|
||||||
|
// } else {
|
||||||
|
// _controller.text = selection.fullName ?? '';
|
||||||
|
// }
|
||||||
|
widget.onPick(selection);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
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 EndUserCostCenterCardView extends StatelessWidget {
|
||||||
|
CostCenterModel costModel;
|
||||||
|
VoidCallback? editPress;
|
||||||
|
bool isViewOnly;
|
||||||
|
|
||||||
|
EndUserCostCenterCardView({
|
||||||
|
super.key,
|
||||||
|
required this.costModel,
|
||||||
|
this.editPress,
|
||||||
|
required this.isViewOnly,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
//need to check this @waseem.
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
'Cost Center Name: ${costModel.costCenterName ?? '-'}',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
8.width,
|
||||||
|
if (!isViewOnly)
|
||||||
|
'edit_icon'.toSvgAsset(height: 18, width: 18).onPress(() {
|
||||||
|
if (editPress != null) {
|
||||||
|
editPress!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Accepted By: ${costModel.acceptedBy ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),Text(
|
||||||
|
'Accepted By Email: ${costModel.acceptedByEmail ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),Text(
|
||||||
|
'Acceptance Date: ${costModel.acceptanceDate!=null? costModel.acceptanceDate.toString().toAssetDetailsFormat: '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20, padding: 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
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),
|
||||||
|
),
|
||||||
|
//TODO Need to confirm with @Ahmed need to hide this or not
|
||||||
|
if (assetModel.status?.value == 2)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,198 @@
|
|||||||
|
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/helper_function.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_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 '../../../../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
|
||||||
|
State<EndUserCostCenterLIstView> createState() => _EndUserCostCenterLIstViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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: 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,
|
||||||
|
|
||||||
|
!viewOnly
|
||||||
|
? FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap),
|
||||||
|
16.height,
|
||||||
|
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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))
|
||||||
|
: FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.white60,
|
||||||
|
label: 'Attachments'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
textColor: AppColor.black10,
|
||||||
|
onPressed: () {
|
||||||
|
HelperFunction.attachmentTap(context: context, viewOnly: true, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Need to refector don't use listview and singlechildview both @waseem.
|
||||||
|
Widget linesList(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Cost Center",
|
||||||
|
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
ListView.separated(
|
||||||
|
itemCount: costCenterList.length,
|
||||||
|
separatorBuilder: (_, __) => 8.height,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (listContext, itemIndex) {
|
||||||
|
return EndUserCostCenterCardView(
|
||||||
|
costModel: costCenterList[itemIndex],
|
||||||
|
isViewOnly: viewOnly,
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _attachmentTap() async {
|
||||||
|
HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 _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,520 @@
|
|||||||
|
// 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 ?? '';
|
||||||
|
// model.type = 'Accessory';
|
||||||
|
// 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,
|
||||||
|
// validator: (value) {
|
||||||
|
// if (value == null) return "Please select status";
|
||||||
|
// return null;
|
||||||
|
// },
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
// showAsBottomSheet: true,
|
||||||
|
// initialValue: model.status,
|
||||||
|
// onSelect: (status) {
|
||||||
|
// if (status != null) {
|
||||||
|
// model.status = status;
|
||||||
|
// 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,
|
||||||
|
// validator: (value) {
|
||||||
|
// if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
// return null;
|
||||||
|
// },
|
||||||
|
// onChange: (value) {
|
||||||
|
// if (value.isNotEmpty) {
|
||||||
|
// model.rejectedQty = model.rejectedQty = num.tryParse(value);
|
||||||
|
// setState(() {});
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
// ),
|
||||||
|
// 8.height,
|
||||||
|
// if (model.status?.value == 1 && (model.rejectedQty != null && quantityController.text.isNotEmpty && model.rejectedQty! > 0))
|
||||||
|
// SingleItemDropDownMenu<Lookup, EndUserRejectionReasonLookupProvider>(
|
||||||
|
// context: context,
|
||||||
|
// height: 56.toScreenHeight,
|
||||||
|
// title: 'Rejection Reason '.addTranslation,
|
||||||
|
// validator: (value) {
|
||||||
|
// if (value == null) return "Please select rejection reason";
|
||||||
|
// return null;
|
||||||
|
// },
|
||||||
|
// 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.status != null && model.status!.value == 2) ...[
|
||||||
|
// SingleItemDropDownMenu<Lookup, EndUserRejectionReasonLookupProvider>(
|
||||||
|
// context: context,
|
||||||
|
// height: 56.toScreenHeight,
|
||||||
|
// title: 'Rejection Reason '.addTranslation,
|
||||||
|
// validator: (value) {
|
||||||
|
// if (value == null) return "Please select rejection reason";
|
||||||
|
// return null;
|
||||||
|
// },
|
||||||
|
// 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,
|
||||||
|
// ],
|
||||||
|
// 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 {
|
||||||
|
// if (!_formKey.currentState!.validate()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// _formKey.currentState!.save();
|
||||||
|
// log('payload ${model.toJson()}');
|
||||||
|
// return;
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
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/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 {
|
||||||
|
final EndUserAssetDetailsModel? assetDetailsModel;
|
||||||
|
final String? costCenterName;
|
||||||
|
final int? tableId;
|
||||||
|
|
||||||
|
const 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>();
|
||||||
|
|
||||||
|
late AssetDeliveryProvider assetDeliveryProvider;
|
||||||
|
EndUserAssetDetailsModel model = EndUserAssetDetailsModel();
|
||||||
|
|
||||||
|
late TextEditingController quantityController;
|
||||||
|
late TextEditingController descriptionController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
quantityController = TextEditingController();
|
||||||
|
descriptionController = TextEditingController();
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_loadInitialData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _loadInitialData() {
|
||||||
|
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;
|
||||||
|
model.receivedQty = widget.assetDetailsModel?.receivedQty;
|
||||||
|
}
|
||||||
|
|
||||||
|
quantityController.text = model.rejectedQty != null ? model.rejectedQty.toString() : '';
|
||||||
|
descriptionController.text = model.description ?? '';
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get _isAccessory => model.type == 'Accessory';
|
||||||
|
|
||||||
|
bool get _isAccepted => model.status?.value == 1;
|
||||||
|
|
||||||
|
bool get _isRejected => model.status?.value == 2;
|
||||||
|
|
||||||
|
bool get _showRejectedQty {
|
||||||
|
if (_isAccessory) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get _showReceivedQty {
|
||||||
|
if (_isAccessory && model.receivedQty != null) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get _showRejectionReason {
|
||||||
|
if (_isAccessory) {
|
||||||
|
if (_isRejected) return true;
|
||||||
|
if (_isAccepted && (model.rejectedQty ?? 0) > 0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_isRejected) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
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: _formBody(context),
|
||||||
|
).expanded,
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: 'Save'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
onPressed: _saveTap,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _formBody(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_statusDropdown(),
|
||||||
|
8.height,
|
||||||
|
if (_showReceivedQty) ...[
|
||||||
|
_receivedQtyField(),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
if (_showRejectedQty) ...[
|
||||||
|
_rejectedQtyField(),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
if (_showRejectionReason) ...[
|
||||||
|
_rejectionReasonDropdown(),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
_descriptionField(),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20, padding: 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _statusDropdown() {
|
||||||
|
return 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,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null) return 'Please select status';
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onSelect: (status) {
|
||||||
|
if (status != null) {
|
||||||
|
model.status = status;
|
||||||
|
model.rejectionReason = null;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _rejectedQtyField() {
|
||||||
|
return AppTextFormField(
|
||||||
|
labelText: 'Rejected Quantity'.addTranslation,
|
||||||
|
controller: quantityController,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
validator: (value) {
|
||||||
|
if (!_showRejectedQty) return null;
|
||||||
|
if ((value ?? '').isEmpty) return 'Mandatory';
|
||||||
|
final qty = num.tryParse(value!);
|
||||||
|
if (qty == null || qty <= 0) return 'Enter valid quantity';
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onChange: (value) {
|
||||||
|
model.rejectedQty = value.isNotEmpty ? num.tryParse(value) : null;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _receivedQtyField() {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.neutral40,
|
||||||
|
// color: AppColor.fieldBgColor(context),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Received Qty', style: AppTextStyles.textFieldLabelStyle),
|
||||||
|
4.height,
|
||||||
|
Text(model.receivedQty.toString(), style: AppTextStyles.textFieldLabelStyle),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Received Quantity'.addTranslation,
|
||||||
|
initialValue: model.receivedQty.toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
enable: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _rejectionReasonDropdown() {
|
||||||
|
return 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,
|
||||||
|
validator: (value) {
|
||||||
|
if (!_showRejectionReason) return null;
|
||||||
|
if (value == null) return 'Please select rejection reason';
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onSelect: (reason) {
|
||||||
|
if (reason != null) {
|
||||||
|
model.rejectionReason = reason;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _descriptionField() {
|
||||||
|
return 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _saveTap() async {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
|
||||||
|
_formKey.currentState!.save();
|
||||||
|
log('payload ${model.toJson()}');
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (_) => const AppLazyLoading(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final status = await assetDeliveryProvider.saveEndUserAssetDataData(model: model);
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,331 @@
|
|||||||
|
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,
|
||||||
|
] else ...[
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Accepted By'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
controller: acceptedByController,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onChange: (value) {
|
||||||
|
model.acceptedByEmail = value;
|
||||||
|
},
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
enable: widget.isHmg == true ? false : true,
|
||||||
|
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) {
|
||||||
|
updateSignature(signature: signature);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSignature({Uint8List? signature}) {
|
||||||
|
if (signature == null || signature.isEmpty) {
|
||||||
|
setState(() {
|
||||||
|
newSignature = null;
|
||||||
|
model.acceptedBySignature = null;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
newSignature = signature;
|
||||||
|
model.acceptedBySignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _saveTap() async {
|
||||||
|
if (!_formKey.currentState!.validate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (model.acceptanceDate == null) {
|
||||||
|
"Select Accepted date".showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (widget.isHmg == true) {
|
||||||
|
if ((model.acceptedBy ?? '').isEmpty || (model.acceptedByEmail ?? '').isEmpty) {
|
||||||
|
'Accepted By and Email are required'.addTranslation.showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (model.acceptedBySignature == null || model.acceptedBySignature!.isEmpty) {
|
||||||
|
'Signature is required'.addTranslation.showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
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/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/new_views/common_widgets/default_app_bar.dart';
|
||||||
|
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
|
for (int i = 0; i < history.length; i++) {
|
||||||
|
var object = history[i];
|
||||||
|
String currentStatus = object.status!.name!;
|
||||||
|
if (lastStatus.isEmpty) {
|
||||||
|
lastStatus = currentStatus;
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
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(statusCard(cxt, lastStatus));
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(children: items),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);}
|
||||||
|
|
||||||
|
Widget historyLogCard(BuildContext context, AssetDeliveryHistoryModel object) {
|
||||||
|
String title = object.status!.name!;
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
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: [
|
||||||
|
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(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, padding: 16).paddingOnly(bottom: 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget statusCard(BuildContext context, String status) {
|
||||||
|
return SizedBox(
|
||||||
|
width: 153.toScreenWidth,
|
||||||
|
child: StatusLabel(
|
||||||
|
radius: 4,
|
||||||
|
label: statusText(status.toLowerCase()),
|
||||||
|
labelInCenter: true,
|
||||||
|
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 "New".addTranslation;
|
||||||
|
} else if (status == "in progress") {
|
||||||
|
return "Status update to In Progress".addTranslation;
|
||||||
|
} else if (status == "closed") {
|
||||||
|
return "Status update to Closed".addTranslation;
|
||||||
|
} else if (status == "completed") {
|
||||||
|
return "Status update to Completed".addTranslation;
|
||||||
|
} else if (status == "fixed") {
|
||||||
|
return "Status update to Fixed".addTranslation;
|
||||||
|
} else if (status == "reject") {
|
||||||
|
return "Status update to Rejected".addTranslation;
|
||||||
|
} else
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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,215 @@
|
|||||||
|
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/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 InspectionCheckListView extends StatefulWidget {
|
||||||
|
final List<InspectionChecklistItem>? initialValues;
|
||||||
|
|
||||||
|
const InspectionCheckListView({super.key, this.initialValues});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InspectionCheckListView> createState() => _InspectionCheckListViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InspectionCheckListViewState extends State<InspectionCheckListView> {
|
||||||
|
late List<InspectionChecklistItem> checklist;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
checklist = AssetDeliveryUtils.inspectionChecklist.map((e) => InspectionChecklistItem(title: e.title)).toList();
|
||||||
|
|
||||||
|
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(
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Asset Check List'.addTranslation,
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: List.generate(
|
||||||
|
checklist.length,
|
||||||
|
(index) {
|
||||||
|
final model = checklist[index];
|
||||||
|
return inspectionStatusRadioWidget(
|
||||||
|
model: model,
|
||||||
|
index: index,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).toShadowContainer(
|
||||||
|
context,
|
||||||
|
borderRadius: 20,
|
||||||
|
margin: const EdgeInsets.only(top: 12, left: 12, right: 12),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: 'Save'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, selectedValues);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget inspectionStatusRadioWidget({required int index, required InspectionChecklistItem model, required BuildContext context}) {
|
||||||
|
bool status = (model.status == null || model.status == null) ? true : (model.status != null ? (model.status == 'true' ? true : false) : false);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
model.title ?? '',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? Colors.white : AppColor.white936),
|
||||||
|
),
|
||||||
|
14.height,
|
||||||
|
// Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
//
|
||||||
|
// (status ? 'Pass' : 'Fail').bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500),
|
||||||
|
// ],
|
||||||
|
// ).expanded,
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
status = !status;
|
||||||
|
model.status = status.toString();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 99.toScreenWidth,
|
||||||
|
height: 40.toScreenHeight,
|
||||||
|
padding: EdgeInsetsDirectional.all(4.toScreenHeight),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.fieldBgColor(context),
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
buildToggleOption(
|
||||||
|
label: "PASS",
|
||||||
|
isActive: status,
|
||||||
|
activeColor: AppColor.green20,
|
||||||
|
inactiveColor: Colors.transparent,
|
||||||
|
textColor: status
|
||||||
|
? AppColor.green50
|
||||||
|
: context.isDark
|
||||||
|
? Colors.white
|
||||||
|
: AppColor.black20,
|
||||||
|
),
|
||||||
|
buildToggleOption(
|
||||||
|
label: "FAIL",
|
||||||
|
isActive: !status,
|
||||||
|
activeColor: AppColor.red20,
|
||||||
|
inactiveColor: Colors.transparent,
|
||||||
|
textColor: status
|
||||||
|
? context.isDark
|
||||||
|
? Colors.white
|
||||||
|
: AppColor.black20
|
||||||
|
: AppColor.red30,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).paddingOnly(top: 4, bottom: 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildToggleOption({
|
||||||
|
required String label,
|
||||||
|
required bool isActive,
|
||||||
|
required Color activeColor,
|
||||||
|
required Color inactiveColor,
|
||||||
|
required Color textColor,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
width: 44.toScreenWidth,
|
||||||
|
height: 30.toScreenHeight,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isActive ? activeColor : inactiveColor,
|
||||||
|
borderRadius: BorderRadius.circular(3),
|
||||||
|
),
|
||||||
|
child: label.bodyText2(context).custom(color: textColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//older widget ...
|
||||||
|
// 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!),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
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/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/new_views/app_style/app_color.dart';
|
||||||
|
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||||
|
|
||||||
|
class TechnicalInspectionAssetCard extends StatelessWidget {
|
||||||
|
TechnicalInspectionAssetModel assetModel;
|
||||||
|
bool isViewOnly;
|
||||||
|
bool ischild;
|
||||||
|
VoidCallback? editPress;
|
||||||
|
|
||||||
|
TechnicalInspectionAssetCard({
|
||||||
|
super.key,
|
||||||
|
required this.isViewOnly,
|
||||||
|
this.ischild = false,
|
||||||
|
required this.assetModel,
|
||||||
|
this.editPress,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (!ischild) ...[
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: getAssetStatus(),
|
||||||
|
radius: 4,
|
||||||
|
textColor: getAssetStatusColor(context: context, status: getAssetStatus(), isBackground: false),
|
||||||
|
backgroundColor: getAssetStatusColor(context: context, status: getAssetStatus()),
|
||||||
|
),
|
||||||
|
if (!isViewOnly)
|
||||||
|
'edit_icon'.toSvgAsset().onPress(() {
|
||||||
|
if (editPress != null) {
|
||||||
|
editPress!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
if (ischild) ...[
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Asset Number: ${assetModel.assetNumber ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
if (!isViewOnly)
|
||||||
|
'edit_icon'.toSvgAsset().onPress(() {
|
||||||
|
if (editPress != null) {
|
||||||
|
editPress!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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?.model ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Manufacturer: ${assetModel.modelDefinition?.manufacturer ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Serial Number: ${assetModel.serialNo ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'System ID: ${assetModel.systemId ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).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';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
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 {
|
||||||
|
CostCenterModel costModel;
|
||||||
|
VoidCallback? editPress;
|
||||||
|
bool isViewOnly;
|
||||||
|
|
||||||
|
TechnicalInspectionCostCard({
|
||||||
|
super.key,
|
||||||
|
required this.costModel,
|
||||||
|
this.editPress,
|
||||||
|
required this.isViewOnly,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
//need to check this @waseem.
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
'Cost Center Name: ${costModel.costCenterName ?? '-'}',
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
8.width,
|
||||||
|
if (!isViewOnly)
|
||||||
|
'edit_icon'.toSvgAsset(height: 18, width: 18).onPress(() {
|
||||||
|
if (editPress != null) {
|
||||||
|
editPress!();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Quantity: ${costModel.quantity ?? '-'}',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20, padding: 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,284 @@
|
|||||||
|
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/helper_function.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/asset_delivery_stage_tab_page.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_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
|
||||||
|
State<TechnicalInspectionLinesListView> createState() => _TechnicalInspectionLinesListViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLinesListView> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
// appBar: DefaultAppBar(
|
||||||
|
// title: 'Technical Inspection'.addTranslation,
|
||||||
|
// titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
// ),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: (isLoading)
|
||||||
|
? const CircularProgressIndicator(color: AppColor.primary10).center
|
||||||
|
: (technicalInspectionLinesList.isEmpty)
|
||||||
|
? const NoDataFound().center
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ListView.separated(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
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),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).expanded,
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: !viewOnly
|
||||||
|
? Column(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap),
|
||||||
|
16.height,
|
||||||
|
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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
children: [
|
||||||
|
AppFilledButton(
|
||||||
|
buttonColor: AppColor.white60,
|
||||||
|
label: 'Attachments'.addTranslation,
|
||||||
|
maxWidth: true,
|
||||||
|
textColor: AppColor.black10,
|
||||||
|
onPressed: () {
|
||||||
|
HelperFunction.attachmentTap(
|
||||||
|
context: context, viewOnly: true, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
}).expanded,
|
||||||
|
8.width,
|
||||||
|
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//May be need to show data.
|
||||||
|
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 _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 {
|
||||||
|
HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
|
||||||
|
// Navigator.push(
|
||||||
|
// context,
|
||||||
|
// MaterialPageRoute(
|
||||||
|
// builder: (context) => AssetDeliveryAttachmentView(
|
||||||
|
// tableItemId: widget.deliveryTableModel.id,
|
||||||
|
// )));
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
// requestModel: widget.requestModel,
|
||||||
|
// deliveryTableModel: widget.deliveryTableModel,
|
||||||
|
// )));
|
||||||
|
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => AssetDeliveryStageTabPage(
|
||||||
|
title: 'End-User Acceptance'.addTranslation,
|
||||||
|
detailWidget: EndUserCostCenterLIstView(
|
||||||
|
deliveryTableModel: widget.deliveryTableModel,
|
||||||
|
requestModel: widget.requestModel,
|
||||||
|
),
|
||||||
|
tableId: widget.deliveryTableModel.id,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
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/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
|
||||||
|
State<TechnicalInspectionParentAssetListView> createState() => _TechnicalInspectionParentAssetListViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TechnicalInspectionParentAssetListViewState extends State<TechnicalInspectionParentAssetListView> {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Technical Inspection'.addTranslation,
|
||||||
|
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
body:Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: parentAssetList(context), // parentAssetList already returns a ListView
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget parentAssetList(BuildContext context) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,472 @@
|
|||||||
|
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/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/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_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 'package:test_sa/providers/loading_list_notifier.dart';
|
||||||
|
import 'package:test_sa/views/widgets/date_and_time/date_picker.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';
|
||||||
|
|
||||||
|
class UpdateChildAssetView extends StatefulWidget {
|
||||||
|
final TechnicalInspectionAssetModel assetModel;
|
||||||
|
final int? lineId;
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
UpdateChildAssetView({
|
||||||
|
Key? key,
|
||||||
|
required this.assetModel,
|
||||||
|
required this.index,
|
||||||
|
this.lineId,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UpdateChildAssetView> createState() => _UpdateChildAssetViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Child Details'.addTranslation,
|
||||||
|
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
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);
|
||||||
|
populateTextFields(model: provider.childFormModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Asset Name'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.assetName,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Model'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.model,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Manufacturer'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.manufacturer ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Serial Number'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
controller: serialNoCtrl,
|
||||||
|
initialValue: model.serialNo ?? '',
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
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 {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
if (assetDeliveryProvider.childFormModel.installationDate == null) {
|
||||||
|
"Installation Date is Required".showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_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) => InspectionCheckListView(
|
||||||
|
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'
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,521 @@
|
|||||||
|
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/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/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/pages/technical_inpection/technical_inpection_asset_card_view.dart';
|
||||||
|
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_child_asset_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/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 '../../../../models/new_models/department.dart';
|
||||||
|
import '../../../../new_views/common_widgets/app_filled_button.dart';
|
||||||
|
import '../../../../new_views/common_widgets/default_app_bar.dart';
|
||||||
|
|
||||||
|
class UpdateParentAssetView extends StatefulWidget {
|
||||||
|
final TechnicalInspectionAssetModel assetModel;
|
||||||
|
final int? lineId;
|
||||||
|
final int? tableItemId;
|
||||||
|
final int? costCenterItemId;
|
||||||
|
|
||||||
|
UpdateParentAssetView({
|
||||||
|
Key? key,
|
||||||
|
required this.assetModel,
|
||||||
|
this.lineId,
|
||||||
|
this.tableItemId,
|
||||||
|
this.costCenterItemId,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UpdateParentAssetView> createState() => _UpdateParentAssetViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateParentAssetViewState extends State<UpdateParentAssetView> {
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
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.isLoading = true;
|
||||||
|
assetDeliveryProvider.setParentModel(widget.assetModel);
|
||||||
|
if (widget.assetModel.site != null) {
|
||||||
|
await assetDeliveryProvider.getSiteData(siteId: widget.assetModel.site?.id, model: assetDeliveryProvider.parentFormModel);
|
||||||
|
} else {
|
||||||
|
if (siteProvider.items.isEmpty) {
|
||||||
|
await siteProvider.getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
populateTextFields(model: assetDeliveryProvider.parentFormModel);
|
||||||
|
assetDeliveryProvider.isLoading = 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Parent Details'.addTranslation,
|
||||||
|
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Consumer<AssetDeliveryProvider>(builder: (context, provider, child) {
|
||||||
|
return provider.isLoading
|
||||||
|
? 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,
|
||||||
|
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);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
childList(
|
||||||
|
context: context,
|
||||||
|
provider: provider,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, borderRadius: 20, padding: 12))
|
||||||
|
.expanded,
|
||||||
|
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget childList({required BuildContext context, required AssetDeliveryProvider provider}) {
|
||||||
|
final List<TechnicalInspectionAssetModel> assetDeliveryTableList = provider.parentFormModel.childAssetList ?? [];
|
||||||
|
return ListView.separated(
|
||||||
|
itemCount: assetDeliveryTableList.length,
|
||||||
|
separatorBuilder: (_, __) => 8.height,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (listContext, itemIndex) {
|
||||||
|
TechnicalInspectionAssetModel model = assetDeliveryTableList[itemIndex];
|
||||||
|
return TechnicalInspectionAssetCard(
|
||||||
|
assetModel: model,
|
||||||
|
ischild: true,
|
||||||
|
editPress: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => UpdateChildAssetView(
|
||||||
|
assetModel: model,
|
||||||
|
index: itemIndex,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
isViewOnly: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Need to make reuseable as used in parent and child both.
|
||||||
|
|
||||||
|
Widget inspectionDetailsForm({
|
||||||
|
int? lineId,
|
||||||
|
required AssetDeliveryProvider provider,
|
||||||
|
}) {
|
||||||
|
TechnicalInspectionAssetModel model = provider.parentFormModel;
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
//Replace with simple container...
|
||||||
|
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.setParentModel(assetModel);
|
||||||
|
if (assetModel.site != null) {
|
||||||
|
await provider.getSiteData(siteId: assetModel.site?.id, model: provider.parentFormModel);
|
||||||
|
}
|
||||||
|
assetModel.assetDeliveryInternalDetailAssetId = assetModel.id;
|
||||||
|
assetModel.id = 0;
|
||||||
|
if (assetModel.childAssetList != null && assetModel.childAssetList!.isNotEmpty) {
|
||||||
|
for (var asset in assetModel.childAssetList!) {
|
||||||
|
asset.assetDeliveryInternalDetailAssetChildId = asset.id;
|
||||||
|
asset.id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
provider.setParentModel(assetModel);
|
||||||
|
log('child list length ${assetModel.childAssetList?.length}');
|
||||||
|
|
||||||
|
populateTextFields(model: provider.parentFormModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Asset Name'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.assetName,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Model'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.model,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Manufacturer'.addTranslation,
|
||||||
|
// backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.modelDefinition?.manufacturer ?? '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
enable: false,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Serial Number'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
controller: serialNoCtrl,
|
||||||
|
initialValue: model.serialNo ?? '',
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
//Need to check whare the picker start for now start from start of year
|
||||||
|
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.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 {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
if (assetDeliveryProvider.parentFormModel.installationDate == null) {
|
||||||
|
"Installation Date is Required".showToast;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_formKey.currentState!.save();
|
||||||
|
assetDeliveryProvider.parentFormModel.lineId = widget.lineId;
|
||||||
|
|
||||||
|
assetDeliveryProvider.parentFormModel.tableItemId = widget.tableItemId;
|
||||||
|
assetDeliveryProvider.parentFormModel.costCenterId = widget.costCenterItemId;
|
||||||
|
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||||
|
await assetDeliveryProvider.saveTechnicalInspectionAssetData(model: assetDeliveryProvider.parentFormModel).then((status) async {
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (status) {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> openInspectionChecklist(BuildContext context) async {
|
||||||
|
applyInspectionFlagsToChecklist(model: assetDeliveryProvider.parentFormModel);
|
||||||
|
final result = await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => InspectionCheckListView(
|
||||||
|
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.parentFormModel.flagphysicalInspection = _isPass(checklist, 'Physical Inspection As Per Manufacturer Instructions');
|
||||||
|
assetDeliveryProvider.parentFormModel.flagFunctionPerformance = _isPass(checklist, 'Functional Performance As Per Results Of Manufacturer Recommended Check List');
|
||||||
|
assetDeliveryProvider.parentFormModel.flagGroundingResistance = _isPass(checklist, 'Grounding Resistance: Ω');
|
||||||
|
assetDeliveryProvider.parentFormModel.flagChassiss = _isPass(checklist, 'Chassis Leakage Current: µA');
|
||||||
|
assetDeliveryProvider.parentFormModel.flagLeadsLeakage = _isPass(checklist, 'Leads Leakage Current: µA');
|
||||||
|
assetDeliveryProvider.parentFormModel.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' : 'FAIL';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,285 @@
|
|||||||
|
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/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_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/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
|
||||||
|
State<UpdateTechnicalInspectionLinesView> createState() => _UpdateTechnicalInspectionLinesViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
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(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(
|
||||||
|
title: 'Technical Inspection'.addTranslation,
|
||||||
|
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
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) {
|
||||||
|
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(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget inspectionDetailsForm() {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
SingleItemDropDownMenu<Lookup, PowerSupplyTypeProvider>(
|
||||||
|
context: context,
|
||||||
|
height: 56.toScreenHeight,
|
||||||
|
title: 'Power Supply Type'.addTranslation,
|
||||||
|
titleTextColor: AppColor.neutral120,
|
||||||
|
showShadow: false,
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null) return 'Please select power supply type';
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
showAsBottomSheet: true,
|
||||||
|
initialValue: model.powerSupplyType,
|
||||||
|
onSelect: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
model.powerSupplyType = value;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Power Reading'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.powerReading != null ? model.powerReading.toString() : '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
showShadow: false,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
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: model.maxCurrent != null ? model.maxCurrent.toString() : '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
showShadow: false,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onSaved: (value) {
|
||||||
|
model.maxCurrent = int.tryParse(value);
|
||||||
|
},
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Voltage'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
initialValue: model.voltage != null ? model.voltage.toString() : '',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onSaved: (value) {
|
||||||
|
model.voltage = int.tryParse(value);
|
||||||
|
},
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
AppTextFormField(
|
||||||
|
labelText: 'Frequency'.addTranslation,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
initialValue: model.frequency != null ? model.frequency.toString() : '',
|
||||||
|
textInputType: TextInputType.number,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
validator: (value) {
|
||||||
|
if ((value ?? "").isEmpty) return "Mandatory";
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onSaved: (value) {
|
||||||
|
model.frequency = int.tryParse(value);
|
||||||
|
},
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle,
|
||||||
|
showShadow: false,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _saveTap() async {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,736 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'package:flutter/material.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/models/generic_attachment_model.dart';
|
||||||
|
import 'package:test_sa/models/module_permissions_model.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/cost_center_serial_no_form_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;
|
||||||
|
AssetDeliveryDataModel? assetDeliveryDataModel;
|
||||||
|
List<AssetDeliveryTableModel> assetDeliveryTableList = [];
|
||||||
|
List<DeliveryLineModel> deliveryLinesList = [];
|
||||||
|
ModulesPermissionsModel? modelPermission;
|
||||||
|
TechnicalInspectionAssetModel parentFormModel = TechnicalInspectionAssetModel();
|
||||||
|
TechnicalInspectionAssetModel childFormModel = TechnicalInspectionAssetModel();
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
pageNo = 1;
|
||||||
|
stateCode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int? stateCode;
|
||||||
|
bool isDetailLoading = false;
|
||||||
|
bool nextPage = false;
|
||||||
|
bool isLoading = false;
|
||||||
|
bool isSiteLoading = false;
|
||||||
|
bool isDeliveryTableListLoading = false;
|
||||||
|
bool isDeliveryLineListLoading = false;
|
||||||
|
bool isChildAssetDataLoading = false;
|
||||||
|
|
||||||
|
void setParentModel(TechnicalInspectionAssetModel m) {
|
||||||
|
parentFormModel = m;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChildModel(TechnicalInspectionAssetModel m) {
|
||||||
|
childFormModel = m;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AssetDeliveryDataModel?> getAssetDeliveryDetailById({int? requestId}) async {
|
||||||
|
try {
|
||||||
|
assetDeliveryDataModel = AssetDeliveryDataModel();
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
final response = await ApiManager.instance.get(URLs.getAssetDeliveryDetailsById + "?Id=$requestId");
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
assetDeliveryDataModel = AssetDeliveryDataModel.fromJson(json.decode(response.body)["data"]);
|
||||||
|
} else {
|
||||||
|
assetDeliveryDataModel = null;
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return assetDeliveryDataModel;
|
||||||
|
} catch (e) {
|
||||||
|
log("getdelivery details [error] : $e");
|
||||||
|
isLoading = false;
|
||||||
|
assetDeliveryDataModel = null;
|
||||||
|
notifyListeners();
|
||||||
|
return assetDeliveryDataModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getAssetDeliveryTableListById({int? requestId}) async {
|
||||||
|
try {
|
||||||
|
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 jsonData = json.decode(response.body)["data"];
|
||||||
|
if (jsonData is List) {
|
||||||
|
assetDeliveryTableList = jsonData.map((e) => AssetDeliveryTableModel.fromJson(e)).toList();
|
||||||
|
} else {
|
||||||
|
assetDeliveryTableList = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assetDeliveryTableList = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
isDeliveryTableListLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
log("get Delivery Table details [error] : $e");
|
||||||
|
isDeliveryTableListLoading = false;
|
||||||
|
assetDeliveryTableList = [];
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<DeliveryLineModel>> getTechnicalInspectionLinesListById({int? itemId}) async {
|
||||||
|
List<DeliveryLineModel> linesList = [];
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
final response = await ApiManager.instance.get(
|
||||||
|
"${URLs.getLineFromTechnicalInspection}?assetDeliveryExternalDeliveryId=$itemId",
|
||||||
|
);
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
final jsonData = json.decode(response.body)["data"];
|
||||||
|
if (jsonData is List) {
|
||||||
|
linesList = jsonData.map((e) => DeliveryLineModel.fromJson(e)).toList();
|
||||||
|
} else {
|
||||||
|
assetDeliveryTableList = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
linesList = [];
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return linesList;
|
||||||
|
} catch (e) {
|
||||||
|
log("get Delivery Lines List [error] : $e");
|
||||||
|
isLoading = false;
|
||||||
|
linesList = [];
|
||||||
|
notifyListeners();
|
||||||
|
return linesList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<CostCenterSerialNoFormModel> getAssetDeliveryCostCenterListForLines({
|
||||||
|
int? lineId,
|
||||||
|
int? tableItemId,
|
||||||
|
}) async {
|
||||||
|
CostCenterSerialNoFormModel costCenterSerialNoFormModel = CostCenterSerialNoFormModel();
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
final response = await ApiManager.instance.get(
|
||||||
|
"${URLs.getCostCenterAndSerialNoToLineDeliveryInspection}?AssetDeliveryExternalDetailId=$lineId&AssetDeliveryExternalDeliveryId=$tableItemId",
|
||||||
|
);
|
||||||
|
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
final jsonData = json.decode(response.body)["data"];
|
||||||
|
costCenterSerialNoFormModel = CostCenterSerialNoFormModel.fromJson(jsonData);
|
||||||
|
} else {
|
||||||
|
costCenterSerialNoFormModel.costCenters = [];
|
||||||
|
costCenterSerialNoFormModel.serialNos = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log("get Delivery Lines List [error] : $e");
|
||||||
|
costCenterSerialNoFormModel.costCenters = [];
|
||||||
|
costCenterSerialNoFormModel.serialNos = [];
|
||||||
|
} finally {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
return costCenterSerialNoFormModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.saveTechnicalInspection, 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<bool> saveCostCenterToLineDeliveryInspection({
|
||||||
|
int? tableItemId,
|
||||||
|
int? lineId,
|
||||||
|
List<CostCenterModel>? list,
|
||||||
|
List<SerialNoModel>? serialNoList,
|
||||||
|
}) async {
|
||||||
|
isLoading = true;
|
||||||
|
Map<String, dynamic> payload = {
|
||||||
|
"assetDeliveryExternalDeliveryId": tableItemId,
|
||||||
|
"assetDeliveryExternalDetailId": lineId,
|
||||||
|
"costCenters": list?.map((x) => x.toJson()).toList(),
|
||||||
|
if (serialNoList != null && serialNoList.isNotEmpty) "serialNos": serialNoList.map((x) => x.toJson()).toList(),
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
final response = await ApiManager.instance.post(URLs.saveCostCenterAndSerialNoToLineDeliveryInspection, 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<bool> changeDeliveryStatusToCancel({int? itemId}) async {
|
||||||
|
isLoading = true;
|
||||||
|
try {
|
||||||
|
final response = await ApiManager.instance.get(
|
||||||
|
"${URLs.changeDeliveryStatusToCancel}?assetDeliveryExternalDeliveryId=$itemId",
|
||||||
|
);
|
||||||
|
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> changeDeliveryStatus({
|
||||||
|
int? itemId,
|
||||||
|
Map<String, dynamic>? requestPayload,
|
||||||
|
}) async {
|
||||||
|
isLoading = true;
|
||||||
|
Map<String, dynamic> payload = {
|
||||||
|
'assetDeliveryExternalDeliveryId': itemId,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
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("getAssetDeliveryInspectionData details [error] : $e");
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return deliveryInspectionFormModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TechnicalInspectionFormModel> getTechnicalInspectionData({int? lineId, int? tableId}) async {
|
||||||
|
isLoading = true;
|
||||||
|
TechnicalInspectionFormModel technicalInspectionFormModel = TechnicalInspectionFormModel();
|
||||||
|
try {
|
||||||
|
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"]);
|
||||||
|
}
|
||||||
|
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"]);
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return list;
|
||||||
|
} catch (error) {
|
||||||
|
log('error $error');
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<GenericAttachmentModel>> getAttachments({
|
||||||
|
num? tableItemId,
|
||||||
|
num? attachmentType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
final response = await ApiManager.instance.get("${URLs.getAttachments}?attachmentDocTypeValue=$attachmentType&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) => GenericAttachmentModel.fromJson(e)).toList();
|
||||||
|
}
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return list;
|
||||||
|
} catch (error) {
|
||||||
|
log('error $error');
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
try {
|
||||||
|
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 null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> saveAttachment({
|
||||||
|
required Map<String, dynamic> payload,
|
||||||
|
}) async {
|
||||||
|
isLoading = true;
|
||||||
|
try {
|
||||||
|
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;
|
||||||
|
notifyListeners();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 AttachmentTypeLookupProvider 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.attachmentTypeLookup);
|
||||||
|
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,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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,174 @@
|
|||||||
|
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;
|
||||||
|
String? lastModifiedBy;
|
||||||
|
|
||||||
|
/// ✅ 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,
|
||||||
|
this.lastModifiedBy,
|
||||||
|
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'];
|
||||||
|
lastModifiedBy = json['lastModifiedBy'];
|
||||||
|
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,
|
||||||
|
'lastModifiedBy': lastModifiedBy,
|
||||||
|
'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,384 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.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/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,
|
||||||
|
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,
|
||||||
|
|
||||||
|
//Older design code
|
||||||
|
// 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,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
if (formModel.deliveredItemList.isNotEmpty) ...[
|
||||||
|
_ItemRowLayout(
|
||||||
|
left: 'Items'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)),
|
||||||
|
right: 'Delivered Qty'.addTranslation.bodyText(context).custom(color: AppColor.textColor(context)),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
ListView.separated(
|
||||||
|
separatorBuilder: (_, __) => 12.height,
|
||||||
|
itemCount: formModel.deliveredItemList.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
MedicalGasRequestDetailModel model = formModel.deliveredItemList[index];
|
||||||
|
return itemQuantityFieldWidget(index: index, model: model, context: context);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
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 formModel.deliveredItemList) {
|
||||||
|
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);
|
||||||
|
if (formModel.isSubmitted == true) {
|
||||||
|
AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
|
||||||
|
allRequestsProvider.reset();
|
||||||
|
await allRequestsProvider.getAllRequests(context, typeTransaction: 14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget itemQuantityFieldWidget({
|
||||||
|
required int index,
|
||||||
|
required MedicalGasRequestDetailModel model,
|
||||||
|
required BuildContext context,
|
||||||
|
}) {
|
||||||
|
final border = OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
borderSide: const BorderSide(color: AppColor.white70, width: 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
return _ItemRowLayout(
|
||||||
|
left: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
model.itemName!.bodyText2(context).custom(
|
||||||
|
color: context.isDark ? Colors.white : AppColor.white936,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
'Req Qty ${model.requestedQuantity}'.bodyText2(context).custom(
|
||||||
|
color: context.isDark ? Colors.white : AppColor.white936,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
right: TextFormField(
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
initialValue: model.deliveredQuantity != null ? model.deliveredQuantity?.toStringAsFixed(0) : '',
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth),
|
||||||
|
filled: true,
|
||||||
|
fillColor: AppColor.fieldBgColor(context),
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: 30.toScreenHeight,
|
||||||
|
),
|
||||||
|
border: border,
|
||||||
|
enabledBorder: border,
|
||||||
|
focusedBorder: border,
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
model.deliveredQuantity = int.tryParse(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ItemRowLayout extends StatelessWidget {
|
||||||
|
final Widget left;
|
||||||
|
final Widget right;
|
||||||
|
|
||||||
|
const _ItemRowLayout({
|
||||||
|
required this.left,
|
||||||
|
required this.right,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(child: left), // Items column
|
||||||
|
SizedBox(
|
||||||
|
width: 100.toScreenWidth, // Delivered Qty column
|
||||||
|
child: right,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue