asset delivery modules design flow completed

design_3.0_asset_delivery_module
WaseemAbbasi22 3 months ago
parent b407103002
commit 789522b79b

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

@ -0,0 +1,27 @@
import 'package:test_sa/models/lookup.dart';
class CostCenterModel {
Lookup? costCenter;
double? quantity;
CostCenterModel({
this.costCenter,
this.quantity,
});
CostCenterModel.fromJson(Map<String, dynamic> json) {
costCenter = json['costCenter'] != null
? Lookup.fromJson(json['costCenter'])
: null;
quantity = json['quantity'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
if (costCenter != null) {
data['costCenter'] = costCenter!.toJson();
}
data['quantity'] = quantity;
return data;
}
}

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

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

@ -0,0 +1,113 @@
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: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// StatusLabel(
// label: requestData!.statusName!,
// textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!),
// backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!),
// ),
// 1.width.expanded,
// Text(
// requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
// ),
// ],
// ),
8.height,
'Asset Delivery'.addTranslation.heading5(context),
infoWidget(label: 'Delivery Type'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Assets'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Sites'.addTranslation, value: '-', context: context),
// 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: (_) => AssetInventoryPage(sessionId: requestData!.id!, moduleId: requestData!.transactionNo!)));
});
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// StatusLabel(
// label: requestDetails!.status!,
// textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!),
// backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!),
// ),
// 1.width.expanded,
// Text(
// requestDetails!.date?.toServiceRequestCardFormat ?? "",
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
// ),
// ],
// ),
8.height,
'Asset Delivery'.addTranslation.heading5(context),
infoWidget(label: 'Delivery Type'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Assets'.addTranslation, value: '-', context: context),
infoWidget(label: 'No of Sites'.addTranslation, value: '-', context: context),
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!)));
});
}
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,75 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class AssetDeliveryLineCard extends StatelessWidget {
///Need to replace with Lines model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
bool isViewOnly;
VoidCallback ?editPress;
AssetDeliveryLineCard({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
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 No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
],
),
Text(
'Item Description: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Quantity: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Remaining Quantity: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Quantity of this Delivery: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Marge Unit: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Unit price: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Total: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
}

@ -0,0 +1,249 @@
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/new_models/site.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_detail_page.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_table_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/change_status_bottomsheet.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/delivery_inspection_form_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/session_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryPage extends StatefulWidget {
final int? requestId;
const AssetDeliveryPage({
Key? key,
this.requestId,
}) : super(key: key);
@override
State<AssetDeliveryPage> createState() => _AssetDeliveryPageState();
}
class _AssetDeliveryPageState extends State<AssetDeliveryPage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'Asset Delivery'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: widget.requestId == null
? const NoDataFound()
: ListView(
padding: const EdgeInsets.all(12),
children: [
requestDetailCard(context),
// const SizedBox(height: 12),
const Divider().defaultStyle(context),
assetDeliveryTableList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 0, margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 12)),
);
}
TextStyle infoTextStyle(context) => AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120);
Widget requestDetailCard(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// //
// StatusLabel(
// label: sessionModel.statusName,
// id: sessionModel.statusId,
// radius: 4,
// textColor: AppColor.getRequestStatusTextColorByName(context, sessionModel.statusName),
// backgroundColor: AppColor.getRequestStatusColorByName(context, sessionModel.statusName),
// // textColor: AppColor.green15,
// // backgroundColor: AppColor.greenStatus(context),
// ),
// Text(
// sessionModel.createdDate!.toString().toServiceRequestCardFormat,
// textAlign: TextAlign.end,
// style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
// )
// ],
// ),
8.height,
//neutral120
Text(
'PO No. Internal'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'PO8745623'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: true,
activeColor: AppColor.neutral120,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
onChanged: (value) {},
),
8.width,
Text(
'HMS'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
],
),
8.height,
Text(
'Operation Units'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'50'.addTranslation,
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,
Text(
'PO438'.addTranslation,
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(
'1 Year'.addTranslation,
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(
'70%'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'EDD (Estimated Delivery Date)'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'25 December, 2025'.addTranslation,
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(
'4930'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
Widget assetDeliveryTableList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Asset Delivery Table",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
Container(
height: 24,
width: 24,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColor.primary10, // or AppColor.blueStatus(context)
),
alignment: Alignment.center,
child: const Icon(
Icons.add,
color: Colors.white,
size: 16,
),
).onPress(() {
//add entry into table.
}),
// AppFilledButton(
// label: '',
// maxWidth: true,
// textColor: AppColor.textColor(context),
// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
// icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
// showIcon: true,
// onPressed: (){
//
// },
// )
],
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryTableCard(
deliveryDetails: AssetInventoryModel(),
onCardTap: () {
///TODO need to display bottomsheet to change status if new...
// if(status=='NEW')
// AssetDeliveryBottomSheet.changeStatusBottomSheet(context: context);
Navigator.of(context).push(MaterialPageRoute(builder: (_) => AssetDeliveryDetailPage(requestId: 13,)));
},
onViewHistoryPress: () {},
);
},
),
],
);
}
}

