Compare commits

...

4 Commits

@ -4,14 +4,14 @@ class URLs {
static const String appReleaseBuildNumber = "31"; static const String appReleaseBuildNumber = "31";
// static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsm.hmg.com"; // production url
static const host1 = "https://atomsmdev.hmg.com"; // local DEV url // static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT url static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static const host1 = "http://10.201.111.125:9495"; // temporary Server UAT url // static const host1 = "http://10.201.111.125:9495"; // temporary Server UAT url
// static String _baseUrl = "$_host/mobile"; // static String _baseUrl = "$_host/mobile";
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
static final String _baseUrl = "$_host/v6/mobile"; // for asset delivery module // static final String _baseUrl = "$_host/v6/mobile"; // for asset delivery module
// static final String _baseUrl = "$_host/mobile"; // host local UAT and for internal audit dev // static final String _baseUrl = "$_host/mobile"; // host local UAT and for internal audit dev
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM // static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation // static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation
@ -68,9 +68,11 @@ class URLs {
//service request new flow urls. //service request new flow urls.
static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount';
static get qaAuditorCount => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorCount'; static get qaAuditorCount => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorCount';
static get commissioningEngineerCount => '$_baseUrl/ServiceRequest/GetDashboardCommissioningEngineerCount';
static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails'; static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails';
static get qaAuditorDetails => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorDetails'; static get qaAuditorDetails => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorDetails';
static get commissioningEngineerDetails => '$_baseUrl/ServiceRequest/GetDashboardCommissioningEngineerDetails';
static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject'; static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject';
@ -413,8 +415,10 @@ class URLs {
static get getLineFromExternalPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetLineFromExternalPo'; static get getLineFromExternalPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetLineFromExternalPo';
static get getCostCenterListToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToLineDeliveryInspection'; static get getCostCenterListToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToLineDeliveryInspection';
static get getCostCenterAndSerialNoToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterAndSerialNoToLineDeliveryInspection';
static get getCostCenterToPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToPo'; static get getCostCenterToPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToPo';
static get saveCostCenterToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterToLineDeliveryInspection'; static get saveCostCenterToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterToLineDeliveryInspection';
static get saveCostCenterAndSerialNoToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterAndSerialNoToLineDeliveryInspection';
static get getDeliveryHistories => '$_baseUrl/AssetDeliveryExternalDelivery/GetDeliveryHistories'; static get getDeliveryHistories => '$_baseUrl/AssetDeliveryExternalDelivery/GetDeliveryHistories';
//Technical Inscption... //Technical Inscption...
static get getLineFromTechnicalInspection => '$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetLineFromDeliveryInspection'; static get getLineFromTechnicalInspection => '$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetLineFromDeliveryInspection';
@ -425,7 +429,7 @@ class URLs {
static get getAssetFromInternalTechnicalInspection => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetFromInternal"; static get getAssetFromInternalTechnicalInspection => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetFromInternal";
static get getAssetDetailsByAssetId => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetByIdFromInternal"; static get getAssetDetailsByAssetId => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetByIdFromInternal";
static get saveTechnicalInspectionAsset => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/SaveTechnicalInspectionItem"; static get saveTechnicalInspectionAsset => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/SaveTechnicalInspectionItem";
static get getAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/GetAttachments"; static get getAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/GetAttachmentsBasedOnType";
static get saveAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/Save"; static get saveAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/Save";
//End user Acceptance... //End user Acceptance...
static get getEndUserAcceptanceCostCenter => "$_baseUrl/AssetDeliveryEndUserAcceptance/GetEndUserAcceptanceCostCenter"; static get getEndUserAcceptanceCostCenter => "$_baseUrl/AssetDeliveryEndUserAcceptance/GetEndUserAcceptanceCostCenter";
@ -433,5 +437,6 @@ class URLs {
static get saveEndUserFormData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveMaster"; static get saveEndUserFormData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveMaster";
static get saveEndUserAssetData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveDetail"; static get saveEndUserAssetData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveDetail";
static get endUserStatusLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=534"; static get endUserStatusLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=534";
static get endUserRejectionReasonLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5007"; static get endUserRejectionReasonLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=415";
static get attachmentTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5009";
} }

@ -166,7 +166,11 @@ class AllRequestsProvider extends ChangeNotifier {
if (context.userProvider.isNurse) { if (context.userProvider.isNurse) {
list.add(9); // list.add(9); //
} }
list.add(12); // loan module list.add(12);
if (context.userProvider.isCommissioningEngineer) {
list = [13];
}
// loan module
return list; return list;
} }

@ -47,6 +47,7 @@ class UserProvider extends ChangeNotifier {
bool get isAssessor => user!.type == UsersTypes.assessor || user!.type == UsersTypes.assessorTl; bool get isAssessor => user!.type == UsersTypes.assessor || user!.type == UsersTypes.assessorTl;
bool get isQualityUser => user!.type == UsersTypes.qualityUser; bool get isQualityUser => user!.type == UsersTypes.qualityUser;
bool get isCommissioningEngineer => user!.type == UsersTypes.commissioningEngineer;
VerifyOtpModel _verifyOtpModel = VerifyOtpModel(); VerifyOtpModel _verifyOtpModel = VerifyOtpModel();
SwipeTransaction _swipeTransactionModel = SwipeTransaction(); SwipeTransaction _swipeTransactionModel = SwipeTransaction();

@ -106,13 +106,22 @@ class DashBoardProvider extends ChangeNotifier {
isAllCountLoading = true; isAllCountLoading = true;
notifyListeners(); notifyListeners();
String url = ''; String url = '';
if (usersType == UsersTypes.qualityUser) {
url = URLs.qaAuditorCount; // if (usersType == UsersTypes.qualityUser) {
} else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) { // url = URLs.qaAuditorCount;
url = URLs.engineerDashboardCountUrl; // } else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) {
} else { // url = URLs.engineerDashboardCountUrl;
url = URLs.nurseDashboardCountUrl; // } else {
} // url = URLs.nurseDashboardCountUrl;
// }
final urlMap = {
UsersTypes.qualityUser: URLs.qaAuditorCount,
UsersTypes.commissioningEngineer: URLs.commissioningEngineerCount,
UsersTypes.engineer: URLs.engineerDashboardCountUrl,
UsersTypes.assessor: URLs.engineerDashboardCountUrl,
UsersTypes.assessorTl: URLs.engineerDashboardCountUrl,
};
url = urlMap[usersType] ?? URLs.nurseDashboardCountUrl;
Response response; Response response;
try { try {
response = await ApiManager.instance.post(url, body: {}); response = await ApiManager.instance.post(url, body: {});
@ -235,6 +244,32 @@ class DashBoardProvider extends ChangeNotifier {
} }
} }
String getDashboardUrl({
required UsersTypes usersType,
int? status,
int? tabId,
}) {
switch (usersType) {
case UsersTypes.qualityUser:
return URLs.qaAuditorDetails;
case UsersTypes.commissioningEngineer:
return URLs.commissioningEngineerDetails;
case UsersTypes.engineer:
case UsersTypes.assessor:
case UsersTypes.assessorTl:
if (status == 0) {
return URLs.engineerDashboardUpcoming;
} else if (status == 1 && tabId == 1) {
return URLs.engineerDashboardNotAssignDetails;
} else {
// status == 1 && tabId == 2 OR any other case
return URLs.engineerDashboardDetailsUrl;
}
default:
return URLs.nurseDashboardDetailsUrl;
}
}
Future<int> getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date, int? tabId}) async { Future<int> getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date, int? tabId}) async {
if (showLoader) { if (showLoader) {
isDetailLoading = showLoader; isDetailLoading = showLoader;
@ -243,25 +278,26 @@ class DashBoardProvider extends ChangeNotifier {
Response response; Response response;
String url = ''; String url = '';
// if (usersType == UsersTypes.qualityUser) {
// url = URLs.qaAuditorDetails;
// } else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) {
// //need to check pagination for not assigned task @waseem.
//
// //these checks are to call different apis for dashboard for engineer...
// if (status == 0) {
// url = URLs.engineerDashboardUpcoming;
// } else if (status == 1 && tabId == 1) {
// url = URLs.engineerDashboardNotAssignDetails;
// } else if (status == 1 && tabId == 2) {
// url = URLs.engineerDashboardDetailsUrl;
// } else {
// url = URLs.engineerDashboardDetailsUrl;
// }
// } else {
// url = URLs.nurseDashboardDetailsUrl;
// }
url = getDashboardUrl(usersType: usersType, status: status, tabId: tabId);
if (usersType == UsersTypes.qualityUser) {
url = URLs.qaAuditorDetails;
} else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) {
//need to check pagination for not assigned task @waseem.
//these checks are to call different apis for dashboard for engineer...
if (status == 0) {
url = URLs.engineerDashboardUpcoming;
} else if (status == 1 && tabId == 1) {
url = URLs.engineerDashboardNotAssignDetails;
} else if (status == 1 && tabId == 2) {
url = URLs.engineerDashboardDetailsUrl;
} else {
url = URLs.engineerDashboardDetailsUrl;
}
} else {
url = URLs.nurseDashboardDetailsUrl;
}
try { try {
Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber}; Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber};
@ -383,6 +419,12 @@ class CategoryTabs {
tabs.add(CategoryTabs(label: 'Closed', tag: 3, id: 4)); tabs.add(CategoryTabs(label: 'Closed', tag: 3, id: 4));
return tabs; return tabs;
} }
if (userType == UsersTypes.commissioningEngineer) {
tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2));
tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3));
tabs.add(CategoryTabs(label: 'Closed', tag: 3, id: 4));
return tabs;
}
tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2)); tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2));
tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3)); tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3));

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/new_models/dashboard_detail.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/asset_inventory_module/pages/inventory_session_item_view.dart'; import 'package:test_sa/modules/asset_inventory_module/pages/inventory_session_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/equipment_internal_audit/equipment_internal_audit_item_view.dart';
import 'package:test_sa/modules/tm_module/tasks/task_request_item_view.dart'; import 'package:test_sa/modules/tm_module/tasks/task_request_item_view.dart';
@ -62,6 +63,8 @@ class RequestCategoryList extends StatelessWidget {
return EquipmentInternalAuditItemView(requestData: request); return EquipmentInternalAuditItemView(requestData: request);
case 11: case 11:
return EquipmentInternalAuditItemView(requestData: request); return EquipmentInternalAuditItemView(requestData: request);
case 13:
return AssetDeliveryItemView(requestData: request);
default: default:
return Container( return Container(
height: 100, height: 100,

@ -125,3 +125,9 @@ enum DropDownMatchType {
identifier, identifier,
name, name,
} }
enum CostCenterType {
costCenter,
serialNumber,
}

@ -28,6 +28,7 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/report/servic
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_type_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_rejection_reason_lookup_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/end_user_rejection_reason_lookup_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/end_user_status_lookup_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/end_user_status_lookup_provider.dart';
@ -326,6 +327,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => PowerSupplyTypeProvider()), ChangeNotifierProvider(create: (_) => PowerSupplyTypeProvider()),
ChangeNotifierProvider(create: (_) => EndUserStatusLookupProvider()), ChangeNotifierProvider(create: (_) => EndUserStatusLookupProvider()),
ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider()), ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider()),
ChangeNotifierProvider(create: (_) => AttachmentTypeLookupProvider()),
], ],
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {

@ -4,5 +4,6 @@ enum UsersTypes {
nurse, // 1 nurse, // 1
assessor, assessor,
assessorTl, assessorTl,
qualityUser qualityUser,
commissioningEngineer
} }

