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