@ -0,0 +1,75 @@
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_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryTableCard extends StatelessWidget {
//Need to replace with AssetTableCard.
AssetInventoryModel deliveryDetails;
VoidCallback onViewHistoryPress;
VoidCallback onCardTap;
AssetDeliveryTableCard({
super.key,
required this.deliveryDetails,
required this.onViewHistoryPress,
required this.onCardTap,
});
@override
Widget build(BuildContext context) {
deliveryDetails.status = 'New';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: deliveryDetails.status,
textColor: AppColor.getRequestStatusTextColorByName(context, deliveryDetails.status),
backgroundColor: AppColor.getRequestStatusColorByName(context, deliveryDetails.status),
),
Row(
children: [
'history_icon'.toSvgAsset(),
6.width,
Text(
'View History'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
),
],
).onPress(() {
onViewHistoryPress();
}),
],
),
8.height,
Text(
'Delivery Number: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Delivery Amount: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Invoice Amount: ${deliveryDetails.assetName ?? '-'}',
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,60 @@
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}) {
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,
),),
),
10.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: () {
Navigator.pop(context);
},
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: () {}).expanded,
],
),
],
));
}
}

@ -0,0 +1,213 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/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_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/lookups/request_type_lookup_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart';
class CostCenterFormView extends StatefulWidget {
final List<CostCenterModel>? costCenterList;
final ValueChanged<List<CostCenterModel>>? onListChanged;
final double? cardPadding;
const CostCenterFormView({
super.key,
this.costCenterList,
this.onListChanged,
this.cardPadding,
});
@override
State<CostCenterFormView> createState() => _CostCenterFormViewState();
}
class _CostCenterFormViewState extends State<CostCenterFormView> {
late List<CostCenterModel> _list;
@override
void initState() {
super.initState();
_list = List<CostCenterModel>.from(widget.costCenterList ?? []);
}
void _addNewEntry() {
setState(() {
_list.add(CostCenterModel());
});
widget.onListChanged?.call(_list);
}
void _removeEntry(int index) {
setState(() {
_list.removeAt(index);
});
widget.onListChanged?.call(_list);
}
void _updateModel(int index, void Function(CostCenterModel model) updateList) {
setState(() {
updateList(_list[index]);
});
}
@override
Widget build(BuildContext context) {
///Need to add check if status changes..
final isReadOnly = Provider.of<CMDetailProvider>(context, listen: false).isReadOnlyRequest;
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar(
title: 'Cost Center for Item'.addTranslation,
onBackPress: () {
Navigator.pop(context);
},
),
body: Column(
children: [
ListView.builder(
itemCount: _list.length + 1,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(widget.cardPadding ?? 16),
itemBuilder: (context, index) {
if (index == _list.length) {
return Visibility(
visible: !isReadOnly,
child: AppFilledButton(
label: "Add Cost Center".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: _addNewEntry,
),
);
}
return CostCenterItemCard(
model: _list[index],
index: index,
isReadOnly: isReadOnly,
onUpdate: (updateList) => _updateModel(index, updateList),
onRemove: () => _removeEntry(index),
);
},
).expanded,
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: () {}),
),
],
),
);
}
}
class CostCenterItemCard extends StatelessWidget {
final CostCenterModel model;
final int index;
final bool isReadOnly;
final void Function(void Function(CostCenterModel model)) onUpdate;
final VoidCallback onRemove;
const CostCenterItemCard({
super.key,
required this.model,
required this.index,
required this.isReadOnly,
required this.onUpdate,
required this.onRemove,
});
@override
Widget build(BuildContext context) {
final requestedDate = Provider.of<CMDetailProvider>(context, listen: false).currentWorkOrder?.data?.requestedDate;
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: [
///TODO replace with exact data or type like searchable dropdown...
AppTextFormField(
labelText: 'Item No'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '232434',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Item Description',
backgroundColor: AppColor.fieldBgColor(context),
initialValue: 'test decription abc',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
LookUpAutoCompleteField(
clearAfterPick: false,
forAssetName: true,
onChanged: (value) {},
initialValue: model.costCenter?.name ?? '',
label: 'Cost Center'.addTranslation,
onPick: (value) {
model.costCenter = value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, RequestTypeLookupProvider>(
context: context,
showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
title: 'Quantity'.addTranslation,
initialValue: model.costCenter,
onSelect: (value) {
model.costCenter = value;
},
),
],
)
],
).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16, vertical: 12)).paddingOnly(bottom: 12);
}
}