@ -108,10 +108,13 @@ class User {
return UsersTypes.assessor; return UsersTypes.assessor;
case "R-19": // Head Nurse Role case "R-19": // Head Nurse Role
return UsersTypes.assessorTl; return UsersTypes.assessorTl;
//TODO need to confirm why repeat.
case "R-3": // Quality User case "R-3": // Quality User
return UsersTypes.qualityUser; return UsersTypes.qualityUser;
case "R-58": // Quality User case "R-58": // Quality User
return UsersTypes.qualityUser; return UsersTypes.qualityUser;
case "R-201": // Quality User
return UsersTypes.commissioningEngineer;
default: default:
return null; return null;
} }

@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_type_provider.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class HelperFunction {
static void attachmentTap({required BuildContext context, required AssetDeliveryProvider assetDeliveryProvider, required dynamic deliveryTableItemId}) async {
Lookup? result;
result = await showAttachmentTypeBottomSheet(context);
List<GenericAttachmentModel> list = [];
if (result != null) {
showDialog(
context: context,
barrierDismissible: false,
builder: (_) => const AppLazyLoading(),
);
list = await assetDeliveryProvider.getAttachments(tableItemId: deliveryTableItemId, attachmentType: result.value);
Navigator.pop(context);
// if (list.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: deliveryTableItemId,
attachmentType: result!.value,
attachmentList: list,
)));
// }
}
}
static Future<Lookup?> showAttachmentTypeBottomSheet(BuildContext context) {
return showModalBottomSheet<Lookup?>(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (_) {
return SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.only(
top: 16,
left: 16,
right: 16,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProvider>(
context: context,
title: context.translation.reason,
onSelect: (value) {
Navigator.pop(context, value);
},
),
],
),
),
);
},
);
}
}

@ -241,7 +241,7 @@ class AssetDeliveryInternalDetail {
num? qtyCancelled; num? qtyCancelled;
num? unitPrice; num? unitPrice;
num? unitPriceWithTax; num? unitPriceWithTax;
String? itemCategory; Lookup? itemCategory;
num? totalAssets; num? totalAssets;
num? childPerAsset; num? childPerAsset;
@ -259,7 +259,9 @@ class AssetDeliveryInternalDetail {
qtyCancelled = json['qtyCancelled']; qtyCancelled = json['qtyCancelled'];
unitPrice = json['unitPrice']; unitPrice = json['unitPrice'];
unitPriceWithTax = json['unitPriceWithTax']; unitPriceWithTax = json['unitPriceWithTax'];
itemCategory = json['itemCategory']; itemCategory = json['itemCategory'] != null
? Lookup.fromJson(json['itemCategory'])
: null;
totalAssets = json['totalAssets']; totalAssets = json['totalAssets'];
childPerAsset = json['childPerAsset']; childPerAsset = json['childPerAsset'];
} }

@ -40,11 +40,6 @@ class CostCenterModel {
data['id'] = id ?? 0; data['id'] = id ?? 0;
data['qty'] = quantity; data['qty'] = quantity;
// data['costCenter'] = costCenter;
// data['acceptedBy'] = acceptedBy;
// data['acceptanceDate'] = acceptanceDate;
// data['acceptedByEmail'] = acceptedByEmail;
// data['acceptedBySignature'] = acceptedBySignature;
data['costCenter'] = costCenterName; data['costCenter'] = costCenterName;
return data; return data;
} }

