requested changes done

design_3.0_asset_delivery_module
WaseemAbbasi22 1 week ago
parent ab6b143763
commit 3944a549b2

@ -68,9 +68,11 @@ class URLs {
//service request new flow urls.
static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount';
static get qaAuditorCount => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorCount';
static get commissioningEngineerCount => '$_baseUrl/ServiceRequest/GetDashboardCommissioningEngineerCount';
static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails';
static get qaAuditorDetails => '$_baseUrl/ServiceRequest/GetDashboardQAAuditorDetails';
static get commissioningEngineerDetails => '$_baseUrl/ServiceRequest/GetDashboardCommissioningEngineerDetails';
static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject';
@ -413,8 +415,10 @@ class URLs {
static get getLineFromExternalPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetLineFromExternalPo';
static get getCostCenterListToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToLineDeliveryInspection';
static get getCostCenterAndSerialNoToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterAndSerialNoToLineDeliveryInspection';
static get getCostCenterToPo => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/GetCostCenterToPo';
static get saveCostCenterToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterToLineDeliveryInspection';
static get saveCostCenterAndSerialNoToLineDeliveryInspection => '$_baseUrl/AssetDeliveryExternalDeliveryInspection/SaveCostCenterAndSerialNoToLineDeliveryInspection';
static get getDeliveryHistories => '$_baseUrl/AssetDeliveryExternalDelivery/GetDeliveryHistories';
//Technical Inscption...
static get getLineFromTechnicalInspection => '$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetLineFromDeliveryInspection';
@ -425,7 +429,7 @@ class URLs {
static get getAssetFromInternalTechnicalInspection => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetFromInternal";
static get getAssetDetailsByAssetId => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/GetAssetByIdFromInternal";
static get saveTechnicalInspectionAsset => "$_baseUrl/AssetDeliveryExternalTechnicalInspection/SaveTechnicalInspectionItem";
static get getAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/GetAttachments";
static get getAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/GetAttachmentsBasedOnType";
static get saveAttachments => "$_baseUrl/AssetDeliveryExternalDeliveryAttachment/Save";
//End user Acceptance...
static get getEndUserAcceptanceCostCenter => "$_baseUrl/AssetDeliveryEndUserAcceptance/GetEndUserAcceptanceCostCenter";
@ -433,5 +437,6 @@ class URLs {
static get saveEndUserFormData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveMaster";
static get saveEndUserAssetData => "$_baseUrl/AssetDeliveryEndUserAcceptance/SaveDetail";
static get endUserStatusLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=534";
static get endUserRejectionReasonLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=5007";
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) {
list.add(9); //
}
list.add(12); // loan module
list.add(12);
if (context.userProvider.isCommissioningEngineer) {
list = [13];
}
// loan module
return list;
}

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

@ -106,13 +106,22 @@ class DashBoardProvider extends ChangeNotifier {
isAllCountLoading = true;
notifyListeners();
String url = '';
if (usersType == UsersTypes.qualityUser) {
url = URLs.qaAuditorCount;
} else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) {
url = URLs.engineerDashboardCountUrl;
} else {
url = URLs.nurseDashboardCountUrl;
}
// if (usersType == UsersTypes.qualityUser) {
// url = URLs.qaAuditorCount;
// } else if (usersType == UsersTypes.engineer || usersType == UsersTypes.assessor || usersType == UsersTypes.assessorTl) {
// url = URLs.engineerDashboardCountUrl;
// } 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;
try {
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 {
if (showLoader) {
isDetailLoading = showLoader;
@ -243,25 +278,26 @@ class DashBoardProvider extends ChangeNotifier {
Response response;
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 {
Map<String, dynamic> body = {"pageNumber": pageNum, "pageSize": pageItemNumber};
@ -383,6 +419,12 @@ class CategoryTabs {
tabs.add(CategoryTabs(label: 'Closed', tag: 3, id: 4));
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: 'In Progress', tag: 2, id: 3));

@ -125,3 +125,9 @@ enum DropDownMatchType {
identifier,
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_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/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/end_user_rejection_reason_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: (_) => EndUserStatusLookupProvider()),
ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider()),
ChangeNotifierProvider(create: (_) => AttachmentTypeLookupProvider()),
],
child: GestureDetector(
onTap: () {

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

@ -108,10 +108,13 @@ class User {
return UsersTypes.assessor;
case "R-19": // Head Nurse Role
return UsersTypes.assessorTl;
//TODO need to confirm why repeat.
case "R-3": // Quality User
return UsersTypes.qualityUser;
case "R-58": // Quality User
return UsersTypes.qualityUser;
case "R-201": // Quality User
return UsersTypes.commissioningEngineer;
default:
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);
},
),
],
),
),
);
},
);
}
}

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

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

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

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.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/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/cost_center_serial_no_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/cost_center_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
@ -47,8 +46,9 @@ class CostCenterFormView extends StatefulWidget {
}
class _CostCenterFormViewState extends State<CostCenterFormView> {
List<CostCenterModel> _list = [];
CostCenterSerialNoFormModel formModel = CostCenterSerialNoFormModel(costCenters: [], serialNos: []);
late AssetDeliveryProvider assetDeliveryProvider;
CostCenterType _selectedType = CostCenterType.costCenter;
@override
void initState() {
@ -60,15 +60,20 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
}
void getInitialData() async {
_list = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines(
formModel = await assetDeliveryProvider.getAssetDeliveryCostCenterListForLines(
lineId: widget.lineId,
tableItemId: widget.tableItemId,
);
if (_list.isEmpty) {
_list.add(CostCenterModel(
if (formModel.costCenters!.isEmpty) {
formModel.costCenters!.add(CostCenterModel(
id: 0,
));
}
// if (formModel.serialNos!.isEmpty) {
// formModel.serialNos!.add(SerialNoModel(
// id: 0,
// ));
// }
if (widget.isHmg == true) {
CostCenterProvider costCenterProvider = Provider.of<CostCenterProvider>(context, listen: false);
if (costCenterProvider.items.isEmpty) {
@ -78,21 +83,21 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
setState(() {});
}
void _addNewEntry() {
void addItem<T>(List<T> list, T Function() creator) {
setState(() {
_list.add(CostCenterModel(costCenter: Lookup()));
list.add(creator());
});
}
void _removeEntry(int index) {
void removeItem<T>(List<T> list, int index) {
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(() {
updateList(_list[index]);
updater(list[index]);
});
}
@ -111,34 +116,9 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
? const CircularProgressIndicator(color: AppColor.primary10).center
: Column(
children: [
itemDetails(context: context, itemNo: widget.itemNo, itemDescription: widget.itemDescription),
ListView.builder(
itemCount: _list.length + 1,
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,
itemDetails(),
selectionButton(),
_selectedType == CostCenterType.costCenter ? _buildCostCenterList() : _buildSerialNumberList(),
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
@ -147,7 +127,9 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
maxWidth: true,
onPressed: () async {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await assetDeliveryProvider.saveCostCenterToLineDeliveryInspection(tableItemId: widget.tableItemId, lineId: widget.lineId, list: _list).then((status) async {
await assetDeliveryProvider
.saveCostCenterToLineDeliveryInspection(tableItemId: widget.tableItemId, lineId: widget.lineId, list: formModel.costCenters, serialNoList: formModel.serialNos)
.then((status) async {
Navigator.pop(context);
if (status) {
Navigator.pop(context);
@ -163,40 +145,169 @@ class _CostCenterFormViewState extends State<CostCenterFormView> {
}),
);
}
}
Widget itemDetails({required BuildContext context, String? itemNo, String? itemDescription}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Item No'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
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),
Widget _buildCostCenterList() {
return ListView.builder(
itemCount: formModel.costCenters!.length + 1,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
itemBuilder: (context, index) {
if (index == formModel.costCenters!.length) {
return AppFilledButton(
label: "Add Cost Center".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: () {
addItem(formModel.costCenters!, () => CostCenterModel(costCenter: Lookup()));
},
);
}
return CostCenterItemCard(
model: formModel.costCenters![index],
index: index,
isReadOnly: false,
isHmg: widget.isHmg,
requestId: widget.requestId,
onUpdate: (update) {
updateItem<CostCenterModel>(formModel.costCenters!, index, update);
},
onRemove: () {
removeItem<CostCenterModel>(formModel.costCenters!, index);
},
);
},
).expanded;
}
Widget _buildSerialNumberList() {
return ListView.builder(
itemCount: formModel.serialNos!.length + 1,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8),
itemBuilder: (context, index) {
if (index == formModel.serialNos!.length) {
return AppFilledButton(
label: "Add Serial Number".addTranslation,
maxWidth: true,
textColor: AppColor.textColor(context),
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: () {
addItem(formModel.serialNos!, () => SerialNoModel());
},
);
}
return SerialNumberItemCard(
model: formModel.serialNos![index],
onUpdate: (update) {
updateItem<SerialNoModel>(formModel.serialNos!, index, update);
},
onRemove: () {
removeItem<SerialNoModel>(formModel.serialNos!, index);
},
);
},
).expanded;
}
Widget selectionButton() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
Expanded(
child: _radioItem(
value: CostCenterType.costCenter,
groupValue: _selectedType,
title: 'Cost Center',
onTap: () {
setState(() {
_selectedType = CostCenterType.costCenter;
});
},
),
),
Expanded(
child: _radioItem(
value: CostCenterType.serialNumber,
groupValue: _selectedType,
title: 'Serial Number',
onTap: () {
setState(() {
_selectedType = CostCenterType.serialNumber;
});
},
),
),
],
),
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,
padding: 12,
showShadow: false,
margin: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
);
);
}
Widget itemDetails() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Item No'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
widget.itemNo ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
8.height,
Text(
'Item Description'.addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10),
),
8.height,
Text(
widget.itemDescription ?? '-',
style: AppTextStyles.bodyText2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120),
),
],
).toShadowContainer(
context,
borderRadius: 20,
padding: 12,
showShadow: false,
margin: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
);
}
}
class CostCenterItemCard extends StatelessWidget {
@ -294,3 +405,53 @@ class CostCenterItemCard extends StatelessWidget {
).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:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
@ -7,21 +7,26 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/asset_delivery_module/helper_function.dart';
import 'package:test_sa/modules/asset_delivery_module/models/asset_delivery_data_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_inspection_form_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/delivery_line_model.dart';
import 'package:test_sa/modules/asset_delivery_module/models/inspection_person_model.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/asset_delivery_line_card_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/attachment_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/cost_center_form_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/oracle_user_autocomplete_field.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/delivery_inspection/inpection_bottomsheet.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/end_user_acceptance/end_user_cost_center_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/pages/technical_inpection/technical_inspection_lines_list_view.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/asset_delivery_provider.dart';
import 'package:test_sa/modules/asset_delivery_module/provider/attachment_type_provider.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
@ -129,7 +134,13 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
child: !viewOnly
? Column(
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,
Row(
children: [
@ -207,56 +218,109 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
Widget inspectionDetailsForm() {
return Column(
children: [
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;
_inspectionTile(
title: 'Inspected by'.addTranslation,
model: model.inspectedByModel,
isHmg: widget.requestModel?.isHMG == true,
onTap: () async {
final result = await showInspectionBottomSheet(
context,
title: 'Inspected by'.addTranslation,
isHmg: widget.requestModel?.isHMG == true,
initialModel: model.inspectedByModel ?? InspectionPersonModel(),
);
if (result != null) {
setState(() => model.inspectedByModel = result);
}
},
),
8.height,
_inspectionTile(
title: 'Approved by'.addTranslation,
model: model.approvedByModel,
isHmg: widget.requestModel?.isHMG == true,
onTap: () async {
final result = await showInspectionBottomSheet(
context,
title: 'Approved by'.addTranslation,
isHmg: widget.requestModel?.isHMG == true,
initialModel: model.approvedByModel ?? InspectionPersonModel(),
);
if (result != null) {
setState(() => model.approvedByModel = result);
}
},
),
if (widget.requestModel?.paymentTerm?.value == 2) ...[
_inspectionTile(
title: 'Third Approved by'.addTranslation,
model: model.thirdApprovalModel,
isHmg: widget.requestModel?.isHMG == true,
onTap: () async {
final result = await showInspectionBottomSheet(
context,
title: 'Third Approved by'.addTranslation,
isHmg: widget.requestModel?.isHMG == true,
initialModel: model.thirdApprovalModel ?? InspectionPersonModel(),
);
if (result != null) {
setState(() => model.thirdApprovalModel = result);
}
},
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,
ADatePicker(
label: 'Inspected Date/Time From'.addTranslation,
@ -417,13 +481,69 @@ class _DeliveryInspectionFormViewState extends State<DeliveryInspectionFormView>
);
}
void _attachmentTap() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AssetDeliveryAttachmentView(
tableItemId: widget.deliveryTableModel.id,
)));
Widget _inspectionTile({
required String title,
InspectionPersonModel? model,
required bool isHmg,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: AppColor.fieldBgColor(context),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: AppTextStyles.textFieldLabelStyle),
6.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
model?.name?.isNotEmpty == true ? model!.name! : 'Tap to add'.addTranslation,
style: AppTextStyles.bodyText,
),
///Need to display other info as well
// Text(
// model?.email?.isNotEmpty == true
// ? model!.email!
// : '',
// style: AppTextStyles.bodyText,
// ),
],
),
],
),
],
),
),
);
}
Future<Lookup?> showAttachmentTypePicker() {
return showDialog<Lookup>(
context: context,
builder: (_) {
return AlertDialog(
content: SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProvider>(
context: context,
title: context.translation.reason,
showAsFullScreenDialog: false,
onSelect: (value) {
Navigator.pop(context, value);
},
),
);
},
);
}
void _cancelTap() async {
@ -469,4 +589,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 ?? '');
widget.isHmg = true;
log('isHmg = ${widget.isHmg}');
}
@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 ?? '';
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,
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);
},
),
],
),
),
);
}
}

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

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

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

@ -106,6 +106,12 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
types['Equipment Internal Audit'] = 10;
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 = {
"All WO": 0,

@ -69,7 +69,7 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
requestsList.add(Request(10, 'Equipment Internal Audit'));
requestsList.add(Request(11, 'System Internal Audit'));
//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"));
@ -80,6 +80,13 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
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) {
requestsList = [
Request(null, context.translation.allWorkOrder),

Loading…
Cancel
Save