@ -0,0 +1,378 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/cost_center_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_lines_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class DeliveryInspectionFormView extends StatefulWidget {
static const String id = "/delivery-inspection-form";
DeliveryInspectionFormView({
Key? key,
}) : super(key: key);
@override
State<DeliveryInspectionFormView> createState() => _DeliveryInspectionFormViewState();
}
class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool viewOnly = true;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!viewOnly) ...[inspectionDetailsForm()] else ...[inspectionDetails()],
8.height,
const Divider().defaultStyle(context),
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
),
),
],
),
);
}
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryLineCard(
deliveryDetails: AssetInventoryModel(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CostCenterFormView(
costCenterList: [CostCenterModel()],
onListChanged: (updatedList) {
// requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployList = updatedList;
},
)));
},
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
// LookUpAutoCompleteField(
// clearAfterPick: false,
// forAssetName: true,
// onChanged: (value) {
// _scannedAssetModel?.newAssetNameId = null;
// _scannedAssetModel?.newAssetNameText = value;
// },
// initialValue: _scannedAssetModel?.assetName ?? "",
// label: 'Asset Name'.addTranslation,
// onPick: (value) {
// _scannedAssetModel?.newAssetNameText = null;
// _scannedAssetModel?.assetName = value.name;
// _scannedAssetModel?.newAssetNameId = value.id;
// setState(() {});
// },
// ),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time To'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
],
);
}
Widget inspectionDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Inspected by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Approved by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time From'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time To'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
void _viewHistoryTap() async {}
void _cancelTap() async {}
void _nextTap() {
Navigator.push(context, MaterialPageRoute(builder: (context) => TechnicalInspectionLinesListView()));
}
void _changeStatusTap() async {
_formKey.currentState!.save();
}
}

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class CostCenterCard extends StatelessWidget {
///Need to replace with cost model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
bool isViewOnly;
VoidCallback ?editPress;
CostCenterCard({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
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 No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
],
),
Text(
'Asset Number: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Asset Type: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Replaced Asset No: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Serial Number: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
}

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

@ -0,0 +1,343 @@
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/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/update_end_user_cost_center_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_technical_inspection_lines_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class EndUserCostCenterLIstView extends StatefulWidget {
EndUserCostCenterLIstView({
Key? key,
}) : 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;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'End-User Acceptance'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
),
),
],
),
),
);
}
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
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: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return CostCenterCard(
deliveryDetails : AssetInventoryModel(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateEndUserCostCenterView()));
},
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time To'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
],
);
}
Widget inspectionDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Inspected by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Approved by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time From'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time To'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
void _viewHistoryTap() async {
}
void _cancelTap() async {
}
void _nextTap() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserCostCenterLIstView()));
}
void _changeStatusTap() async {
}
}

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