@ -0,0 +1,53 @@
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
class CostCenterSerialNoFormModel {
List<CostCenterModel>? costCenters;
List<SerialNoModel>? serialNos;
CostCenterSerialNoFormModel({
this.costCenters,
this.serialNos,
});
// From JSON
CostCenterSerialNoFormModel.fromJson(Map<String, dynamic> json) {
if (json['costCenters'] != null) {
costCenters = List<CostCenterModel>.from((json['costCenters'] as List).map((e) => CostCenterModel.fromJson(e)));
}
if (json['serialNos'] != null) {
serialNos = List<SerialNoModel>.from((json['serialNos'] as List).map((e) => SerialNoModel.fromJson(e)));
}
}
// To JSON
Map<String, dynamic> toJson() {
return {
'costCenters': costCenters?.map((e) => e.toJson()).toList() ?? [],
'serialNos': serialNos?.map((e) => e.toJson()).toList() ?? [],
};
}
}
class SerialNoModel {
int? id;
String? serialNo;
SerialNoModel({
this.id,
this.serialNo,
});
SerialNoModel.fromJson(Map<String, dynamic> json) {
id = json['id'] ?? json['costCenterId'];
serialNo = json['serialNo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = {};
data['id'] = id ?? 0;
data['serialNo'] = serialNo;
return data;
}
}

@ -1,6 +1,11 @@
import 'package:test_sa/modules/asset_delivery_module/models/inspection_person_model.dart';
class DeliveryInspectionFormModel { class DeliveryInspectionFormModel {
int? assetDeliveryExternalDeliveryId; int? assetDeliveryExternalDeliveryId;
String? deliveryInspectionInspectedBy; String? deliveryInspectionInspectedBy;
InspectionPersonModel? inspectedByModel;
InspectionPersonModel? approvedByModel;
InspectionPersonModel? thirdApprovalModel;
DateTime? deliveryInspectionInspectedDateFrom; DateTime? deliveryInspectionInspectedDateFrom;
DateTime? deliveryInspectionInspectedDateTo; DateTime? deliveryInspectionInspectedDateTo;
num? totalTime; num? totalTime;
@ -9,6 +14,9 @@ class DeliveryInspectionFormModel {
DeliveryInspectionFormModel({ DeliveryInspectionFormModel({
this.assetDeliveryExternalDeliveryId, this.assetDeliveryExternalDeliveryId,
this.deliveryInspectionInspectedBy, this.deliveryInspectionInspectedBy,
this.inspectedByModel,
this.approvedByModel,
this.thirdApprovalModel,
this.deliveryInspectionInspectedDateFrom, this.deliveryInspectionInspectedDateFrom,
this.deliveryInspectionInspectedDateTo, this.deliveryInspectionInspectedDateTo,
this.totalTime, this.totalTime,
@ -18,20 +26,32 @@ class DeliveryInspectionFormModel {
DeliveryInspectionFormModel.fromJson(Map<String, dynamic> json) { DeliveryInspectionFormModel.fromJson(Map<String, dynamic> json) {
assetDeliveryExternalDeliveryId = json['assetDeliveryExternalDeliveryId']; assetDeliveryExternalDeliveryId = json['assetDeliveryExternalDeliveryId'];
deliveryInspectionInspectedBy = json['deliveryInspectionInspectedBy']; deliveryInspectionInspectedBy = json['deliveryInspectionInspectedBy'];
deliveryInspectionInspectedDateFrom = json['deliveryInspectionInspectedDateFrom']!=null?DateTime.tryParse(json['deliveryInspectionInspectedDateFrom']):null; inspectedByModel = InspectionPersonModel(name: json['deliveryInspectionInspectedBy'], email: json['deliveryInspectionInspectedByEmail'], signature: json['deliveryInspectionInspectedBySignature']);
deliveryInspectionInspectedDateTo = json['deliveryInspectionInspectedDateTo']!=null?DateTime.tryParse(json['deliveryInspectionInspectedDateTo']):null; approvedByModel = InspectionPersonModel(name: json['deliveryInspectionApprovedBy'], email: json['deliveryInspectionApprovedByEmail'], signature: json['deliveryInspectionApprovedBySignature']);
thirdApprovalModel =
InspectionPersonModel(name: json['deliveryInspectionThirdApproverBy'], email: json['deliveryInspectionThirdApproverByEmail'], signature: json['deliveryInspectionThirdApproverBySignature']);
deliveryInspectionInspectedDateFrom = json['deliveryInspectionInspectedDateFrom'] != null ? DateTime.tryParse(json['deliveryInspectionInspectedDateFrom']) : null;
deliveryInspectionInspectedDateTo = json['deliveryInspectionInspectedDateTo'] != null ? DateTime.tryParse(json['deliveryInspectionInspectedDateTo']) : null;
totalTime = json['totalTime']; totalTime = json['totalTime'];
deliveryInspectionApprovedBy = json['deliveryInspectionApprovedBy']; deliveryInspectionApprovedBy = json['deliveryInspectionApprovedBy'];
} }
//TODO need to set payload..
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'assetDeliveryExternalDeliveryId': assetDeliveryExternalDeliveryId, 'assetDeliveryExternalDeliveryId': assetDeliveryExternalDeliveryId,
'deliveryInspectionInspectedBy': deliveryInspectionInspectedBy, 'deliveryInspectionInspectedDateFrom': deliveryInspectionInspectedDateFrom?.toIso8601String(),
'deliveryInspectionInspectedDateFrom': deliveryInspectionInspectedDateFrom?.toIso8601String(),
'deliveryInspectionInspectedDateTo': deliveryInspectionInspectedDateTo?.toIso8601String(), 'deliveryInspectionInspectedDateTo': deliveryInspectionInspectedDateTo?.toIso8601String(),
'totalTime': totalTime, 'totalTime': totalTime,
'deliveryInspectionApprovedBy': deliveryInspectionApprovedBy, 'deliveryInspectionInspectedBy': inspectedByModel?.name,
"deliveryInspectionInspectedBySignature": inspectedByModel?.signature,
"deliveryInspectionInspectedByEmail": inspectedByModel?.email,
'deliveryInspectionApprovedBy': approvedByModel?.name,
"deliveryInspectionApprovedBySignature": approvedByModel?.signature,
"deliveryInspectionApprovedByEmail": approvedByModel?.email,
"deliveryInspectionThirdApproverBy": thirdApprovalModel?.name,
"deliveryInspectionThirdApproverBySignature": thirdApprovalModel?.signature,
"deliveryInspectionThirdApproverByEmail": thirdApprovalModel?.email,
}; };
} }
} }

@ -0,0 +1,15 @@
import 'package:flutter/services.dart';
class InspectionPersonModel {
String? name;
String? email;
String? signature;
Uint8List? localSignature;
InspectionPersonModel({
this.name,
this.email,
this.signature,
this.localSignature,
});
}

@ -136,7 +136,7 @@ class TechnicalInspectionAssetModel {
Map<String, dynamic> toChildJson() { Map<String, dynamic> toChildJson() {
final Map<String, dynamic> data = {}; final Map<String, dynamic> data = {};
data['id'] = id; data['id'] = id ?? 0;
data['assetDeliveryInternalDetailAssetChildId'] = assetDeliveryInternalDetailAssetChildId; data['assetDeliveryInternalDetailAssetChildId'] = assetDeliveryInternalDetailAssetChildId;
data['assetNumber'] = assetNumber; data['assetNumber'] = assetNumber;
data['assetOriginId'] = assetOrigin?.id; data['assetOriginId'] = assetOrigin?.id;

@ -1,8 +1,10 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
@ -15,21 +17,20 @@ 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_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class AssetDeliveryAttachmentView extends StatefulWidget { class AssetDeliveryAttachmentView extends StatefulWidget {
///Need to check which parm need here.
final int? lineId;
final int? tableItemId; final int? tableItemId;
final int? requestId; final int? attachmentType;
final bool? isHmg; final List<GenericAttachmentModel> attachmentList;
const AssetDeliveryAttachmentView({ const AssetDeliveryAttachmentView({
super.key, super.key,
this.lineId, required this.attachmentList,
this.requestId, this.attachmentType,
this.tableItemId, this.tableItemId,
this.isHmg,
}); });
@override @override
@ -52,15 +53,17 @@ class _AssetDeliveryAttachmentViewState extends State<AssetDeliveryAttachmentVie
void getInitialData() async { void getInitialData() async {
///get previoues Attachment from Apis. ///get previoues Attachment from Apis.
isLoading = true; // isLoading = true;
setState(() {}); setState(() {});
_attachments = await assetDeliveryProvider.getAttachments(tableItemId: widget.tableItemId); _attachments = widget.attachmentList;
isLoading = false; // await assetDeliveryProvider.getAttachments(tableItemId: widget.tableItemId, attachmentType: widget.attachmentType);
// isLoading = false;
setState(() {}); setState(() {});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
log('value ${widget.attachmentType}');
return Scaffold( return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar( appBar: DefaultAppBar(
@ -69,59 +72,79 @@ class _AssetDeliveryAttachmentViewState extends State<AssetDeliveryAttachmentVie
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
body: isLoading body: widget.attachmentList.isEmpty
? const CircularProgressIndicator(color: AppColor.primary10).center ? const NoDataFound().center
: Column( : Column(
children: [ children: [
AttachmentPicker( Flexible(
label: context.translation.attachments, fit: FlexFit.loose, // expands only as much as needed
attachment: _attachments, child: Column(
buttonColor: AppColor.primary10, children: [
onlyImages: false, widget.attachmentType == 5
showAsListView: true, ? AttachmentPicker(
// showAsGrid: true, label: context.translation.attachments,
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), attachment: _attachments,
onChange: (attachment) {}, buttonColor: AppColor.primary10,
) onlyImages: false,
.toShadowContainer( showAsListView: true,
context, buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
borderRadius: 20, onChange: (attachment) {},
padding: 12, ).toShadowContainer(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), context,
) borderRadius: 20,
.expanded, padding: 12,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
)
: FilesList(images: _attachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []).toShadowContainer(
context,
borderRadius: 20,
padding: 12,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
],
),
),
FooterActionButton.footerContainer( FooterActionButton.footerContainer(
context: context, context: context,
child: AppFilledButton( child: AppFilledButton(
buttonColor: AppColor.primary10, buttonColor: AppColor.primary10,
label: 'Save'.addTranslation, label: 'Save'.addTranslation,
maxWidth: true, maxWidth: true,
onPressed: () async { onPressed: _onSavePressed,
List<GenericAttachmentModel> attachement = []; ),
for (var item in _attachments) {
String fileName =
CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
attachement.add(GenericAttachmentModel(id: item.id ?? 0, name: fileName));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
Map<String, dynamic> payLoad = {
'assetDeliveryExternalDeliveryId': widget.tableItemId,
'attachments': attachement,
};
await assetDeliveryProvider.saveAttachment(payload: payLoad).then((status) async {
Navigator.pop(context);
if (status) {
///Need to verify need to stay on this page and refresh or go back..
Navigator.pop(context);
// assetDeliveryProvider.getDeliveryLinesListById(
// itemId: widget.tableItemId,
// );
}
});
}),
), ),
], ],
), ),
); );
} }
Future<void> _onSavePressed() async {
final List<GenericAttachmentModel> attachmentPayload = _attachments.map((item) {
final String name = CMRequestUtils.isLocalUrl(item.name ?? '') ? '${item.name?.split("/").last}|${base64Encode(File(item.name!).readAsBytesSync())}' : item.name ?? '';
return GenericAttachmentModel(
id: item.id ?? 0,
name: name,
);
}).toList();
showDialog(
context: context,
barrierDismissible: false,
builder: (_) => const AppLazyLoading(),
);
final payload = {
'assetDeliveryExternalDeliveryId': widget.tableItemId,
'attachments': attachmentPayload,
};
final status = await assetDeliveryProvider.saveAttachment(payload: payload);
Navigator.pop(context);
if (status) {
Navigator.pop(context);
}
}
} }

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
@ -10,6 +8,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_serial_no_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
@ -47,8 +46,9 @@ class CostCenterFormView extends StatefulWidget {
} }
class _CostCenterFormViewState extends State<CostCenterFormView> { class _CostCenterFormViewState extends State<CostCenterFormView> {
List<CostCenterModel> _list = []; CostCenterSerialNoFormModel formModel = CostCenterSerialNoFormModel(costCenters: [], serialNos: []);
late AssetDeliveryProvider assetDeliveryProvider; late AssetDeliveryProvider assetDeliveryProvider;
CostCenterType _selectedType = CostCenterType.costCenter;
@override @override
void initState() { void initState() {
@ -60,15 +60,20 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
} }
void getInitialData() async { void getInitialData() async {
_list = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines( formModel = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines(
lineId: widget.lineId, lineId: widget.lineId,
tableItemId: widget.tableItemId, tableItemId: widget.tableItemId,
); );
if (_list.isEmpty) { if (formModel.costCenters!.isEmpty) {
_list.add(CostCenterModel( formModel.costCenters!.add(CostCenterModel(
id: 0, id: 0,
)); ));
} }
// if (formModel.serialNos!.isEmpty) {
// formModel.serialNos!.add(SerialNoModel(
// id: 0,
// ));
// }
if (widget.isHmg == true) { if (widget.isHmg == true) {
CostCenterProvider costCenterProvider = Provider.of<CostCenterProvider>(context, listen: false); CostCenterProvider costCenterProvider = Provider.of<CostCenterProvider>(context, listen: false);
if (costCenterProvider.items.isEmpty) { if (costCenterProvider.items.isEmpty) {
@ -78,21 +83,21 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
setState(() {}); setState(() {});
} }
void _addNewEntry() { void addItem<T>(List<T> list, T Function() creator) {
setState(() { setState(() {
_list.add(CostCenterModel(costCenter: Lookup())); list.add(creator());
}); });
} }
void _removeEntry(int index) { void removeItem<T>(List<T> list, int index) {
setState(() { setState(() {
_list.removeAt(index); list.removeAt(index);
}); });
} }
void _updateModel(int index, void Function(CostCenterModel model) updateList) { void updateItem<T>(List<T> list, int index, void Function(T item) updater) {
setState(() { setState(() {
updateList(_list[index]); updater(list[index]);
}); });
} }
@ -111,34 +116,9 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
? const CircularProgressIndicator(color: AppColor.primary10).center ? const CircularProgressIndicator(color: AppColor.primary10).center
: Column( : Column(
children: [ children: [
itemDetails(context: context, itemNo: widget.itemNo, itemDescription: widget.itemDescription), itemDetails(),
ListView.builder( selectionButton(),
itemCount: _list.length + 1, _selectedType == CostCenterType.costCenter ? _buildCostCenterList() : _buildSerialNumberList(),
shrinkWrap: true,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
itemBuilder: (context, index) {
if (index == _list.length) {
return AppFilledButton(
label: "Add Cost Center".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: _addNewEntry,
);
}
return CostCenterItemCard(
model: _list[index],
index: index,
isReadOnly: false,
isHmg: widget.isHmg,
requestId: widget.requestId,
onUpdate: (updateList) => _updateModel(index, updateList),
onRemove: () => _removeEntry(index),
);
},
).expanded,
FooterActionButton.footerContainer( FooterActionButton.footerContainer(
context: context, context: context,
child: AppFilledButton( child: AppFilledButton(
@ -147,7 +127,9 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
maxWidth: true, maxWidth: true,
onPressed: () async { onPressed: () async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.saveCostCenterToLineDeliveryInspection(tableItemId: widget.tableItemId, lineId: widget.lineId, list: _list).then((status) async { await assetDeliveryProvider
.saveCostCenterToLineDeliveryInspection(tableItemId: widget.tableItemId, lineId: widget.lineId, list: formModel.costCenters, serialNoList: formModel.serialNos)
.then((status) async {
Navigator.pop(context); Navigator.pop(context);
if (status) { if (status) {
Navigator.pop(context); Navigator.pop(context);
@ -163,40 +145,169 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
}), }),
); );
} }
}
Widget itemDetails({required BuildContext context, String? itemNo, String? itemDescription}) { Widget _buildCostCenterList() {
return Column( return ListView.builder(
crossAxisAlignment: CrossAxisAlignment.start, itemCount: formModel.costCenters!.length + 1,
mainAxisSize: MainAxisSize.min, shrinkWrap: true,
children: [ padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
Text( itemBuilder: (context, index) {
'Item No'.addTranslation, if (index == formModel.costCenters!.length) {
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10), return AppFilledButton(
), label: "Add Cost Center".addTranslation,
8.height, maxWidth: true,
Text( textColor: AppColor.textColor(context),
itemNo ?? '-', buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
), showIcon: true,
8.height, onPressed: () {
Text( addItem(formModel.costCenters!, () => CostCenterModel(costCenter: Lookup()));
'Item Description'.addTranslation, },
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10), );
}
return CostCenterItemCard(
model: formModel.costCenters![index],
index: index,
isReadOnly: false,
isHmg: widget.isHmg,
requestId: widget.requestId,
onUpdate: (update) {
updateItem<CostCenterModel>(formModel.costCenters!, index, update);
},
onRemove: () {
removeItem<CostCenterModel>(formModel.costCenters!, index);
},
);
},
).expanded;
}
Widget _buildSerialNumberList() {
return ListView.builder(
itemCount: formModel.serialNos!.length + 1,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
itemBuilder: (context, index) {
if (index == formModel.serialNos!.length) {
return AppFilledButton(
label: "Add Serial Number".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: () {
addItem(formModel.serialNos!, () => SerialNoModel());
},
);
}
return SerialNumberItemCard(
model: formModel.serialNos![index],
onUpdate: (update) {
updateItem<SerialNoModel>(formModel.serialNos!, index, update);
},
onRemove: () {
removeItem<SerialNoModel>(formModel.serialNos!, index);
},
);
},
).expanded;
}
Widget selectionButton() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
Expanded(
child: _radioItem(
value: CostCenterType.costCenter,
groupValue: _selectedType,
title: 'Cost Center',
onTap: () {
setState(() {
_selectedType = CostCenterType.costCenter;
});
},
),
),
Expanded(
child: _radioItem(
value: CostCenterType.serialNumber,
groupValue: _selectedType,
title: 'Serial Number',
onTap: () {
setState(() {
_selectedType = CostCenterType.serialNumber;
});
},
),
),
],
), ),
8.height, );
Text( }
itemDescription ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), Widget _radioItem({
required CostCenterType value,
required CostCenterType groupValue,
required String title,
required VoidCallback onTap,
}) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: Row(
children: [
Radio<CostCenterType>(
value: value,
groupValue: groupValue,
onChanged: (_) => onTap(),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: VisualDensity.compact,
),
4.width,
title.addTranslation.bodyText(context),
],
), ),
], );
).toShadowContainer( }
context,
borderRadius: 20, Widget itemDetails() {
padding: 12, return Column(
showShadow: false, crossAxisAlignment: CrossAxisAlignment.start,
margin: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8), mainAxisSize: MainAxisSize.min,
); children: [
Text(
'Item No'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
widget.itemNo ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Item Description'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
widget.itemDescription ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
).toShadowContainer(
context,
borderRadius: 20,
padding: 12,
showShadow: false,
margin: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
);
}
} }
class CostCenterItemCard extends StatelessWidget { class CostCenterItemCard extends StatelessWidget {
@ -294,3 +405,53 @@ class CostCenterItemCard extends StatelessWidget {
).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 12, vertical: 12)).paddingOnly(bottom: 12); ).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 12, vertical: 12)).paddingOnly(bottom: 12);
} }
} }
class SerialNumberItemCard extends StatelessWidget {
final SerialNoModel model;
final VoidCallback onRemove;
final void Function(void Function(SerialNoModel model)) onUpdate;
const SerialNumberItemCard({
super.key,
required this.model,
required this.onRemove,
required this.onUpdate,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
'Serial Number'.addTranslation.bodyText(context),
Container(
height: 28,
width: 28,
padding: const EdgeInsets.all(6),
child: "trash".toSvgAsset(height: 20, width: 20),
).onPress(onRemove),
],
),
8.height,
AppTextFormField(
labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.serialNo ?? '',
textAlign: TextAlign.center,
showShadow: false,
onChange: (value) {
model.serialNo = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
],
)
.toShadowContainer(
context,
paddingObject: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
)
.paddingOnly(bottom: 12);
}
}

@ -1,5 +1,5 @@
import 'dart:developer'; import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
@ -7,21 +7,24 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/helper_function.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/inspection_person_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/cost_center_form_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/cost_center_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/inpection_bottomsheet.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_lines_list_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_lines_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_type_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/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/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_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart'; import '../../../../new_views/common_widgets/app_filled_button.dart';
@ -110,9 +113,16 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
), ),
8.height, 8.height,
Text( Text(
model.totalTime != null ? '${model.totalTime.toString()} hours' : '-', formatInspectionDuration(model.totalTime),
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(
color: context.isDark ? AppColor.neutral30 : AppColor.neutral120,
),
), ),
// Text(
// model.totalTime != null ? '${model.totalTime.toString()} hours' : '-',
// style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
// ),
8.height, 8.height,
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
Text( Text(
@ -129,7 +139,13 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
child: !viewOnly child: !viewOnly
? Column( ? Column(
children: [ children: [
AppFilledButton(buttonColor: AppColor.primary10, label: 'Attachments'.addTranslation, maxWidth: true, onPressed: _attachmentTap), AppFilledButton(
buttonColor: AppColor.primary10,
label: 'Attachments'.addTranslation,
maxWidth: true,
onPressed: () {
HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
}),
16.height, 16.height,
Row( Row(
children: [ children: [
@ -194,69 +210,132 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
} }
void calculateTotalTime() { void calculateTotalTime() {
if (model.deliveryInspectionInspectedDateFrom == null || model.deliveryInspectionInspectedDateTo == null) { final from = model.deliveryInspectionInspectedDateFrom;
final to = model.deliveryInspectionInspectedDateTo;
if (from == null || to == null) {
model.totalTime = null;
return;
}
final diffInSeconds = to.difference(from).inSeconds;
if (diffInSeconds < 0) {
model.totalTime = null; model.totalTime = null;
return; return;
} }
final fromDate = model.deliveryInspectionInspectedDateFrom!;
final toDate = model.deliveryInspectionInspectedDateTo!; final hours = diffInSeconds / 3600;
final hours = toDate.difference(fromDate).inSeconds / 3600.0;
model.totalTime = num.parse(hours.toStringAsFixed(3)); model.totalTime = num.parse(hours.toStringAsFixed(3));
} }
Widget inspectionDetailsForm() { Widget inspectionDetailsForm() {
return Column( return Column(
children: [ children: [
if (widget.requestModel?.isHMG == true) ...[ _inspectionTile(
OracleUserAutoCompleteField( title: 'Inspected by'.addTranslation,
clearAfterPick: false, model: model.inspectedByModel,
initialValue: model.deliveryInspectionInspectedBy ?? '', isHmg: widget.requestModel?.isHMG == true,
label: 'Inspected by'.addTranslation, onTap: () async {
onPick: (value) { final result = await showInspectionBottomSheet(
model.deliveryInspectionInspectedBy = value.fullName; context,
setState(() {}); title: 'Inspected by'.addTranslation,
}, isHmg: widget.requestModel?.isHMG == true,
onChanged: (value) {}, initialModel: model.inspectedByModel ?? InspectionPersonModel(),
), );
8.height, if (result != null) {
OracleUserAutoCompleteField( setState(() => model.inspectedByModel = result);
clearAfterPick: false, }
initialValue: model.deliveryInspectionApprovedBy ?? '', },
label: 'Approved by'.addTranslation, ),
onChanged: (value) {},
onPick: (value) { 8.height,
model.deliveryInspectionApprovedBy = value.fullName; _inspectionTile(
setState(() {}); title: 'Approved by'.addTranslation,
}, model: model.approvedByModel,
), isHmg: widget.requestModel?.isHMG == true,
] //No HMG user free text insted of dropdown ... onTap: () async {
else ...[ final result = await showInspectionBottomSheet(
AppTextFormField( context,
labelText: 'Inspected by'.addTranslation, title: 'Approved by'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context), isHmg: widget.requestModel?.isHMG == true,
initialValue: model.deliveryInspectionInspectedBy ?? '', initialModel: model.approvedByModel ?? InspectionPersonModel(),
textAlign: TextAlign.center, );
labelStyle: AppTextStyles.textFieldLabelStyle, if (result != null) {
showShadow: false, setState(() => model.approvedByModel = result);
onChange: (value) { }
model.deliveryInspectionInspectedBy = value; },
}, ),
style: Theme.of(context).textTheme.titleMedium, if (widget.requestModel?.paymentTerm?.value == 2) ...[
),
8.height, 8.height,
AppTextFormField( _inspectionTile(
labelText: 'Approved by'.addTranslation, title: 'Third Approved by'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context), model: model.thirdApprovalModel,
initialValue: model.deliveryInspectionApprovedBy ?? '', isHmg: widget.requestModel?.isHMG == true,
textAlign: TextAlign.center, onTap: () async {
labelStyle: AppTextStyles.textFieldLabelStyle, final result = await showInspectionBottomSheet(
showShadow: false, context,
onChange: (value) { title: 'Third Approved by'.addTranslation,
model.deliveryInspectionApprovedBy = value; isHmg: widget.requestModel?.isHMG == true,
initialModel: model.thirdApprovalModel ?? InspectionPersonModel(),
);
if (result != null) {
setState(() => model.thirdApprovalModel = result);
}
}, },
style: Theme.of(context).textTheme.titleMedium,
), ),
], ],
// if (widget.requestModel?.isHMG == true) ...[
// OracleUserAutoCompleteField(
// clearAfterPick: false,
// initialValue: model.deliveryInspectionInspectedBy ?? '',
// label: 'Inspected by'.addTranslation,
// onPick: (value) {
// model.deliveryInspectionInspectedBy = value.fullName;
// setState(() {});
// },
// onChanged: (value) {},
// ),
// 8.height,
// OracleUserAutoCompleteField(
// clearAfterPick: false,
// initialValue: model.deliveryInspectionApprovedBy ?? '',
// label: 'Approved by'.addTranslation,
// onChanged: (value) {},
// onPick: (value) {
// model.deliveryInspectionApprovedBy = value.fullName;
// setState(() {});
// },
// ),
// ] //No HMG user free text insted of dropdown ...
// else ...[
// AppTextFormField(
// labelText: 'Inspected by'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
// initialValue: model.deliveryInspectionInspectedBy ?? '',
// textAlign: TextAlign.center,
// labelStyle: AppTextStyles.textFieldLabelStyle,
// showShadow: false,
// onChange: (value) {
// model.deliveryInspectionInspectedBy = value;
// },
// style: Theme.of(context).textTheme.titleMedium,
// ),
// 8.height,
// AppTextFormField(
// labelText: 'Approved by'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
// initialValue: model.deliveryInspectionApprovedBy ?? '',
// textAlign: TextAlign.center,
// labelStyle: AppTextStyles.textFieldLabelStyle,
// showShadow: false,
// onChange: (value) {
// model.deliveryInspectionApprovedBy = value;
// },
// style: Theme.of(context).textTheme.titleMedium,
// ),
// ],
8.height, 8.height,
ADatePicker( ADatePicker(
label: 'Inspected Date/Time From'.addTranslation, label: 'Inspected Date/Time From'.addTranslation,
@ -266,52 +345,31 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
date: model.deliveryInspectionInspectedDateFrom, date: model.deliveryInspectionInspectedDateFrom,
from: DateTime(DateTime.now().year, 1, 1), from: DateTime(DateTime.now().year, 1, 1),
formatDateWithTime: true, formatDateWithTime: true,
onDatePicker: (selectedDate) { onDatePicker: (selectedDate) async {
showTimePicker( final selectedTime = await showTimePicker(
context: context, context: context,
initialTime: TimeOfDay.now(), initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) { builder: _timePickerThemeBuilder,
final ThemeData currentTheme = Theme.of(context); );
return Theme( if (selectedTime == null) return;
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData( final fromDateTime = DateTime(
dialHandColor: AppColor.primary10, selectedDate.year,
dialBackgroundColor: Colors.grey.withOpacity(0.1), selectedDate.month,
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)), selectedDate.day,
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent), selectedTime.hour,
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10), selectedTime.minute,
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)), );
entryModeIconColor: AppColor.primary10,
), if (!_validateInspectionDates(from: fromDateTime, to: model.deliveryInspectionInspectedDateTo)) {
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)), return; // invalid, do not assign
), }
child: child!,
); model.deliveryInspectionInspectedDateFrom = fromDateTime;
}, setState(() {});
).then((selectedTime) {
if (selectedTime != null) {
model.deliveryInspectionInspectedDateFrom = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
// calculateTotalTime();
///need to check if need validation or not.
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
if (model.deliveryInspectionInspectedDateFrom!.isAfter(DateTime.now())) {
"Start time is after than current time".showToast;
model.deliveryInspectionInspectedDateFrom = null;
selectedTime = null;
return;
}
setState(() {});
}
});
}, },
), ),
8.height, 8.height,
ADatePicker( ADatePicker(
label: 'Inspected Date/Time To'.addTranslation, label: 'Inspected Date/Time To'.addTranslation,
@ -321,55 +379,120 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
date: model.deliveryInspectionInspectedDateTo, date: model.deliveryInspectionInspectedDateTo,
from: model.deliveryInspectionInspectedDateFrom, from: model.deliveryInspectionInspectedDateFrom,
formatDateWithTime: true, formatDateWithTime: true,
onDatePicker: (selectedDate) { onDatePicker: (selectedDate) async {
showTimePicker( if (model.deliveryInspectionInspectedDateFrom == null) {
"Please select time to first".showToast;
return;
}
final selectedTime = await showTimePicker(
context: context, context: context,
initialTime: TimeOfDay.now(), initialTime: TimeOfDay.now(),
builder: (BuildContext context, Widget? child) { builder: _timePickerThemeBuilder,
final ThemeData currentTheme = Theme.of(context); );
return Theme( if (selectedTime == null) return;
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData( final toDateTime = DateTime(
dialHandColor: AppColor.primary10, selectedDate.year,
dialBackgroundColor: Colors.grey.withOpacity(0.1), selectedDate.month,
hourMinuteColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1)), selectedDate.day,
dayPeriodColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent), selectedTime.hour,
dayPeriodTextColor: MaterialStateColor.resolveWith((states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10), selectedTime.minute,
dayPeriodBorderSide: BorderSide(color: Colors.grey.withOpacity(0.2)), );
entryModeIconColor: AppColor.primary10,
), if (!_validateInspectionDates(from: model.deliveryInspectionInspectedDateFrom, to: toDateTime)) {
textButtonTheme: TextButtonThemeData(style: TextButton.styleFrom(foregroundColor: AppColor.primary10)), return; // invalid, do not assign
), }
child: child!,
); model.deliveryInspectionInspectedDateTo = toDateTime;
}, setState(() {});
).then((selectedTime) {
if (selectedTime != null) {
model.deliveryInspectionInspectedDateTo = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute);
calculateTotalTime();
///Need to check need validation or not..
// if (widget.pickerFromDate != null && _pickerStartAt!.isBefore(widget.pickerFromDate!)) {
// "Start time is before the request time.".showToast;
// _pickerStartAt = null;
// selectedTime = null;
// return;
// }
if (model.deliveryInspectionInspectedDateTo!.isAfter(DateTime.now())) {
"End time is after than current time".showToast;
model.deliveryInspectionInspectedDateTo = null;
selectedTime = null;
return;
}
setState(() {});
}
});
}, },
), ),
], ],
); );
} }
bool _validateInspectionDates({DateTime? from, DateTime? to}) {
if (from == null && to == null) return true;
if (from != null) {
if (from.isAfter(DateTime.now())) {
"Time From cannot be in the future".showToast;
return false;
}
if (to != null && from.isAfter(to)) {
"Time To cannot be after Time From".showToast;
return false;
}
}
if (to != null) {
if (to.isAfter(DateTime.now())) {
"Time To cannot be in the future".showToast;
return false;
}
if (from != null && to.isBefore(from)) {
"Timer To cannot be before from time".showToast;
return false;
}
}
if (from != null && to != null) {
final diffInSeconds = to.difference(from).inSeconds;
if (diffInSeconds < 0) {
model.totalTime = null;
return false;
}
final hours = diffInSeconds / 3600.0;
model.totalTime = num.parse(hours.toStringAsFixed(3));
} else {
model.totalTime = null;
}
return true;
}
String formatInspectionDuration(num? hours) {
if (hours == null) return '-';
if (hours < 1) {
final minutes = (hours * 60).round();
return '$minutes minutes';
}
return '${hours.toStringAsFixed(2)} hours';
}
Widget _timePickerThemeBuilder(BuildContext context, Widget? child) {
final ThemeData currentTheme = Theme.of(context);
return Theme(
data: currentTheme.copyWith(
timePickerTheme: TimePickerThemeData(
dialHandColor: AppColor.primary10,
dialBackgroundColor: Colors.grey.withOpacity(0.1),
hourMinuteColor: MaterialStateColor.resolveWith(
(states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.grey.withOpacity(0.1),
),
dayPeriodColor: MaterialStateColor.resolveWith(
(states) => states.contains(MaterialState.selected) ? AppColor.primary10 : Colors.transparent,
),
dayPeriodTextColor: MaterialStateColor.resolveWith(
(states) => states.contains(MaterialState.selected) ? Colors.white : AppColor.primary10,
),
dayPeriodBorderSide: BorderSide(
color: Colors.grey.withOpacity(0.2),
),
entryModeIconColor: AppColor.primary10,
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: AppColor.primary10,
),
),
),
child: child!,
);
}
Widget inspectionDetails() { Widget inspectionDetails() {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -417,13 +540,69 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
); );
} }
void _attachmentTap() async { Widget _inspectionTile({
Navigator.push( required String title,
context, InspectionPersonModel? model,
MaterialPageRoute( required bool isHmg,
builder: (context) => AssetDeliveryAttachmentView( required VoidCallback onTap,
tableItemId: widget.deliveryTableModel.id, }) {
))); return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: AppColor.fieldBgColor(context),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: AppTextStyles.textFieldLabelStyle),
6.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
model?.name?.isNotEmpty == true ? model!.name! : 'Tap to add'.addTranslation,
style: AppTextStyles.bodyText,
),
///Need to display other info as well
// Text(
// model?.email?.isNotEmpty == true
// ? model!.email!
// : '',
// style: AppTextStyles.bodyText,
// ),
],
),
],
),
],
),
),
);
}
Future<Lookup?> showAttachmentTypePicker() {
return showDialog<Lookup>(
context: context,
builder: (_) {
return AlertDialog(
content: SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProvider>(
context: context,
title: context.translation.reason,
showAsFullScreenDialog: false,
onSelect: (value) {
Navigator.pop(context, value);
},
),
);
},
);
} }
void _cancelTap() async { void _cancelTap() async {
@ -469,4 +648,40 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
} }
}); });
} }
Future<InspectionPersonModel?> showInspectionBottomSheet(
BuildContext context, {
required String title,
required bool isHmg,
required InspectionPersonModel initialModel,
}) {
return showModalBottomSheet<InspectionPersonModel>(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (_) {
if (initialModel.localSignature == null && initialModel.signature != null) {
initialModel.localSignature = signatureFromString(initialModel.signature);
}
return InspectionPersonBottomSheet(
title: title,
isHmg: isHmg,
model: InspectionPersonModel(
name: initialModel.name,
email: initialModel.email,
signature: initialModel.signature,
localSignature: initialModel.localSignature,
),
);
},
);
}
Uint8List? signatureFromString(String? value) {
if (value == null || !value.contains('|')) return null;
final base64Part = value.split('|').last;
return base64Decode(base64Part);
}
} }