@ -0,0 +1,187 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDeliveryHistoryLogView extends StatelessWidget {
const AssetDeliveryHistoryLogView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
///Replace with provider and data..
return Consumer<CMDetailProvider>(builder: (context, requestProvider, _) {
return requestProvider.isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: (requestProvider.currentWorkOrder == null || (requestProvider.currentWorkOrder?.data?.workOrderHistory.isEmpty ?? true)
? const NoDataFound()
: Stack(
children: [
Padding(
padding: EdgeInsets.only(left: 122.toScreenWidth),
child: const VerticalDivider(
color: AppColor.white40,
thickness: 2,
width: 20,
indent: 10,
endIndent: 10,
),
),
SafeArea(
child: Builder(builder: (cxt) {
List<Widget> items = [];
String lastStatus = "";
DateTime? nextDate;
var workOrderHistory = requestProvider.currentWorkOrder!.data!.workOrderHistory;
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
if (isNurse) {
workOrderHistory.removeWhere((element) => element.step?.id == 5617);
}
for (int i = 0; i < workOrderHistory.length; i++) {
var object = workOrderHistory[i];
String currentStatus = object.workorderStatus!.name!;
if (lastStatus.isEmpty) {
lastStatus = currentStatus;
}
if (lastStatus == currentStatus) {
if (i + 1 < workOrderHistory.length) {
nextDate = workOrderHistory[i + 1].date;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.date!, nextDate!);
object.timeDifference = timeDifference;
} else {
object.timeDifference = ''; // Empty string for the last action
}
items.add(historyLogCard(cxt, object));
} else {
items.add(statusCard(cxt, lastStatus));
lastStatus = currentStatus;
if (i + 1 < workOrderHistory.length) {
nextDate = workOrderHistory[i + 1].date;
String timeDifference = CMRequestUtils.calculateTimeDifference(object.date!, nextDate!);
object.timeDifference = timeDifference;
} 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, WorkOrderHistory object) {
String title = object.step!.name!;
if (object.step!.value == 18 || object.step!.value == 27 || object.step!.value == 28) {
title = object.activityStatus?.name ?? "";
}
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
object.date.toString().toServiceRequestCardFormat,
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
).expanded,
Expanded(
flex: 2,
//....
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (object.assetVerificationType?.value == 4 && object.photoVerfication != null) ...[
Padding(
padding: EdgeInsets.symmetric(vertical: 12.toScreenWidth),
child: InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!, height: 143.toScreenHeight)),
).onPress(() async {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!)).center,
const ABackButton(),
],
),
),
),
),
);
}),
],
title.bodyText(context).custom(color: AppColor.textColor(context)),
object.timeDifference.isNotEmpty ? object.timeDifference.tinyFont(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120) : const SizedBox(),
],
),
),
],
).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.getHistoryLogStatusTextColorByName(status),
backgroundColor: AppColor.getHistoryLogStatusColorByName(status),
),
).paddingOnly(bottom: 16, start: 40);
}
String statusText(String status) {
if (status == "new" || status == "open") {
return "Open Request".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;
}
}
class HistoryLogModel {
String message;
DateTime date;
String? status;
Color? statusColor;
HistoryLogModel({required this.message, required this.date, this.status, this.statusColor});
}

@ -0,0 +1,109 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class TechnicalInspectionAssetCard extends StatelessWidget {
Asset assetModel;
///if include in model skip this
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: [
///Need to give specific colors
if (!ischild) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StatusLabel(
label: 'Pass',
radius: 4,
textColor: AppColor.getPriorityStatusTextColor(context, 1),
backgroundColor: AppColor.getPriorityStatusColor(context, 1),
),
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!();
}
}),
],
),
],
if (!ischild)
Text(
'Asset Number: ${assetModel.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Model: ${assetModel.modelDefinition ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Serial Number: ${assetModel.assetSerialNo ?? '-'}',
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),
),
if (!ischild)
Text(
'Medical Department: ${assetModel.department ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Installation Date: ${assetModel.deliveryInspectionDate ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if (!ischild)
Text(
'Asset Type: ${assetModel.assetType ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
}

@ -0,0 +1,77 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class TechnicalInspectionCostCard extends StatelessWidget {
///Need to replace with Cost model.
AssetInventoryModel deliveryDetails;
///if include in model skip this
bool isViewOnly;
VoidCallback ?editPress;
TechnicalInspectionCostCard({
super.key,
required this.isViewOnly,
required this.deliveryDetails,
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 No: ${deliveryDetails.transactionDate?.toServiceRequestDetailsFormat ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
if(!isViewOnly)
'edit_icon'.toSvgAsset().onPress(() {
if(editPress!=null){
editPress!();
}
}),
],
),
Text(
'Cost Center: ${deliveryDetails.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Power Supply Type: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Cost Center: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Power Reading: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Max Current: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Voltage: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Frequency: ${deliveryDetails.assetName ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
],
).toShadowContainer(context, borderRadius: 20, padding: 12);
}
}

@ -0,0 +1,336 @@
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/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_technical_inspection_lines_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class TechnicalInspectionLinesListView extends StatefulWidget {
TechnicalInspectionLinesListView({
Key? key,
}) : 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 = true;
@override
void initState() {
super.initState();
}
@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: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
linesList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
if (!viewOnly) ...[
8.height,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(buttonColor: AppColor.green70, label: 'Change Status'.addTranslation, maxWidth: true, onPressed: _changeStatusTap),
),
8.height,
],
FooterActionButton.footerContainer(
context: context,
child: !viewOnly
? Row(
children: [
AppFilledButton(
label: 'Cancel'.addTranslation,
maxWidth: true,
buttonColor: AppColor.background(context),
// textColor: context.isDark ? AppColor.neutral30 : Colors.white,
textColor: AppColor.red30,
showBorder: true,
onPressed: _cancelTap,
).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
],
)
: Row(
children: [
AppFilledButton(buttonColor: AppColor.black10, label: 'View History'.addTranslation, maxWidth: true, onPressed: _viewHistoryTap).expanded,
12.width,
AppFilledButton(buttonColor: AppColor.primary10, label: 'Next'.addTranslation, maxWidth: true, onPressed: _nextTap).expanded,
],
),
),
],
),
),
);
}
Widget linesList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Lines",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return AssetDeliveryLineCard(
deliveryDetails: AssetInventoryModel(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateTechnicalInspectionLinesView()));
},
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Inspected by'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Approved by'.addTranslation,
showShadow: false,
titleTextColor: AppColor.neutral120,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
ADatePicker(
label: 'Inspected Date/Time To'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
],
);
}
Widget inspectionDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Inspected by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Approved by'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'Mahmoud Shrouf'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time From'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Inspected Date/Time To'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
'19 August, 2025'.addTranslation,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
);
}
void _viewHistoryTap() async {}
void _cancelTap() async {}
void _nextTap() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => EndUserCostCenterLIstView()));
}
void _changeStatusTap() async {}
}

@ -0,0 +1,87 @@
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/device/asset.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/new_views/app_style/app_color.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class TechnicalInspectionParentAssetListView extends StatefulWidget {
TechnicalInspectionParentAssetListView({
Key? key,
}) : 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;
@override
void initState() {
super.initState();
}
@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: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: parentAssetList(context).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
),
);
}
Widget parentAssetList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Parents",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionAssetCard(
assetModel: Asset(),
isViewOnly: viewOnly,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateParentAssetView()));
},
);
},
),
],
);
}
}

@ -0,0 +1,145 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
///convert this to stateless no state needed when impleminting api's
class UpdateChildAssetView extends StatefulWidget {
///Need to pass model here...
UpdateChildAssetView({
Key? key,
}) : 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>();
bool viewOnly = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'Child Details'.addTranslation,
titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Asset Number'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTextFormField(
labelText: 'Model'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'System ID'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
}

@ -0,0 +1,258 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/update_child_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
class UpdateParentAssetView extends StatefulWidget {
UpdateParentAssetView({
Key? key,
}) : 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>();
bool viewOnly = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: DefaultAppBar(
title: 'Parent 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: [
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
8.height,
childList(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 childList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
"Test List",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.width,
'web_link_icon'.toSvgAsset().onPress((){
///Open webview...
}),
],
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionAssetCard(
assetModel: Asset(),
ischild: true,
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateChildAssetView()));
},
isViewOnly: viewOnly,
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Asset Number'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
8.height,
AppTextFormField(
labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'System ID'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Medical Department'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
ADatePicker(
label: 'Installation Date'.addTranslation,
hideShadow: true,
height: 56.toScreenHeight,
backgroundColor: AppColor.fieldBgColor(context),
// date: _pickerStartAt,
// from: widget.pickerFromDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)),
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent),
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10),
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)),
),
child: child!,
);
},
).then((selectedTime) {
if (selectedTime != null) {
// _pickerStartAt = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
// if (_pickerStartAt!.isAfter(DateTime.now())) {
// "Start time is after than current time".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
setState(() {});
}
});
},
),
8.height,
AppTextFormField(
labelText: 'Asset Type'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
],
);
}
///Need to check which details show here...
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
}