@ -0,0 +1,152 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/inspection_person_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
class InspectionPersonBottomSheet extends StatefulWidget {
final String title;
bool isHmg;
final InspectionPersonModel model;
InspectionPersonBottomSheet({
super.key,
required this.title,
required this.isHmg,
required this.model,
});
@override
State<InspectionPersonBottomSheet> createState() => _InspectionPersonBottomSheetState();
}
class _InspectionPersonBottomSheetState extends State<InspectionPersonBottomSheet> {
late InspectionPersonModel _model;
late TextEditingController nameController;
late TextEditingController emailController;
@override
void initState() {
super.initState();
_model = InspectionPersonModel(name: widget.model.name, email: widget.model.email, signature: widget.model.signature, localSignature: widget.model.localSignature);
nameController = TextEditingController(text: _model.name ?? '');
emailController = TextEditingController(text: _model.email ?? '');
}
@override
void dispose() {
nameController.dispose();
emailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: Padding(
padding: EdgeInsets.only(
top: 16,
left: 16,
right: 16,
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(widget.title, style: Theme.of(context).textTheme.titleLarge),
16.height,
if (widget.isHmg)
OracleUserAutoCompleteField(
clearAfterPick: false,
initialValue: _model.name ?? '',
label: 'Name'.addTranslation,
onPick: (value) {
_model.name = value.fullName;
nameController.text = value.fullName ?? '';
emailController.text = value.employeeEmail ?? '';
setState(() {});
},
)
else
AppTextFormField(
labelText: 'Name'.addTranslation,
controller: nameController,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
style: Theme.of(context).textTheme.titleMedium,
onChange: (v) {
_model.name = v;
setState(() {});
},
),
12.height,
AppTextFormField(
labelText: 'Email'.addTranslation,
controller: emailController,
textInputType: TextInputType.emailAddress,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
enable: widget.isHmg?false:true,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
style: Theme.of(context).textTheme.titleMedium,
onChange: (v) {
setState(() {
_model.email = v;
});
},
),
12.height,
ESignature(
title: '',
oldSignature: _model.localSignature == null ? _model.signature : null,
newSignature: _model.localSignature,
backgroundColor: AppColor.neutral100,
showShadow: false,
onChange: (signature) {
if (signature.isEmpty) return;
setState(() {
_model.localSignature = signature;
_model.signature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
onSaved: (signature) {
if (signature == null || signature.isEmpty) return;
setState(() {
_model.localSignature = signature;
_model.signature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
});
},
),
20.height,
AppFilledButton(
label: context.translation.save,
maxWidth: true,
buttonColor: AppColor.primary10,
onPressed: () async {
_model.name = nameController.text.trim();
_model.email = emailController.text.trim();
Navigator.pop(context, _model);
},
),
],
),
),
);
}
}

@ -26,25 +26,26 @@ class OracleUserAutoCompleteField extends StatefulWidget {
class _AutoCompletePartsFieldState extends State<OracleUserAutoCompleteField> { class _AutoCompletePartsFieldState extends State<OracleUserAutoCompleteField> {
AssetDeliveryProvider? assetDeliveryProvider; AssetDeliveryProvider? assetDeliveryProvider;
late TextEditingController _controller;
// late TextEditingController _controller;
@override @override
void initState() { void initState() {
_controller = TextEditingController(text: widget.initialValue); // _controller = TextEditingController(text: widget.initialValue);
super.initState(); super.initState();
} }
@override @override
void didUpdateWidget(covariant OracleUserAutoCompleteField oldWidget) { void didUpdateWidget(covariant OracleUserAutoCompleteField oldWidget) {
if (widget.initialValue != oldWidget.initialValue) { // if (widget.initialValue != oldWidget.initialValue) {
_controller = TextEditingController(text: widget.initialValue); // _controller = TextEditingController(text: widget.initialValue);
} // }
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
} }
@override @override
void dispose() { void dispose() {
_controller.dispose(); // _controller.dispose();
super.dispose(); super.dispose();
} }
@ -59,16 +60,18 @@ class _AutoCompletePartsFieldState extends State<OracleUserAutoCompleteField> {
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
), ),
child: Autocomplete<OracleUserModel>( child: Autocomplete<OracleUserModel>(
key: ValueKey(widget.initialValue),
optionsBuilder: (TextEditingValue textEditingValue) async { optionsBuilder: (TextEditingValue textEditingValue) async {
if (textEditingValue.text.isEmpty) { if (textEditingValue.text.isEmpty) {
return const Iterable<OracleUserModel>.empty(); return const Iterable<OracleUserModel>.empty();
} }
return await assetDeliveryProvider!.getOracleUserAutoCompleteDetails(query: textEditingValue.text); return await assetDeliveryProvider!.getOracleUserAutoCompleteDetails(query: textEditingValue.text);
}, },
initialValue: TextEditingValue(text: widget.initialValue),
displayStringForOption: (OracleUserModel option) => option.fullName ?? "", displayStringForOption: (OracleUserModel option) => option.fullName ?? "",
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
return TextField( return TextField(
controller: _controller, controller: fieldTextEditingController,
focusNode: fieldFocusNode, focusNode: fieldFocusNode,
style: AppTextStyles.bodyText.copyWith(color: AppColor.black10), style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
textAlign: TextAlign.start, textAlign: TextAlign.start,
@ -101,11 +104,11 @@ class _AutoCompletePartsFieldState extends State<OracleUserAutoCompleteField> {
); );
}, },
onSelected: (OracleUserModel selection) { onSelected: (OracleUserModel selection) {
if (widget.clearAfterPick) { // if (widget.clearAfterPick) {
_controller.clear(); // fieldTextEditingController.clear();
} else { // } else {
_controller.text = selection.fullName ?? ''; // _controller.text = selection.fullName ?? '';
} // }
widget.onPick(selection); widget.onPick(selection);
}, },
), ),

@ -90,10 +90,12 @@ class EndUserAssetDetailCard extends StatelessWidget {
'Replaced Asset No: ${assetModel.replacedAssetNo ?? '-'}', 'Replaced Asset No: ${assetModel.replacedAssetNo ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
), ),
Text( //TODO Need to confirm with @Ahmed need to hide this or not
'Rejection Reason: ${assetModel.rejectionReason?.name ?? '-'}', if (assetModel.status?.value == 2)
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), Text(
), 'Rejection Reason: ${assetModel.rejectionReason?.name ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text( Text(
'Description: ${assetModel.description ?? '-'}', 'Description: ${assetModel.description ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),

@ -5,6 +5,7 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/helper_function.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
@ -156,12 +157,7 @@ class _EndUserCostCenterLIstViewState extends State<EndUserCostCenterLIstView> {
} }
void _attachmentTap() async { void _attachmentTap() async {
Navigator.push( HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: widget.deliveryTableModel.id,
)));
} }
void _cancelTap() async { void _cancelTap() async {

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

@ -235,16 +235,6 @@ class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCe
onChanged: (value) {}, onChanged: (value) {},
), ),
8.height, 8.height,
AppTextFormField(
labelText: 'Accepted By Email'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByEmailController,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: false,
style: Theme.of(context).textTheme.titleMedium,
),
] else ...[ ] else ...[
AppTextFormField( AppTextFormField(
labelText: 'Accepted By'.addTranslation, labelText: 'Accepted By'.addTranslation,
@ -253,25 +243,34 @@ class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCe
textAlign: TextAlign.center, textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle, labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false, showShadow: false,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onChange: (value) { onChange: (value) {
model.acceptedBy = value; model.acceptedBy = value;
}, },
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
8.height, 8.height,
AppTextFormField(
labelText: 'Accepted By Email'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByEmailController,
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
onChange: (value) {
model.acceptedByEmail = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
], ],
AppTextFormField(
labelText: 'Accepted By Email'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
controller: acceptedByEmailController,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onChange: (value) {
model.acceptedByEmail = value;
},
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
enable: widget.isHmg == true ? false : true,
style: Theme.of(context).textTheme.titleMedium,
),
8.height, 8.height,
ESignature( ESignature(
title: 'End User Signature', title: 'End User Signature',
@ -280,11 +279,6 @@ class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCe
backgroundColor: AppColor.neutral100, backgroundColor: AppColor.neutral100,
showShadow: false, showShadow: false,
onChange: (signature) { onChange: (signature) {
log('onChange called.');
updateSignature(signature: signature);
},
onSaved: (signature) {
log('onSaved called.');
updateSignature(signature: signature); updateSignature(signature: signature);
}, },
) )
@ -294,7 +288,10 @@ class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCe
void updateSignature({Uint8List? signature}) { void updateSignature({Uint8List? signature}) {
if (signature == null || signature.isEmpty) { if (signature == null || signature.isEmpty) {
model.acceptedBySignature = ''; setState(() {
newSignature = null;
model.acceptedBySignature = null;
});
return; return;
} }
setState(() { setState(() {
@ -304,6 +301,23 @@ class _UpdateEndUserCostCenterDetailsViewState extends State<UpdateEndUserCostCe
} }
void _saveTap() async { void _saveTap() async {
if (!_formKey.currentState!.validate()) {
return;
}
if (model.acceptanceDate == null) {
"Select Accepted date".showToast;
return;
}
if (widget.isHmg == true) {
if ((model.acceptedBy ?? '').isEmpty || (model.acceptedByEmail ?? '').isEmpty) {
'Accepted By and Email are required'.addTranslation.showToast;
return;
}
}
if (model.acceptedBySignature == null || model.acceptedBySignature!.isEmpty) {
'Signature is required'.addTranslation.showToast;
return;
}
_formKey.currentState!.save(); _formKey.currentState!.save();
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
model.assetDeliveryExternalDetailId = widget.tableItemId; model.assetDeliveryExternalDetailId = widget.tableItemId;

@ -7,7 +7,7 @@ import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/asset_delivery_utils.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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/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_filled_button.dart';

@ -75,6 +75,14 @@ class TechnicalInspectionAssetCard extends StatelessWidget {
'Asset Number: ${assetModel.assetNumber ?? '-'}', 'Asset Number: ${assetModel.assetNumber ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
), ),
Text(
'Model: ${assetModel.modelDefinition?.model ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text(
'Manufacturer: ${assetModel.modelDefinition?.manufacturer ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
),
Text( Text(
'Serial Number: ${assetModel.serialNo ?? '-'}', 'Serial Number: ${assetModel.serialNo ?? '-'}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),

@ -8,6 +8,7 @@ import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/helper_function.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
@ -224,12 +225,13 @@ class _TechnicalInspectionLinesListViewState extends State<TechnicalInspectionLi
} }
void _attachmentTap() async { void _attachmentTap() async {
Navigator.push( HelperFunction.attachmentTap(context: context, assetDeliveryProvider: assetDeliveryProvider!, deliveryTableItemId: widget.deliveryTableModel.id);
context, // Navigator.push(
MaterialPageRoute( // context,
builder: (context) => AssetDeliveryAttachmentView( // MaterialPageRoute(
tableItemId: widget.deliveryTableModel.id, // builder: (context) => AssetDeliveryAttachmentView(
))); // tableItemId: widget.deliveryTableModel.id,
// )));
} }
void _cancelTap() async { void _cancelTap() async {

@ -10,7 +10,7 @@ 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/floor.dart';
import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/asset_delivery_utils.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/search_asset_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/search_asset_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/status_checklist_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/status_checklist_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart'; import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
@ -189,11 +189,48 @@ class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
} }
}), }),
8.height, 8.height,
AppTextFormField(
labelText: 'Asset Name'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.assetName,
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Model'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.model,
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Manufacturer'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.manufacturer ?? '',
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField( AppTextFormField(
labelText: 'Serial Number'.addTranslation, labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context), backgroundColor: AppColor.fieldBgColor(context),
controller: serialNoCtrl, controller: serialNoCtrl,
initialValue: model.serialNo ?? '', initialValue: model.serialNo ?? '',
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
textAlign: TextAlign.center, textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle, labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number, textInputType: TextInputType.number,
@ -346,7 +383,13 @@ class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
///Need to check which details show here... ///Need to check which details show here...
void _saveTap() async { void _saveTap() async {
if(!_formKey.currentState!.validate()) return;
if(assetDeliveryProvider.childFormModel.installationDate==null){
"Installation Date is Required".showToast;
return;
}
_formKey.currentState!.save(); _formKey.currentState!.save();
//Need to check if not auto update. //Need to check if not auto update.
// assetDeliveryProvider.parentFormModel.childAssetList?[widget.index]= assetDeliveryProvider.childFormModel; // assetDeliveryProvider.parentFormModel.childAssetList?[widget.index]= assetDeliveryProvider.childFormModel;
Navigator.pop(context); Navigator.pop(context);
@ -423,6 +466,10 @@ class _UpdateChildAssetViewState extends State<UpdateChildAssetView> {
} }
String _statusFromBool(bool? value) { String _statusFromBool(bool? value) {
return value == true ? 'PASS' :value==false? 'FAIL':''; return value == true
? 'PASS'
: value == false
? 'FAIL'
: '';
} }
} }

@ -10,7 +10,7 @@ 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/floor.dart';
import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/technical_inspection_asset_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/asset_delivery_utils.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_utils.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/search_asset_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/search_asset_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/status_checklist_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/status_checklist_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart'; import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inpection_asset_card_view.dart';
@ -216,20 +216,64 @@ class _UpdateParentAssetViewState extends State<UpdateParentAssetView> {
if (assetModel.site != null) { if (assetModel.site != null) {
await provider.getSiteData(siteId: assetModel.site?.id, model: provider.parentFormModel); await provider.getSiteData(siteId: assetModel.site?.id, model: provider.parentFormModel);
} }
assetModel.assetDeliveryInternalDetailAssetId = assetModel.id; assetModel.assetDeliveryInternalDetailAssetId = assetModel.id;
assetModel.id = 0; assetModel.id = 0;
if (assetModel.childAssetList != null && assetModel.childAssetList!.isNotEmpty) {
for (var asset in assetModel.childAssetList!) {
asset.assetDeliveryInternalDetailAssetChildId = asset.id;
asset.id = 0;
}
}
provider.setParentModel(assetModel); provider.setParentModel(assetModel);
log('child list length ${assetModel.childAssetList?.length}'); log('child list length ${assetModel.childAssetList?.length}');
populateTextFields(model: provider.parentFormModel); populateTextFields(model: provider.parentFormModel);
} }
} }
}), }),
8.height, 8.height,
AppTextFormField(
labelText: 'Asset Name'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.assetName,
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Model'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.model,
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: 'Manufacturer'.addTranslation,
// backgroundColor: AppColor.fieldBgColor(context),
initialValue: model.modelDefinition?.manufacturer ?? '',
textAlign: TextAlign.center,
enable: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField( AppTextFormField(
labelText: 'Serial Number'.addTranslation, labelText: 'Serial Number'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context), backgroundColor: AppColor.fieldBgColor(context),
controller: serialNoCtrl, controller: serialNoCtrl,
initialValue: model.serialNo ?? '', initialValue: model.serialNo ?? '',
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
textAlign: TextAlign.center, textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle, labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number, textInputType: TextInputType.number,
@ -384,6 +428,11 @@ class _UpdateParentAssetViewState extends State<UpdateParentAssetView> {
///Need to check which details show here... ///Need to check which details show here...
void _saveTap() async { void _saveTap() async {
if (!_formKey.currentState!.validate()) return;
if (assetDeliveryProvider.parentFormModel.installationDate == null) {
"Installation Date is Required".showToast;
return;
}
_formKey.currentState!.save(); _formKey.currentState!.save();
assetDeliveryProvider.parentFormModel.lineId = widget.lineId; assetDeliveryProvider.parentFormModel.lineId = widget.lineId;

@ -179,6 +179,10 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
title: 'Power Supply Type'.addTranslation, title: 'Power Supply Type'.addTranslation,
titleTextColor: AppColor.neutral120, titleTextColor: AppColor.neutral120,
showShadow: false, showShadow: false,
validator: (value) {
if (value == null) return 'Please select power supply type';
return null;
},
backgroundColor: AppColor.fieldBgColor(context), backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true, showAsBottomSheet: true,
initialValue: model.powerSupplyType, initialValue: model.powerSupplyType,
@ -198,6 +202,10 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
labelStyle: AppTextStyles.textFieldLabelStyle, labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number, textInputType: TextInputType.number,
showShadow: false, showShadow: false,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onSaved: (value) { onSaved: (value) {
model.powerReading = int.tryParse(value); model.powerReading = int.tryParse(value);
}, },
@ -212,6 +220,10 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
labelStyle: AppTextStyles.textFieldLabelStyle, labelStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.number, textInputType: TextInputType.number,
showShadow: false, showShadow: false,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onSaved: (value) { onSaved: (value) {
model.maxCurrent = int.tryParse(value); model.maxCurrent = int.tryParse(value);
}, },
@ -224,6 +236,10 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
textInputType: TextInputType.number, textInputType: TextInputType.number,
initialValue: model.voltage != null ? model.voltage.toString() : '', initialValue: model.voltage != null ? model.voltage.toString() : '',
textAlign: TextAlign.center, textAlign: TextAlign.center,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onSaved: (value) { onSaved: (value) {
model.voltage = int.tryParse(value); model.voltage = int.tryParse(value);
}, },
@ -238,6 +254,10 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
initialValue: model.frequency != null ? model.frequency.toString() : '', initialValue: model.frequency != null ? model.frequency.toString() : '',
textInputType: TextInputType.number, textInputType: TextInputType.number,
textAlign: TextAlign.center, textAlign: TextAlign.center,
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
onSaved: (value) { onSaved: (value) {
model.frequency = int.tryParse(value); model.frequency = int.tryParse(value);
}, },
@ -250,6 +270,7 @@ class _UpdateTechnicalInspectionLinesViewState extends State<UpdateTechnicalInsp
} }
void _saveTap() async { void _saveTap() async {
if (!_formKey.currentState!.validate()) return;
_formKey.currentState!.save(); _formKey.currentState!.save();
model.tableItemId = widget.deliveryTableModel.id; model.tableItemId = widget.deliveryTableModel.id;
model.lineId = widget.deliveryLineModel?.id; model.lineId = widget.deliveryLineModel?.id;

@ -11,6 +11,7 @@ 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/room_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_serial_no_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/end_user_asset_details_model.dart'; import 'package:test_sa/modules/asset_delivery_module/models/end_user_asset_details_model.dart';
@ -171,33 +172,38 @@ class AssetDeliveryProvider extends ChangeNotifier {
} }
} }
Future<List<CostCenterModel>> getAssetDeliveryCostCenterListForLines({int? lineId, int? tableItemId}) async { Future<CostCenterSerialNoFormModel> getAssetDeliveryCostCenterListForLines({
List<CostCenterModel> costCenterList = []; int? lineId,
int? tableItemId,
}) async {
CostCenterSerialNoFormModel costCenterSerialNoFormModel = CostCenterSerialNoFormModel();
try { try {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
final response = await ApiManager.instance.get( final response = await ApiManager.instance.get(
"${URLs.getCostCenterListToLineDeliveryInspection}?AssetDeliveryExternalDetailId=$lineId&AssetDeliveryExternalDeliveryId=$tableItemId", "${URLs.getCostCenterAndSerialNoToLineDeliveryInspection}?AssetDeliveryExternalDetailId=$lineId&AssetDeliveryExternalDeliveryId=$tableItemId",
); );
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body)["data"]; final jsonData = json.decode(response.body)["data"];
if (jsonData is List) { costCenterSerialNoFormModel = CostCenterSerialNoFormModel.fromJson(jsonData);
costCenterList = jsonData.map((e) => CostCenterModel.fromJson(e)).toList();
}
} else { } else {
costCenterList = []; costCenterSerialNoFormModel.costCenters = [];
costCenterSerialNoFormModel.serialNos = [];
} }
isLoading = false;
notifyListeners();
return costCenterList;
} catch (e) { } catch (e) {
log("get Delivery Lines List [error] : $e"); log("get Delivery Lines List [error] : $e");
costCenterSerialNoFormModel.costCenters = [];
costCenterSerialNoFormModel.serialNos = [];
} finally {
isLoading = false; isLoading = false;
costCenterList = [];
notifyListeners(); notifyListeners();
return costCenterList;
} }
return costCenterSerialNoFormModel;
} }
Future<bool> addNewDelivery({ Future<bool> addNewDelivery({
@ -253,15 +259,17 @@ class AssetDeliveryProvider extends ChangeNotifier {
int? tableItemId, int? tableItemId,
int? lineId, int? lineId,
List<CostCenterModel>? list, List<CostCenterModel>? list,
List<SerialNoModel>? serialNoList,
}) async { }) async {
isLoading = true; isLoading = true;
Map<String, dynamic> payload = { Map<String, dynamic> payload = {
"assetDeliveryExternalDeliveryId": tableItemId, "assetDeliveryExternalDeliveryId": tableItemId,
"assetDeliveryExternalDetailId": lineId, "assetDeliveryExternalDetailId": lineId,
"costCenters": list?.map((x) => x.toJson()).toList(), "costCenters": list?.map((x) => x.toJson()).toList(),
if (serialNoList != null && serialNoList.isNotEmpty) "serialNos": serialNoList.map((x) => x.toJson()).toList(),
}; };
try { try {
final response = await ApiManager.instance.post(URLs.saveCostCenterToLineDeliveryInspection, body: payload); final response = await ApiManager.instance.post(URLs.saveCostCenterAndSerialNoToLineDeliveryInspection, body: payload);
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false; isLoading = false;
@ -421,10 +429,11 @@ class AssetDeliveryProvider extends ChangeNotifier {
Future<List<GenericAttachmentModel>> getAttachments({ Future<List<GenericAttachmentModel>> getAttachments({
num? tableItemId, num? tableItemId,
num? attachmentType,
}) async { }) async {
try { try {
isLoading = true; isLoading = true;
final response = await ApiManager.instance.get("${URLs.getAttachments}?assetDeliveryExternalDeliveryId=$tableItemId"); final response = await ApiManager.instance.get("${URLs.getAttachments}?attachmentDocTypeValue=$attachmentType&assetDeliveryExternalDeliveryId=$tableItemId");
List<GenericAttachmentModel> list = []; List<GenericAttachmentModel> list = [];
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
isLoading = false; isLoading = false;

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

@ -18,13 +18,12 @@ class AppBottomNavigationBar extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.engineer; bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.engineer;
bool isUserFMS = Provider.of<SettingProvider>(context, listen: false).isUserFMS; bool isUserFMS = Provider.of<SettingProvider>(context, listen: false).isUserFMS;
bool commissioningEng = context.userProvider.isCommissioningEngineer;
List<NavItemModel> navItems = [ List<NavItemModel> navItems = [
NavItemModel(0, "overview", context.translation.overview), NavItemModel(0, "overview", context.translation.overview),
NavItemModel(1, "request_icon", context.translation.workOrder), NavItemModel(1, "request_icon", context.translation.workOrder),
//TODO unCommit this to disable task if (!commissioningEng) NavItemModel(2, "add_icon", context.translation.calendar, showLabel: false),
// if (!isEngineer||isUserFMS)
NavItemModel(2, "add_icon", context.translation.calendar, showLabel: false),
NavItemModel(3, "assets", context.translation.assets), NavItemModel(3, "assets", context.translation.assets),
NavItemModel(4, "contact", context.translation.contact), NavItemModel(4, "contact", context.translation.contact),
]; ];

@ -106,6 +106,12 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
types['Equipment Internal Audit'] = 10; types['Equipment Internal Audit'] = 10;
types['System Internal Audit'] = 11; types['System Internal Audit'] = 11;
} }
if (context.userProvider.isCommissioningEngineer) {
///TODO need to check what other requests type needed here.
types = {
'Asset Delivery': 13,
};
}
final statuses = { final statuses = {
"All WO": 0, "All WO": 0,

@ -69,7 +69,7 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
requestsList.add(Request(10, 'Equipment Internal Audit')); requestsList.add(Request(10, 'Equipment Internal Audit'));
requestsList.add(Request(11, 'System Internal Audit')); requestsList.add(Request(11, 'System Internal Audit'));
//Need to be added for new user role commissioning engineer //Need to be added for new user role commissioning engineer
requestsList.add(Request(13, "Asset Delivery")); // requestsList.add(Request(13, "Asset Delivery"));
} }
requestsList.add(Request(12, "Loan Equipment")); requestsList.add(Request(12, "Loan Equipment"));
@ -80,6 +80,13 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
Request(9, 'TRAF'), Request(9, 'TRAF'),
]; ];
} }
if (context.userProvider.isCommissioningEngineer) {
///TODO need to show only allowed ids for all workOrder
requestsList = [
Request(null, context.translation.allWorkOrder),
Request(13, "Asset Delivery"),
];
}
if (context.userProvider.isQualityUser) { if (context.userProvider.isQualityUser) {
requestsList = [ requestsList = [
Request(null, context.translation.allWorkOrder), Request(null, context.translation.allWorkOrder),

Loading…
Cancel
Save