@ -0,0 +1,224 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/common_widgets/lookup_autocomplete_field.dart';
import 'package:test_sa/controllers/providers/api/all_requests_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_cost_center_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_parent_asset_list_view.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/search_asset_view.dart';
import 'package:test_sa/modules/asset_inventory_module/provider/asset_inventory_provider.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker_item.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../../../../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";
UpdateTechnicalInspectionLinesView({
Key? key,
}) : 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>();
@override
void initState() {
super.initState();
}
@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: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
inspectionDetailsForm(),
8.height,
const Divider().defaultStyle(context),
costCenterList(context),
],
).toShadowContainer(context, borderRadius: 20, padding: 12))
.expanded,
FooterActionButton.footerContainer(context: context, child: AppFilledButton(buttonColor: AppColor.primary10, label: 'Save'.addTranslation, maxWidth: true, onPressed: _saveTap)),
],
),
),
);
}
Widget costCenterList(BuildContext context) {
final assetDeliveryTableList = ['abc', 'def', 'ghi', 'fhg', 'hjhh'];
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Cost Centers",
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
ListView.separated(
itemCount: assetDeliveryTableList.length,
separatorBuilder: (_, __) => 8.height,
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (listContext, itemIndex) {
return TechnicalInspectionCostCard(
deliveryDetails: AssetInventoryModel(),
editPress: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => TechnicalInspectionParentAssetListView()));
},
isViewOnly: false,
);
},
),
],
);
}
Widget inspectionDetailsForm() {
return Column(
children: [
AppTextFormField(
labelText: 'Item No'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '232434',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Item Description',
backgroundColor: AppColor.fieldBgColor(context),
initialValue: 'test decription abc',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
SingleItemDropDownMenu<Lookup, LastSituationProvider>(
context: context,
height: 56.toScreenHeight,
title: 'Power Supply Type'.addTranslation,
titleTextColor: AppColor.neutral120,
showShadow: false,
// backgroundColor: AppColor.neutral100,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
onSelect: (status) {
if (status != null) {
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
setState(() {});
}
},
),
// 8.height,
// LookUpAutoCompleteField(
// clearAfterPick: false,
// forAssetName: true,
// onChanged: (value) {},
// initialValue: '',
// label: 'Cost Center'.addTranslation,
// onPick: (value) {},
// ),
8.height,
AppTextFormField(
labelText: 'Power Reading'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Max Current'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Voltage'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Frequency'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
],
);
}
void _saveTap() async {
AssetInventoryProvider assetInventoryProvider = Provider.of<AssetInventoryProvider>(context, listen: false);
_formKey.currentState!.save();
}
}

@ -0,0 +1,470 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/module_permissions_model.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_engineer_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/session_model.dart';
import '../../../models/service_request/search_work_order.dart';
import '../../../models/service_request/wo_call_request.dart';
import '../../../models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
class AssetDeliveryProvider extends ChangeNotifier {
final pageItemNumber = 10;
final searchPageItemNumber = 10;
int pageNo = 1;
List<AssetInventoryModel> _devices = [];
List<AssetInventoryModel> _searchDevices = [];
List<AssetInventoryModel> get devices => _devices;
List<AssetInventoryModel> get searchDevices => _searchDevices;
SessionModel? sessionModel;
//TODO need to check i think don't need to create this obj
AssetInventoryResponse? assetInventoryResponse;
AssetInventoryResponse? siteFilterAssetResponse;
List<AssetInventoryModel> sessionAssetList = [];
List<AssetInventoryModel> siteFilterAssetList = [];
ModulesPermissionsModel? modelPermission;
void reset() {
pageNo = 1;
modelPermission = null;
assetInventoryResponse = null;
sessionModel = null;
sessionAssetList = [];
stateCode = null;
}
int? stateCode;
bool isDetailLoading = false;
bool nextPage = false;
bool isNextPageLoading = false;
bool isLoading = false;
bool isAllAssetLoading = false;
void searchReset() {
stateCode = null;
_searchDevices = [];
}
Future<void> getSessionById({required int id}) async {
try {
sessionModel = SessionModel();
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(URLs.getAssetInventoryById + "?assetInventoryId=$id");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
sessionModel = SessionModel.fromJson(json.decode(response.body)["data"]);
} else {
sessionModel = null;
}
isLoading = false;
notifyListeners();
} catch (e) {
log("getSessionError [error] : $e");
isLoading = false;
sessionModel = null;
notifyListeners();
return null;
}
}
Future<int> getAssetsInSession({
required int sessionId,
bool loadMore = false,
}) async {
if (isLoading || isNextPageLoading) return -2;
if (loadMore) {
isNextPageLoading = true;
pageNo += 1;
} else {
isLoading = true;
pageNo = 1; // reset pagination
}
notifyListeners();
try {
final payload = {
"pageSize": pageItemNumber,
"pageNumber": pageNo,
"sessionId": sessionId,
};
final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final newResponse = AssetInventoryResponse.fromJson(jsonData);
if (loadMore) {
assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
assetInventoryResponse?.totalRows = newResponse.totalRows;
} else {
assetInventoryResponse = newResponse;
}
nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
} else {
nextPage = false;
}
isLoading = false;
isNextPageLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
isNextPageLoading = false;
stateCode = -1;
nextPage = false;
notifyListeners();
return -1;
}
}
///older code
// Future<int> getAssetsInSession({
// required int sessionId,
// bool loadMore = false,
// }) async {
// // if (isLoading || nextPage) return -2;
//
// if (loadMore) {
// nextPage = true;
// pageNo += 1;
// } else {
// isLoading = true;
// pageNo = 1; // reset pagination
// }
//
// notifyListeners();
// log('Fetching page: $pageNo');
//
// try {
// final payload = {
// "pageSize": pageItemNumber,
// "pageNumber": pageNo,
// "sessionId": sessionId,
// };
//
// final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
// stateCode = response.statusCode;
//
// if (response.statusCode >= 200 && response.statusCode < 300) {
// final Map<String, dynamic> jsonData = json.decode(response.body);
// final newResponse = AssetInventoryResponse.fromJson(jsonData);
//
// if (loadMore) {
// assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
// assetInventoryResponse?.totalRows = newResponse.totalRows;
// } else {
// assetInventoryResponse = newResponse;
// }
//
// nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
// }
//
// isLoading = false;
// nextPage = false;
// notifyListeners();
// return response.statusCode;
// } catch (error) {
// isLoading = false;
// nextPage = false;
// stateCode = -1;
// notifyListeners();
// return -1;
// }
// }
Future<int> getInventoryDetailsByFilter({
required Map<String, dynamic> payload,
bool loadMore = false,
}) async {
if (isLoading || isNextPageLoading) return -2;
if (loadMore) {
isNextPageLoading = true;
pageNo += 1;
} else {
isLoading = true;
pageNo = 1;
}
notifyListeners();
log('Fetching inventory page: $pageNo');
try {
final paginatedPayload = {
...payload,
"pageSize": pageItemNumber,
"pageNumber": pageNo,
};
final response = await ApiManager.instance.post(URLs.getInventoryDetailsByFilter, body: paginatedPayload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body);
final newResponse = AssetInventoryResponse.fromJson(jsonData);
if (loadMore) {
siteFilterAssetList.addAll(newResponse.assetList ?? []);
siteFilterAssetResponse?.totalRows = newResponse.totalRows;
} else {
siteFilterAssetResponse = newResponse;
siteFilterAssetList = newResponse.assetList ?? [];
}
nextPage = (siteFilterAssetList.length) < (siteFilterAssetResponse?.totalRows ?? 0);
} else {
siteFilterAssetList = [];
nextPage = false;
}
isLoading = false;
isNextPageLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
isNextPageLoading = false;
nextPage = false;
stateCode = -1;
notifyListeners();
return -1;
}
}
Future<AssetInventoryModel?> searchAsset({
required Map<String, dynamic> payload,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.searchAsset, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final Map<String, dynamic> jsonData = json.decode(response.body)["data"];
AssetInventoryModel model = AssetInventoryModel.fromJson(jsonData);
log('model json ${model.toJson()}');
isLoading = false;
notifyListeners();
return model;
} else {
isLoading = false;
notifyListeners();
return null;
}
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return null;
}
}
Future<bool> saveAssetInSession({
AssetInventoryModel? model,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.saveAssetInSession, 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<String?> getClassification({
required Map<String, dynamic> payload,
}) async {
isLoading = true;
String? classification;
try {
final response = await ApiManager.instance.post(URLs.getClassification, body: payload);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
log('classifcation on response ${json.decode(response.body)["data"]['classification']}');
classification = json.decode(response.body)["data"]['classification'];
isLoading = false;
notifyListeners();
return classification;
} else {
isLoading = false;
notifyListeners();
return classification;
}
} catch (error) {
isLoading = false;
notifyListeners();
return classification;
}
}
Future<bool> deleteAssetISession({required num id}) async {
try {
isLoading = true;
notifyListeners();
final response = await ApiManager.instance.get(URLs.deleteAssetInSession + "?id=$id");
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false;
notifyListeners();
return true;
}
isLoading = false;
notifyListeners();
return false;
} catch (e) {
log("Delete Asset [error] : $e");
isLoading = false;
notifyListeners();
return false;
}
}
Future<List<Lookup>> getAutoCompleteDetails({
bool? isManufacturer,
String? query,
int type = 0,
}) async {
try {
String url = '';
switch (type) {
//for model and manufacturer..
case 0:
url = URLs.getManufacturerOrModelAutoComplete;
break;
//for asset name..
case 1:
url = URLs.searchAssetName;
break;
//for supplier...
case 2:
url = URLs.getSuppliersAutoCompleteInventory;
break;
default:
url = URLs.getManufacturerOrModelAutoComplete;
}
final queryParams = <String, String>{};
if (isManufacturer != null && type == 0) {
queryParams['isManufacturer'] = isManufacturer.toString();
}
if (query != null && query.isNotEmpty) {
queryParams['searchText'] = query;
}
if (queryParams.isNotEmpty) {
url += '?${Uri(queryParameters: queryParams).query}';
}
final response = await ApiManager.instance.get(url);
List<Lookup> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) {
final data = json.decode(response.body)["data"];
list = (data as List).map((e) => Lookup.fromJson(e)).toList();
}
return list;
} catch (error) {
log('error $error');
return [];
}
}
Future<int> getAssets({DeviceSearch? search, bool isQr = false, bool isSearchBy = false, num? sessionId}) async {
if (isLoading == true) return -2;
isLoading = true;
notifyListeners();
late Response response;
try {
final Map<String, dynamic> body = {
"pageSize": isSearchBy ? searchPageItemNumber : pageItemNumber,
"pageNumber": isSearchBy ? (searchDevices.length / searchPageItemNumber).ceil() + 1 : devices.length ~/ pageItemNumber + 1,
"sessionId": sessionId ?? 0,
"assetSerialNo": search?.assetSerialNumber ?? '',
"assetName": search?.assetName ?? '',
"model": search?.model ?? '',
"manufacturer": search?.manufacturer ?? '',
"supplier": search?.supplier ?? '',
"siteName": search?.site ?? '',
// "buildingName":search?.??'',
// "floorName": search?.f??'',
"departmentName": search?.department ?? '',
// "roomName": search?.room
};
// if (search != null) body.addAll(search.toJson());
response = await ApiManager.instance.post(URLs.getAssetsTemp, body: body);
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
List equipmentListJson = json.decode(response.body)["data"];
var dList = equipmentListJson.map<AssetInventoryModel>((asset) => AssetInventoryModel.fromJson(asset)).toList() ?? [];
isSearchBy ? _searchDevices.addAll(dList) : _devices.addAll(dList);
nextPage = true;
} else {
nextPage = false;
}
isLoading = false;
notifyListeners();
return response.statusCode;
}
Future<bool> markAsComplete({
required Map<String, dynamic> payload,
}) async {
isLoading = true;
try {
final response = await ApiManager.instance.post(URLs.convertDetailToComplete, 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;
}
}
}

@ -27,6 +27,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
final bool showShadow;
final bool showCancel;
final Color? backgroundColor; // Now nullable
final Color? titleTextColor; // Now nullable
final bool? loading; // Now nullable
final int? requestById;
final String? Function(T?)? validator;
@ -49,6 +50,7 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
this.showShadow = true,
this.showCancel = false,
this.backgroundColor,
this.titleTextColor,
this.loading,
this.requestById,
this.validator,
@ -146,7 +148,11 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
children: [
Text(
widget.title,
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: context.isDark
? null
: widget.titleTextColor ?? AppColor.neutral20,
fontWeight: FontWeight.w500),
),
DropdownButton<T>(
value: _selectedItem,

@ -37,6 +37,7 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
@override
Widget build(BuildContext context) {
//TODO need to refactor this and move out of build...
if (_provider == null) {
requestsList = [
Request(null, context.translation.allWorkOrder),
@ -67,6 +68,7 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
if (context.userProvider.isEngineer) {
requestsList.add(Request(10, 'Equipment Internal Audit'));
requestsList.add(Request(11, 'System Internal Audit'));
requestsList.add(Request(12, "Asset Delivery"));
}
requestsList.add(Request(12, "Loan Equipment"));
@ -91,7 +93,6 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
_provider!.getAllRequests(context);
});
}
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/models/new_models/dashboard_detail.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_item_view.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_item_view.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_item_view.dart';
@ -75,6 +76,8 @@ class RequestPaginatedListview extends StatelessWidget {
return SystemInternalAuditItemView(requestData: request);
case 12:
return LoanEquipmentItemView(requestData: request);
case 13:
return AssetDeliveryItemView(requestData: request);
default:
return Container(
height: 100,

@ -6,6 +6,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_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/modules/asset_delivery_module/pages/asset_delivery_item_view.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_item_view.dart';
import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_item_view.dart';
@ -69,8 +70,12 @@ class RequestItemViewList extends StatelessWidget {
return EquipmentInternalAuditItemView(requestDetails: list[index]);
case 11:
return SystemInternalAuditItemView(requestDetails: list[index]);
//Need to use correct value ....
case 12:
return AssetDeliveryItemView(requestDetails: list[index]);
case 12:
return LoanEquipmentItemView(requestDetails: list[index]);
default:
Container(
height: 100,

Loading…
Cancel
Save