document library CR implementation

main_production_attahment_type
WaseemAbbasi22 14 hours ago
parent b9a354d2a2
commit 63d4c79a73

@ -3,12 +3,12 @@ class URLs {
static const String appReleaseBuildNumber = "50";
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://atomsmuat.hmg.com"; // local UAT url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static final String _baseUrl = "$_host/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/mobile"; // host local UAT
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/v3/mobile"; // v3 for production CM,PM,TM
// static final String _baseUrl = "$_host/v4/mobile"; // v4 for Demo module
// static final String _baseUrl = "$_host/v5/mobile"; // v5 for data segregation
@ -309,6 +309,7 @@ class URLs {
static get genderLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=3065";
static get getDemoDocumentTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=4106";
static get getAttachmentTypesLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=4021";
static get getClassificationTypeLookup => "$_baseUrl/Lookups/GetLookup?lookupEnum=450";

@ -153,6 +153,7 @@ class DeviceTransferProvider extends ChangeNotifier {
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
log('payload: ${model.toCreateAssetTransferJson()}');
response = await ApiManager.instance.post(URLs.createAssetTransferRequest, body: model.toCreateAssetTransferJson());
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {

@ -7,9 +7,12 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:haptic_feedback/haptic_feedback.dart';
import 'package:http/http.dart' as http;
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/nfc_manager_android.dart' show NfcAAndroid, NfcBAndroid;
import 'package:nfc_manager/nfc_manager_ios.dart' show MiFareIos, Iso15693Ios;
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
@ -193,6 +196,73 @@ class Utils {
);
}
static Future<File?> downloadFile(
String url, {
bool autoOpen = true,
bool showToast = true,
String? authToken,
String? fileName,
}) async {
final client = http.Client();
try {
if (showToast) {
Utils.showToast("Downloading file...", longDuration: false);
}
fileName ??= url.split('/').last.split('?').first;
if (!fileName.contains('.')) {
fileName = 'downloaded_file_${DateTime.now().millisecondsSinceEpoch}.jpg';
}
final request = http.Request('GET', Uri.parse(url));
if (authToken != null) {
request.headers['Authorization'] = 'Bearer $authToken';
}
request.followRedirects = false;
final streamedResponse = await client.send(request);
File? file;
final dir = await getTemporaryDirectory();
if (streamedResponse.statusCode == 302) {
final redirectUrl = streamedResponse.headers['location'];
if (redirectUrl == null) {
throw Exception('302 Redirect missing Location header');
}
final headers = authToken != null ? {'Authorization': 'Bearer $authToken'} : <String, String>{};
final fileResponse = await http.get(Uri.parse(redirectUrl), headers: headers);
if (fileResponse.statusCode == 200) {
file = File('${dir.path}/$fileName');
await file.writeAsBytes(fileResponse.bodyBytes);
} else {
throw Exception('Download from redirect failed: ${fileResponse.statusCode}');
}
}
else if (streamedResponse.statusCode == 200) {
file = File('${dir.path}/$fileName');
await file.writeAsBytes(await streamedResponse.stream.toBytes());
}
else {
throw Exception('Download failed with status: ${streamedResponse.statusCode}');
}
if (showToast) {
Utils.showToast("File downloaded successfully", longDuration: false);
}
if (autoOpen) {
await OpenFile.open(file.path);
}
return file;
} catch (ex) {
if (showToast) {
Utils.showToast("Download failed: ${ex.toString()}");
}
return null;
} finally {
client.close();
}
}
static bool isLocalFile(String path) {
if (path.isEmpty) return false;
return path.startsWith("/") || path.startsWith("file://") || (path.length > 1 && path.substring(1).startsWith(':\\'));
}
//
// static Widget getNoDataWidget(BuildContext context) {
// return Column(

@ -249,6 +249,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => EndUserStatusLookupProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => EndUserRejectionReasonLookupProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => AttachmentTypeLookupProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => AttachmentTypeLookupProviderLatest(), lazy: true),
ChangeNotifierProvider(create: (_) => DemoPeriodLookupProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => DemoDocumentLookupProvider(), lazy: true),
ChangeNotifierProvider(create: (_) => IncidentStatusLookupProvider(), lazy: true),

@ -55,7 +55,7 @@ class AssetByIdModel {
String? comment;
bool? isEnabled;
String? tagCode;
List<AssetAttachment>? assetAttachments;
List<GenericAttachmentModel>? assetAttachments;
String? retirementTypeName;
String? retirementStatusName;
String? retirementDate;
@ -198,9 +198,9 @@ class AssetByIdModel {
isEnabled = json['isEnabled'];
tagCode = json['tagCode'];
if (json['assetAttachments'] != null) {
assetAttachments = <AssetAttachment>[];
assetAttachments = <GenericAttachmentModel>[];
json['assetAttachments'].forEach((v) {
assetAttachments!.add(AssetAttachment.fromJson(v));
assetAttachments!.add(GenericAttachmentModel.fromAssetJson(v));
});
}
retirementTypeName = json['retirementTypeName'];
@ -298,7 +298,7 @@ class AssetByIdModel {
data['isEnabled'] = isEnabled;
data['tagCode'] = tagCode;
if (assetAttachments != null) {
data['assetAttachments'] = assetAttachments!.map((v) => v).toList();
data['assetAttachments'] = assetAttachments!.map((v) => v.toAssetJson()).toList();
}
data['retirementTypeName'] = retirementTypeName;
data['retirementStatusName'] = retirementStatusName;

@ -1,30 +1,39 @@
class AssetTransferAttachment {
AssetTransferAttachment({
this.id,
this.attachmentName,
});
AssetTransferAttachment.fromJson(dynamic json) {
id = json['id'];
attachmentName = json['attachmentName'];
}
num? id; // Now nullable
String? attachmentName; // Now nullable
AssetTransferAttachment copyWith({
num? id, // Parameter is now nullable
String? attachmentName, // Parameter is now nullable
}) =>
AssetTransferAttachment(
id: id ?? this.id,
attachmentName: attachmentName ?? this.attachmentName,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['attachmentName'] = attachmentName;
return map;
}
}
//TODO: need to remove this class
// import 'package:test_sa/models/lookup.dart';
//
// class AssetTransferAttachment {
// AssetTransferAttachment({
// this.id,
// this.attachmentName,
// this.documentType,
//
// });
//
// AssetTransferAttachment.fromJson(dynamic json) {
// id = json['id'];
// attachmentName = json['attachmentName'];
// }
//
// num? id; // Now nullable
// String? attachmentName; // Now nullable
// Lookup ? documentType;
//
// AssetTransferAttachment copyWith({
// num? id, // Parameter is now nullable
// String? attachmentName, // Parameter is now nullable
// Lookup? documentType, // Parameter is now nullable
// }) =>
// AssetTransferAttachment(
// id: id ?? this.id,
// attachmentName: attachmentName ?? this.attachmentName,
// documentType: documentType ?? this.documentType,
// );
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['id'] = id;
// map['attachmentName'] = attachmentName;
// map['documentTypeId'] = documentType?.id;
// return map;
// }
// }

@ -1,4 +1,5 @@
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/assistant_employee.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
@ -95,7 +96,6 @@ class DeviceTransfer {
this.assistantEmployList,
this.assetTransferAssistantEmployeesReceiver,
this.assetTransferAssistantEmployeesSender,
this.statusValue,
});
@ -130,13 +130,13 @@ class DeviceTransfer {
if (json['senderAttachments'] != null) {
senderAttachments = [];
json['senderAttachments'].forEach((v) {
senderAttachments!.add(AssetTransferAttachment.fromJson(v));
senderAttachments!.add(GenericAttachmentModel.fromAssetTransferJson(v));
});
}
if (json['assetTransferAttachments'] != null) {
assetTransferAttachments = [];
json['assetTransferAttachments'].forEach((v) {
assetTransferAttachments?.add(AssetTransferAttachment.fromJson(v));
assetTransferAttachments?.add(GenericAttachmentModel.fromAssetTransferJson(v));
});
}
if (json['assetTransferContactPersons'] != null) {
@ -198,7 +198,7 @@ class DeviceTransfer {
if (json['receiverAttachments'] != null) {
receiverAttachments = [];
json['receiverAttachments'].forEach((v) {
receiverAttachments!.add(AssetTransferAttachment.fromJson(v));
receiverAttachments!.add(GenericAttachmentModel.fromAssetTransferJson(v));
});
}
assetNumber = json['assetNumber'];
@ -270,9 +270,9 @@ class DeviceTransfer {
String? senderWorkingHours;
String? senderTravelingHours;
String? senderEngSignature;
List<AssetTransferAttachment>? senderAttachments;
List<AssetTransferAttachment>? attachments;
List<AssetTransferAttachment>? assetTransferAttachments;
List<GenericAttachmentModel>? senderAttachments;
List<GenericAttachmentModel>? attachments;
List<GenericAttachmentModel>? assetTransferAttachments;
String? receiverAssignedEmployeeId;
String? receiverAssignedEmployeeNumber;
num? receiverMachineStatusId;
@ -283,7 +283,7 @@ class DeviceTransfer {
String? receiverWorkingHours;
String? receiverTravelingHours;
String? receiverEngSignature;
List<AssetTransferAttachment>? receiverAttachments;
List<GenericAttachmentModel>? receiverAttachments;
num? supplierId;
String? supplierName;
String? destSiteName;
@ -314,11 +314,11 @@ class DeviceTransfer {
List<VisitTimers>? assetTransferEngineerTimers;
List<TimerModel>? timerModelList = [];
List<AssistantEmployees>? assistantEmployees;
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesSender=[];
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesReceiver=[];
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesSender = [];
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesReceiver = [];
List<AssetTransferContactPerson>? assetTransferContactPersons;
AssetTransferAssistantEmployees? modelAssistantEmployees;
List<AssetTransferAssistantEmployees>? assistantEmployList=[];
List<AssetTransferAssistantEmployees>? assistantEmployList = [];
TimerModel? tbsTimer = TimerModel();
TimerModel? deviceTimePicker;
@ -349,7 +349,7 @@ class DeviceTransfer {
String? senderWorkingHours,
String? senderTravelingHours,
String? senderEngSignature,
List<AssetTransferAttachment>? senderAttachments,
List<GenericAttachmentModel>? senderAttachments,
String? receiverAssignedEmployeeId,
String? receiverAssignedEmployeeNumber,
num? receiverMachineStatusId,
@ -359,7 +359,7 @@ class DeviceTransfer {
String? receiverWorkingHours,
String? receiverTravelingHours,
String? receiverEngSignature,
List<AssetTransferAttachment>? receiverAttachments,
List<GenericAttachmentModel>? receiverAttachments,
num? supplierId,
String? supplierName,
String? destSiteName,
@ -472,7 +472,7 @@ class DeviceTransfer {
senderVisitTimers: senderVisitTimers ?? this.senderVisitTimers,
receiverVisitTimers: receiverVisitTimers ?? this.receiverVisitTimers,
tbsTimer: tbsTimer ?? this.tbsTimer,
assistantEmployList: assistantEmployList??this.assistantEmployList,
assistantEmployList: assistantEmployList ?? this.assistantEmployList,
deviceTimePicker: deviceTimePicker ?? this.deviceTimePicker,
manufacturerName: manufacturerName ?? this.manufacturerName);
@ -510,7 +510,7 @@ class DeviceTransfer {
map['assetTransferReceiverTimers'] = receiverVisitTimers!.map((v) => v.toJson()).toList();
}
if (senderAttachments != null) {
map['senderAttachments'] = senderAttachments!.map((v) => v.toJson()).toList();
map['senderAttachments'] = senderAttachments!.map((v) => v.toAssetTransferJson()).toList();
}
map['receiverAssignedEmployeeId'] = receiverAssignedEmployeeId;
map['receiverAssignedEmployeeNumber'] = receiverAssignedEmployeeNumber;
@ -522,7 +522,7 @@ class DeviceTransfer {
map['receiverTravelingHours'] = receiverTravelingHours;
map['receiverEngSignature'] = receiverEngSignature;
if (receiverAttachments != null) {
map['receiverAttachments'] = receiverAttachments!.map((v) => v.toJson()).toList();
map['receiverAttachments'] = receiverAttachments?.map((v) => v.toAssetTransferJson() ?? {}).toList();
}
map["supplierId"] = supplierId;
map["supplierName"] = supplierName;
@ -571,7 +571,7 @@ class DeviceTransfer {
map['destRoomId'] = destRoomId;
map['comment'] = comment;
if (attachments != null) {
map['attachments'] = attachments!.map((v) => v.toJson()).toList();
map['attachments'] = attachments!.map((v) => v.toAssetTransferJson()).toList();
}
return map;
}
@ -586,7 +586,7 @@ class DeviceTransfer {
map['assetTransferAssistantEmployees'] = modelAssistantEmployees;
map['assetTransferEngineerTimers'] = assetTransferEngineerTimers;
if (attachments != null) {
map['attachments'] = attachments!.map((v) => v.toJson()).toList();
map['attachments'] = attachments!.map((v) => v.toAssetTransferJson()).toList();
}
if (assetTransferEngineerTimers != null) {
map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList();
@ -634,7 +634,7 @@ class DeviceTransfer {
map['senderTravelingHours'] = senderTravelingHours;
map['senderEngSignature'] = senderEngSignature;
if (senderAttachments != null) {
map['senderAttachments'] = senderAttachments!.map((v) => v.toJson()).toList();
map['senderAttachments'] = senderAttachments!.map((v) => v.toAssetTransferJson()).toList();
}
if (senderVisitTimers != null) {
map['assetTransferSenderTimers'] = senderVisitTimers!.map((v) => v.toJson()).toList();
@ -652,7 +652,7 @@ class DeviceTransfer {
map['receiverTravelingHours'] = receiverTravelingHours;
map['receiverEngSignature'] = receiverEngSignature;
if (receiverAttachments != null) {
map['receiverAttachments'] = receiverAttachments!.map((v) => v.toJson()).toList();
map['receiverAttachments'] = receiverAttachments!.map((v) => v.toAssetTransferJson() ?? {}).toList();
}
return map;
}

@ -1,33 +1,287 @@
import 'dart:io';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
class GenericAttachmentModel {
GenericAttachmentModel({this.id, this.name, this.originalName, this.createdBy, this.documentTypeId});
GenericAttachmentModel({
this.id,
this.name,
this.originalName,
this.createdBy,
this.documentType,
this.attachmentDescription,
this.attachmentURL,
this.moduleReferenceId,
this.attachmentTypeId,
this.createdDate,
this.modifiedBy,
this.modifiedDate,
this.supplierId,
});
int? id;
String? name;
String? createdBy;
String? originalName;
Lookup? documentTypeId;
Lookup? documentType;
String? attachmentDescription;
String? attachmentURL;
num? moduleReferenceId;
num? attachmentTypeId;
String? createdDate;
String? modifiedBy;
String? modifiedDate;
num? supplierId;
GenericAttachmentModel.fromJson(Map<String, dynamic> json, {bool convertToLink = false}) {
id = json['id'];
name = json['name'] ?? json['imageName'];
name = json['name'] ?? json['attachmentName'] ?? json['imageName'];
createdBy = json['createdBy'];
documentType = json['documentType'];
originalName = json['originalName'] ?? json['imageOriginalName'];
if (convertToLink) {
name = URLs.getFileUrl(name);
}
}
GenericAttachmentModel.fromWorkOrderJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
createdBy = json['createdBy'];
}
GenericAttachmentModel.fromLoanJson(Map<String, dynamic> json) {
id = json['id']?.toInt();
name = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
documentType = json['documentType'];
moduleReferenceId = json['loanId'];
attachmentTypeId = json['loanAttachmentTypeId'];
}
GenericAttachmentModel.fromLoanDetailJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
moduleReferenceId = json['loanId'];
attachmentTypeId = json['loanAttachmentTypeId'];
createdBy = json['createdBy'];
createdDate = json['createdDate'];
modifiedBy = json['modifiedBy'];
modifiedDate = json['modifiedDate'];
}
GenericAttachmentModel.fromPpmJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'] ?? json['name'];
moduleReferenceId = json['visitId'];
attachmentURL = json['attachmentURL'];
}
GenericAttachmentModel.fromSupplierJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'] ?? json['name'];
supplierId = json['supplierId'];
moduleReferenceId = json['visitId'];
attachmentURL = json['attachmentURL'];
}
GenericAttachmentModel.fromGasRefillJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
moduleReferenceId = json['gasRefillId'];
documentType = json['documentType'];
}
GenericAttachmentModel.fromIncidentJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
moduleReferenceId = json['incidentId'];
attachmentDescription = json['attachmentDescription'];
}
GenericAttachmentModel.fromAssetTransferJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
}
GenericAttachmentModel.fromDemoJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
originalName = json['originalName'];
moduleReferenceId = json['demoRequestId'];
documentType = json['documentType'] != null ? Lookup.fromJson(json['documentType']) : null;
}
GenericAttachmentModel.fromInternalAuditJson(Map<String, dynamic> json) {
id = json['id'];
name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
originalName = json['originalName'];
createdBy = json['createdBy'];
documentType = json['documentType'];
}
GenericAttachmentModel.fromPreventiveVisitJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
documentType = json['documentType'];
}
GenericAttachmentModel.fromAssetJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
attachmentURL = json['attachmentURL'];
originalName = json['originalName'];
}
GenericAttachmentModel.fromTrafJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
moduleReferenceId = json['trafId'];
documentType = json['documentType'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
data['createdBy'] = createdBy;
data['originalName'] = originalName;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toWorkOrderJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
data['createdBy'] = createdBy;
///TODO need to keep same variable for document type in backend for all modules, currently it is different for different modules
if (documentType != null) {
data['attachmentTypeId'] = documentType?.id;
}
return data;
}
Map<String, dynamic> toLoanJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['loanId'] = moduleReferenceId;
data['loanAttachmentTypeId'] = attachmentTypeId;
data['documentTypeId'] = documentType?.id;
data['attachmentDescription'] = attachmentDescription;
return data;
}
Map<String, dynamic> toLoanDetailJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['loanId'] = moduleReferenceId;
data['loanAttachmentTypeId'] = attachmentTypeId;
data['attachmentDescription'] = attachmentDescription;
data['createdBy'] = createdBy;
data['createdDate'] = createdDate;
data['documentTypeId'] = documentType?.id;
data['modifiedBy'] = modifiedBy;
data['modifiedDate'] = modifiedDate;
return data;
}
//TODO need to check where to use this need to verify with backend team.
Map<String, dynamic> toPpmJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['visitId'] = moduleReferenceId;
data['attachmentName'] = name;
data['documentTypeId'] = documentType?.id;
data['attachmentURL'] = attachmentURL;
return data;
}
Map<String, dynamic> toGasRefillJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['gasRefillId'] = moduleReferenceId;
data['attachmentName'] = name;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toIncidentJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['incidentId'] = moduleReferenceId;
data['documentTypeId'] = documentType?.id;
data['attachmentDescription'] = attachmentDescription;
return data;
}
Map<String, dynamic> toAssetTransferJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toDemoJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['demoRequestId'] = moduleReferenceId;
data['originalName'] = originalName;
if (documentType != null) {
data['documentTypeId'] = documentType?.id;
}
return data;
}
Map<String, dynamic> toInternalAuditJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
data['originalName'] = originalName;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toPreventiveVisitJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toAssetJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = name;
data['attachmentURL'] = attachmentURL;
data['documentTypeId'] = documentType?.id;
data['originalName'] = originalName;
return data;
}
Map<String, dynamic> toTrafJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['trafId'] = moduleReferenceId;
data['attachmentName'] = name;
data['documentTypeId'] = documentType?.id;
return data;
}
Map<String, dynamic> toSupplierJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['supplierId'] = supplierId;
data['documentTypeId'] = documentType?.id;
data['attachmentName'] = name;
data['attachmentURL'] = attachmentURL;
return data;
}
}

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
class AssetRetiredHelperModel {
@ -5,7 +6,7 @@ class AssetRetiredHelperModel {
int? workOrderId;
Lookup? retirmentReason;
String? retirementComment;
List<ActivityAssetToBeRetiredAttachments>?
List<GenericAttachmentModel>?
activityAssetToBeRetiredAttachments=[];
AssetRetiredHelperModel(
@ -30,14 +31,3 @@ class AssetRetiredHelperModel {
}
}
class ActivityAssetToBeRetiredAttachments {
int? id;
String? name;
ActivityAssetToBeRetiredAttachments({this.id, this.name});
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
@ -12,7 +13,7 @@ class SparePartHelperModel {
num? installQty;
num? returnQty;
String? comment;
List<SparePartAttachments>? sparePartAttachments;
List<GenericAttachmentModel>? sparePartAttachments;
SparePartHelperModel({
this.id,
@ -42,27 +43,10 @@ class SparePartHelperModel {
data['comment'] = comment;
if (sparePartAttachments != null) {
data['acitiySparePartAttachments'] =
sparePartAttachments!.map((v) => v.toJson()).toList();
sparePartAttachments!.map((v) => v?.toJson() ?? {}).toList();
}
return data;
}
}
class SparePartAttachments {
int? id;
String? name;
SparePartAttachments({this.id, this.name});
SparePartAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
return data;
}
}

@ -1,4 +1,5 @@
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import '../../new_models/work_order_detail_model.dart';
@ -24,7 +25,7 @@ class WorkOrderHelperModel {
int? problemDescriptionId;
String? comments;
String? voiceNote;
List<WorkOrderAttachments>? workOrderAttachments;
List<GenericAttachmentModel>? workOrderAttachments;
WorkOrderHelperModel({this.assetId, this.equipmentStatusId, this.priorityId, this.problemDescriptionId, this.comments, this.voiceNote, this.workOrderAttachments});
@ -37,42 +38,21 @@ class WorkOrderHelperModel {
data['comments'] = comments;
data['voiceNote'] = voiceNote;
if (workOrderAttachments != null) {
data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList();
data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toWorkOrderJson()).toList();
}
return data;
}
Map<String, dynamic> toUploadAttachmentJson(int? workOrderId, List<WorkOrderAttachments>? workOrderAttachments) {
Map<String, dynamic> toUploadAttachmentJson(int? workOrderId, List<GenericAttachmentModel>? workOrderAttachments) {
final Map<String, dynamic> data = <String, dynamic>{};
data['workOrderId'] = workOrderId;
if (workOrderAttachments != null) {
data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList();
data['workOrderAttachments'] = workOrderAttachments.map((v) => v.toWorkOrderJson()).toList();
}
return data;
}
}
class WorkOrderAttachments {
WorkOrderAttachments({this.id, this.name,this.createdBy});
int? id;
String? name;
String ?createdBy;
WorkOrderAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
createdBy = json['createdBy'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
data['createdBy'] = createdBy;
return data;
}
}
class EngineerUpdateWorkOrderHelperModel {
int? workOrderId;
Lookup? equipmentStatus;
@ -173,9 +153,19 @@ class WorkOrderCostModel {
String? mrNo;
num? exchangeCost;
WorkOrderCostModel({this.workOrderId, this.sparePartCost, this.labourCost, this.travelCost, this.qAmount, this.poNo, this.prNo,this.mrNo,this.exchangeCost});
WorkOrderCostModel({this.workOrderId, this.sparePartCost, this.labourCost, this.travelCost, this.qAmount, this.poNo, this.prNo, this.mrNo, this.exchangeCost});
Map<String, dynamic> toJson() {
return {'workOrderId': workOrderId, 'sparePartCost': sparePartCost, 'laborCost': labourCost, 'travelCost': travelCost, 'qAmount': qAmount, 'prNo': prNo, 'poNo': poNo,'mrNo':mrNo,'exchangeCost':exchangeCost};
return {
'workOrderId': workOrderId,
'sparePartCost': sparePartCost,
'laborCost': labourCost,
'travelCost': travelCost,
'qAmount': qAmount,
'prNo': prNo,
'poNo': poNo,
'mrNo': mrNo,
'exchangeCost': exchangeCost
};
}
}

@ -3,6 +3,7 @@ import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.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/models/new_models/assigned_employee.dart';
import 'package:test_sa/models/new_models/building.dart';
@ -87,7 +88,7 @@ class GasRefillModel {
TimerModel? gasRefillTimePicker;
List<TimerModel>? timerModelList = [];
List<GasRefillTimer>? gasRefillTimers = [];
List<GasRefillAttachments>? gasRefillAttachments;
List<GenericAttachmentModel>? gasRefillAttachments;
List<GasRefillContactPerson>? gasRefillContactPerson;
int? statusValue;
@ -115,9 +116,9 @@ class GasRefillModel {
workingHours = json['gasRefillTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDate']).difference(DateTime.parse(item['startDate'])).inSeconds) ?? 0;
}
if (json['gasRefillAttachments'] != null) {
gasRefillAttachments = <GasRefillAttachments>[];
gasRefillAttachments = <GenericAttachmentModel>[];
json['gasRefillAttachments'].forEach((v) {
gasRefillAttachments!.add(GasRefillAttachments.fromJson(v));
gasRefillAttachments!.add(GenericAttachmentModel.fromGasRefillJson(v));
});
}
if (json['gasRefillContactPerson'] != null) {
@ -127,24 +128,6 @@ class GasRefillModel {
});
}
// try {
// final DateTime? sd = DateTime.tryParse(startDate ?? "");
// final DateTime? st = DateTime.tryParse(startTime ?? "");
// final DateTime? ed = DateTime.tryParse(endDate ?? "");
// final DateTime? et = DateTime.tryParse(endTime ?? "");
// timer = TimerModel(
// startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd'
// endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed'
// );
// if (timer!.endAt != null && timer!.startAt != null) {
// // Use '!' since timer could be null after initialization
// timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds;
// workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60);
// }
// } catch (e) {
// print(e);
// }
engSignature = json['engSignature'];
nurseSignature = json['nurseSignature'];
site = json['site'] != null ? Site.fromJson(json['site']) : null;
@ -188,7 +171,7 @@ class GasRefillModel {
map['comment'] = comment;
if (gasRefillAttachments != null) {
map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toGasRefillJson() ?? {}).toList();
}
//older code.....
@ -241,8 +224,8 @@ class GasRefillModel {
if (gasRefillTimers != null) {
map['gasRefillTimers'] = gasRefillTimers?.map((v) => v.toJson()).toList();
}
if (gasRefillAttachments != null) {
map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
if (gasRefillContactPerson != null) {
map['gasRefillContactPerson'] = gasRefillContactPerson?.map((v) => v?.toJson() ?? {}).toList();
}
return map;
@ -454,27 +437,30 @@ class GasRefillTimer {
}
}
class GasRefillAttachments {
int? id;
num? gasRefillId;
String? attachmentName;
GasRefillAttachments({this.id, this.attachmentName, this.gasRefillId});
GasRefillAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
gasRefillId = json['gasRefillId'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['gasRefillId'] = gasRefillId;
data['attachmentName'] = attachmentName;
return data;
}
}
// class GasRefillAttachments {
// int? id;
// num? gasRefillId;
// String? attachmentName;
// Lookup ? documentType;
//
// GasRefillAttachments({this.id, this.attachmentName,this.documentType, this.gasRefillId});
//
// GasRefillAttachments.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// gasRefillId = json['gasRefillId'];
// attachmentName = json['attachmentName'];
// documentType = json['documentType'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = <String, dynamic>{};
// data['id'] = id;
// data['gasRefillId'] = gasRefillId;
// data['attachmentName'] = attachmentName;
// data['documentTypeId'] = documentType?.id;
// return data;
// }
// }
class GasRefillContactPerson {
int? id;

@ -1,6 +1,7 @@
import 'dart:typed_data';
import 'package:test_sa/models/base.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/assistant_employee.dart';
import 'package:test_sa/models/new_models/building.dart';
@ -63,7 +64,7 @@ class TaskData {
Department? department;
Rooms? room;
String? callComment;
List<TaskJobAttachment>? taskJobAttachments;
List<GenericAttachmentModel>? taskJobAttachments;
TaskContactUser? assignedEngineer;
List<TaskJobAssistantEmployees>? taskJobAssistantEmployees = [];
TaskJobAssistantEmployees? modelAssistantEmployees;
@ -146,18 +147,18 @@ class TaskData {
});
}
if (json['attachments'] != null) {
taskJobAttachments = <TaskJobAttachment>[];
taskJobAttachments = <GenericAttachmentModel>[];
json['attachments'].forEach((v) {
taskJobAttachments!.add(TaskJobAttachment.fromJson(v));
taskJobAttachments!.add(GenericAttachmentModel.fromJson(v));
});
}
taskType = json['taskType'] != null ? TaskTypeModel.fromJson(json['taskType']) : null;
taskJobStatus = json['taskJobStatus'] != null ? TaskJobStatus.fromJson(json['taskJobStatus']) : null;
callComment = json['callComment'];
if (json['taskJobAttachments'] != null) {
taskJobAttachments = <TaskJobAttachment>[];
taskJobAttachments = <GenericAttachmentModel>[];
json['taskJobAttachments'].forEach((v) {
taskJobAttachments!.add(TaskJobAttachment.fromJson(v));
taskJobAttachments!.add(GenericAttachmentModel.fromJson(v));
});
}
assignedEngineer = json['assignedEngineer'] != null ? TaskContactUser.fromJson(json['assignedEngineer']) : null;
@ -283,7 +284,7 @@ class TaskData {
data['callComment'] = callComment;
if (taskJobAttachments != null) {
data['taskJobAttachments'] = taskJobAttachments!.map((e) => e.toJson()).toList();
data['taskJobAttachments'] = taskJobAttachments!.map((e) => e?.toJson() ?? {}).toList();
}
if (assignedEngineer != null) {
@ -368,7 +369,7 @@ class TaskData {
data['taskJobActivityEngineerTimers'] = taskJobActivityEngineerTimers!.map((v) => v.toJson()).toList();
}
if (taskJobAttachments != null) {
data['attachments'] = taskJobAttachments!.map((v) => v.toJson()).toList();
data['attachments'] = taskJobAttachments!.map((v) => v?.toJson() ?? {}).toList();
}
data['installationBuildingId'] = building?.id;
data['installationFloorId'] = floor?.id;
@ -567,26 +568,6 @@ class TaskJobStatus {
};
}
class TaskJobAttachment {
final int? id;
final String? name;
String? createdBy;
TaskJobAttachment({this.id, this.name, this.createdBy});
factory TaskJobAttachment.fromJson(Map<String, dynamic> json) => TaskJobAttachment(
id: json['id'],
name: json['name'],
createdBy: json['createdBy'],
);
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'createdBy': createdBy,
};
}
class TaskJobAssistantEmployees {
DateTime? startDate;
int? id;
@ -755,7 +736,7 @@ class AddTaskModel {
TaskEvaluatorUser? taskEvaluatorUser;
String? alertNo;
String? estimationDeliveryDate;
List<TaskJobAttachment>? attachments;
List<GenericAttachmentModel>? attachments;
String? reasonOfFSCA;
String? correctiveActionDescription;
@ -800,7 +781,7 @@ class AddTaskModel {
'reasonOfFSCA': reasonOfFSCA,
'correctiveActionDescription': correctiveActionDescription,
'evaluatorUserId': taskEvaluatorUser?.userId,
'attachments': attachments?.map((x) => x.toJson()).toList(),
'attachments': attachments?.map((x) => x.toJson() ?? {}).toList(),
};
}

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/lookup.dart';
@ -146,7 +147,7 @@ class WorkOrderData {
Lookup? problemDescription;
String? comments;
String? voiceNote;
List<WorkOrderAttachments> workOrderAttachments;
List<GenericAttachmentModel> workOrderAttachments;
String? returnToService;
Lookup? serviceType;
Lookup? failureReasone;
@ -232,7 +233,7 @@ class WorkOrderData {
comments: json["comments"],
voiceNote: json["voiceNote"],
edd: json["edd"],
workOrderAttachments: json["workOrderAttachments"] == null ? [] : List.from(json['workOrderAttachments']).map((e) => WorkOrderAttachments.fromJson(e)).toList(),
workOrderAttachments: json["workOrderAttachments"] == null ? [] : List.from(json['workOrderAttachments']).map((e) => GenericAttachmentModel.fromWorkOrderJson(e)).toList(),
returnToService: json["returnToService"],
serviceType: json["serviceType"] == null ? null : Lookup.fromJson(json["serviceType"]),
failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]),
@ -286,7 +287,7 @@ class WorkOrderData {
"edd": edd,
'mrNo': mrNo,
'exchangeCost': exchangeCost,
"workOrderAttachments": workOrderAttachments.map((e) => e.toJson()).toList(),
"workOrderAttachments": workOrderAttachments.map((e) => e.toWorkOrderJson() ?? {}).toList(),
"returnToService": returnToService,
"serviceType": serviceType?.toJson(),
"failureReasone": failureReasone?.toJson(),
@ -503,7 +504,7 @@ class ActivitySparePart {
double? installQty;
double? returnQty;
String? comment;
List<SparePartAttachments>? acitiySparePartAttachments;
List<GenericAttachmentModel>? acitiySparePartAttachments;
ActivitySparePart({this.id, this.partCatalogItem, this.quantity, this.installQty, this.returnQty, this.comment, this.acitiySparePartAttachments});
@ -515,9 +516,9 @@ class ActivitySparePart {
returnQty = json['returnQty'];
comment = json['comment'];
if (json['acitiySparePartAttachments'] != null) {
acitiySparePartAttachments = <SparePartAttachments>[];
acitiySparePartAttachments = <GenericAttachmentModel>[];
json['acitiySparePartAttachments'].forEach((v) {
acitiySparePartAttachments!.add(SparePartAttachments.fromJson(v));
acitiySparePartAttachments!.add(GenericAttachmentModel.fromJson(v));
});
}
}
@ -533,7 +534,7 @@ class ActivitySparePart {
data['returnQty'] = returnQty;
data['comment'] = comment;
if (acitiySparePartAttachments != null) {
data['acitiySparePartAttachments'] = acitiySparePartAttachments!.map((v) => v.toJson()).toList();
data['acitiySparePartAttachments'] = acitiySparePartAttachments!.map((v) => v?.toJson() ?? {}).toList();
}
return data;
}

@ -4,6 +4,7 @@ import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/models/timer_model.dart';
@ -42,7 +43,7 @@ class PlanPreventiveVisit {
Lookup? safety;
String? engSignature;
String? nurseSignature;
List<PreventiveVisitAttachments>? preventiveVisitAttachments;
List<GenericAttachmentModel>? preventiveVisitAttachments;
List<File>? attachments = [];
List<PreventiveVisitCalibrations>? preventiveVisitCalibrations;
List<PreventiveVisitChecklists>? preventiveVisitChecklists;
@ -132,9 +133,9 @@ class PlanPreventiveVisit {
engSignature = json['engSignature'];
nurseSignature = json['nurseSignature'];
if (json['preventiveVisitAttachments'] != null) {
preventiveVisitAttachments = <PreventiveVisitAttachments>[];
preventiveVisitAttachments = <GenericAttachmentModel>[];
json['preventiveVisitAttachments'].forEach((v) {
preventiveVisitAttachments!.add(PreventiveVisitAttachments.fromJson(v));
preventiveVisitAttachments!.add(GenericAttachmentModel.fromPreventiveVisitJson(v));
});
}
if (json['preventiveVisitCalibrations'] != null) {
@ -183,53 +184,9 @@ class PlanPreventiveVisit {
data['safetyId'] = safety?.id;
data['engSignature'] = engSignature;
data['nurseSignature'] = nurseSignature;
//
// if (asset != null) {
// data['asset'] = asset!.toJson();
// }
// data['visitNo'] = visitNo;
// data['planNo'] = planNo;
// data['planName'] = planName;
// data['nextPMDate'] = nextPMDate;
// data['assetName'] = assetName;
// data['model'] = model;
// data['manufacturer'] = manufacturer;
// data['supplierName'] = supplierName;
// data['siteName'] = siteName;
// data['buildingName'] = buildingName;
// data['floorName'] = floorName;
// data['departmentName'] = departmentName;
// data['roomName'] = roomName;
// data['fromDate'] = fromDate;
// data['toDate'] = toDate;
// if (assignedEmployee != null) {
// data['assignedEmployee'] = assignedEmployee!.toJson();
// }
// data['acutalDateOfVisit'] = acutalDateOfVisit;
// if (typeOfService != null) {
// data['typeOfService'] = typeOfService!.toJson();
// }
// if (visitStatus != null) {
// data['visitStatus'] = visitStatus!.toJson();
// }
// data['travelingHours'] = travelingHours;
// data['comments'] = comments;
// data['executionTimeFrame'] = executionTimeFrame;
// if (taskStatus != null) {
// data['taskStatus'] = taskStatus!.toJson();
// }
// if (deviceStatus != null) {
// data['deviceStatus'] = deviceStatus!.toJson();
// }
// data['assetAvailability'] = assetAvailability;
// if (safety != null) {
// data['safety'] = safety!.toJson();
// }
// data['engSignature'] = engSignature;
// data['nurseSignature'] = nurseSignature;
if (preventiveVisitAttachments != null) {
data['preventiveVisitAttachments'] = preventiveVisitAttachments!.map((v) => v.toJson()).toList();
data['preventiveVisitAttachments'] = preventiveVisitAttachments!.map((v) => v.toPreventiveVisitJson()).toList();
}
if (preventiveVisitCalibrations != null) {
data['preventiveVisitCalibrations'] = preventiveVisitCalibrations!.map((v) => v.toJson()).toList();
@ -249,10 +206,6 @@ class PlanPreventiveVisit {
return data;
}
bool _isLocalUrl(String url) {
if (url.isEmpty != false) return false;
return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
}
Future<bool> validate(BuildContext context) async {
if (visitStatus?.id == null) {
@ -263,10 +216,6 @@ class PlanPreventiveVisit {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.actualDate}");
return false;
}
// if (expectedDate == null) {
// await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.visitDate}");
// return false;
// }
if (tbsTimer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required");
return false;
@ -276,11 +225,6 @@ class PlanPreventiveVisit {
return false;
}
// if (externalEngineerTimer?.startAt != null && externalEngineerTimer?.endAt == null) {
// await Fluttertoast.showToast(msg: "Please Stop External Engineer Timer");
// return false;
// }
return true;
}
@ -290,275 +234,6 @@ class PlanPreventiveVisit {
}
}
// class PlanPreventiveVisit {
// String? id;
// String? visitNo;
// Asset? asset;
// String? planNo;
// String? planName;
// String? nextPMDate;
// String? assetName;
// String? model;
// String? manufacturer;
// String? supplierName;
// String? siteName;
// String? buildingName;
// String? floorName;
// String? departmentName;
// String? roomName;
// String? fromDate;
// String? toDate;
// AssignedEmployee? assignedEmployee;
// String? acutalDateOfVisit;
// TypeOfService? typeOfService;
// VisitStatus? visitStatus;
// String? travelingHours;
// String? comments;
// int? executionTimeFrame;
// Lookup? taskStatus;
// String? deviceStatus;
// Lookup? assetAvailability;
// Lookup? safety;
// String? engSignature;
// String? nurseSignature;
// List<PreventiveVisitChecklists>? preventiveVisitAttachments;
// List<PreventiveVisitChecklists>? preventiveVisitCalibrations;
// List<PreventiveVisitChecklists>? preventiveVisitChecklists;
// List<PreventiveVisitChecklists>? preventiveVisitKits;
// List<PreventiveVisitTimers>? preventiveVisitTimers;
// List<PreventiveVisitChecklists>? preventiveVisitSuppliers;
// TimerModel? tbsTimer = TimerModel();
//
// PlanPreventiveVisit(
// {this.id,
// this.visitNo,
// this.asset,
// this.planNo,
// this.planName,
// this.nextPMDate,
// this.assetName,
// this.model,
// this.manufacturer,
// this.supplierName,
// this.siteName,
// this.buildingName,
// this.floorName,
// this.departmentName,
// this.roomName,
// this.fromDate,
// this.toDate,
// this.assignedEmployee,
// this.acutalDateOfVisit,
// this.typeOfService,
// this.visitStatus,
// this.travelingHours,
// this.comments,
// this.executionTimeFrame,
// this.taskStatus,
// this.deviceStatus,
// this.assetAvailability,
// this.safety,
// this.engSignature,
// this.nurseSignature,
// this.preventiveVisitAttachments,
// this.preventiveVisitCalibrations,
// this.preventiveVisitChecklists,
// this.preventiveVisitKits,
// this.preventiveVisitTimers,
// this.preventiveVisitSuppliers});
//
// PlanPreventiveVisit.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// visitNo = json['visitNo'];
// asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null;
// planNo = json['planNo'];
// planName = json['planName'];
// nextPMDate = json['nextPMDate'];
// assetName = json['assetName'];
// model = json['model'];
// manufacturer = json['manufacturer'];
// supplierName = json['supplierName'];
// siteName = json['siteName'];
// buildingName = json['buildingName'];
// floorName = json['floorName'];
// departmentName = json['departmentName'];
// roomName = json['roomName'];
// fromDate = json['fromDate'];
// toDate = json['toDate'];
// assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
// acutalDateOfVisit = json['acutalDateOfVisit'];
// typeOfService = json['typeOfService'] != null ? TypeOfService.fromJson(json['typeOfService']) : null;
// visitStatus = json['visitStatus'] != null ? VisitStatus.fromJson(json['visitStatus']) : null;
// travelingHours = json['travelingHours'];
// comments = json['comments'];
// executionTimeFrame = json['executionTimeFrame'];
// taskStatus = json['taskStatus'];
// deviceStatus = json['deviceStatus'];
// assetAvailability = json['assetAvailability'];
// safety = json['safety'];
// engSignature = json['engSignature'];
// nurseSignature = json['nurseSignature'];
// if (json['preventiveVisitAttachments'] != null) {
// preventiveVisitAttachments = <PreventiveVisitChecklists>[];
// json['preventiveVisitAttachments'].forEach((v) {
// preventiveVisitAttachments!.add(PreventiveVisitChecklists.fromJson(v));
// });
// }
// if (json['preventiveVisitCalibrations'] != null) {
// preventiveVisitCalibrations = <PreventiveVisitChecklists>[];
// json['preventiveVisitCalibrations'].forEach((v) {
// preventiveVisitCalibrations!.add( PreventiveVisitChecklists.fromJson(v));
// });
// }
// if (json['preventiveVisitChecklists'] != null) {
// preventiveVisitChecklists = <PreventiveVisitChecklists>[];
// json['preventiveVisitChecklists'].forEach((v) {
// preventiveVisitChecklists!.add( PreventiveVisitChecklists.fromJson(v));
// });
// }
// if (json['preventiveVisitKits'] != null) {
// preventiveVisitKits = <PreventiveVisitChecklists>[];
// json['preventiveVisitKits'].forEach((v) {
// preventiveVisitKits!.add( PreventiveVisitChecklists.fromJson(v));
// });
// }
// if (json['preventiveVisitTimers'] != null) {
// preventiveVisitTimers = <PreventiveVisitTimers>[];
// json['preventiveVisitTimers'].forEach((v) {
// preventiveVisitTimers!.add( PreventiveVisitTimers.fromJson(v));
// });
// }
// if (json['preventiveVisitSuppliers'] != null) {
// preventiveVisitSuppliers = <PreventiveVisitChecklists>[];
// json['preventiveVisitSuppliers'].forEach((v) {
// preventiveVisitSuppliers!.add( PreventiveVisitChecklists.fromJson(v));
// });
// }
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['visitNo'] = this.visitNo;
// if (this.asset != null) {
// data['asset'] = this.asset!.toJson();
// }
// data['planNo'] = this.planNo;
// data['planName'] = this.planName;
// data['nextPMDate'] = this.nextPMDate;
// data['assetName'] = this.assetName;
// data['model'] = this.model;
// data['manufacturer'] = this.manufacturer;
// data['supplierName'] = this.supplierName;
// data['siteName'] = this.siteName;
// data['buildingName'] = this.buildingName;
// data['floorName'] = this.floorName;
// data['departmentName'] = this.departmentName;
// data['roomName'] = this.roomName;
// data['fromDate'] = this.fromDate;
// data['toDate'] = this.toDate;
// if (this.assignedEmployee != null) {
// data['assignedEmployee'] = this.assignedEmployee!.toJson();
// }
// data['acutalDateOfVisit'] = this.acutalDateOfVisit;
// if (this.typeOfService != null) {
// data['typeOfService'] = this.typeOfService!.toJson();
// }
// if (this.visitStatus != null) {
// data['visitStatus'] = this.visitStatus!.toJson();
// }
// data['travelingHours'] = this.travelingHours;
// data['comments'] = this.comments;
// data['executionTimeFrame'] = this.executionTimeFrame;
// data['taskStatus'] = this.taskStatus;
// data['deviceStatus'] = this.deviceStatus;
// data['assetAvailability'] = this.assetAvailability;
// data['safety'] = this.safety;
// data['engSignature'] = this.engSignature;
// data['nurseSignature'] = this.nurseSignature;
// if (this.preventiveVisitAttachments != null) {
// data['preventiveVisitAttachments'] = this.preventiveVisitAttachments!.map((v) => v.toJson()).toList();
// }
// if (this.preventiveVisitCalibrations != null) {
// data['preventiveVisitCalibrations'] = this.preventiveVisitCalibrations!.map((v) => v.toJson()).toList();
// }
// if (this.preventiveVisitChecklists != null) {
// data['preventiveVisitChecklists'] = this.preventiveVisitChecklists!.map((v) => v.toJson()).toList();
// }
// if (this.preventiveVisitKits != null) {
// data['preventiveVisitKits'] = this.preventiveVisitKits!.map((v) => v.toJson()).toList();
// }
// if (this.preventiveVisitTimers != null) {
// data['preventiveVisitTimers'] = this.preventiveVisitTimers!.map((v) => v.toJson()).toList();
// }
// if (this.preventiveVisitSuppliers != null) {
// data['preventiveVisitSuppliers'] = this.preventiveVisitSuppliers!.map((v) => v.toJson()).toList();
// }
// return data;
// }
//
// bool _isLocalUrl(String url) {
// if (url.isEmpty != false) return false;
// return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
// }
//
// Future<bool> validate(BuildContext context) async {
// if (visitStatus?.id == null) {
// await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.status}");
// return false;
// }
// if (acutalDateOfVisit == null) {
// await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.actualDate}");
// return false;
// }
// // if (expectedDate == null) {
// // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.visitDate}");
// // return false;
// // }
// if (tbsTimer?.startAt == null) {
// await Fluttertoast.showToast(msg: "Working Hours Required");
// return false;
// }
// if (tbsTimer?.endAt == null) {
// await Fluttertoast.showToast(msg: "Please Stop The Timer");
// return false;
// }
//
// // if (externalEngineerTimer?.startAt != null && externalEngineerTimer?.endAt == null) {
// // await Fluttertoast.showToast(msg: "Please Stop External Engineer Timer");
// // return false;
// // }
//
// return true;
// }
//
// void removeEmptyObjects() {
// // if (vCalibrationTools?.isNotEmpty ?? false) vCalibrationTools!.removeWhere((element) => element.assetId == null && element.calibrationDateOfTesters == null);
// // if (vKits?.isNotEmpty ?? false) vKits!.removeWhere((element) => element.partName == null && element.partNumber == null);
// }
// }
// class Asset {
// num? id;
// String? assetNumber;
// String? assetSerialNo;
//
// Asset({this.id, this.assetNumber, this.assetSerialNo});
//
// Asset.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// assetNumber = json['assetNumber'];
// assetSerialNo = json['assetSerialNo'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['assetNumber'] = this.assetNumber;
// data['assetSerialNo'] = this.assetSerialNo;
// return data;
// }
// }
class AssignedEmployee {
String? userId;
@ -588,49 +263,6 @@ class AssignedEmployee {
}
}
// class Lookup {
// int? id;
// String? name;
// int? value;
//
// Lookup({this.id, this.name, this.value});
//
// Lookup.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// name = json['name'];
// value = json['value'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['name'] = this.name;
// data['value'] = this.value;
// return data;
// }
// }
// class VisitStatus {
// int? id;
// String? name;
// int? value;
//
// VisitStatus({this.id, this.name, this.value});
//
// VisitStatus.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// name = json['name'];
// value = json['value'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['name'] = this.name;
// data['value'] = this.value;
// return data;
// }
// }
class PreventiveVisitChecklists {
int? id;
@ -655,9 +287,6 @@ class PreventiveVisitChecklists {
data['taskStatusId'] = taskStatus?.id;
data['taskComment'] = taskComment;
data['measuredValue'] = measuredValue;
// if (instructionText != null) {
// data['instructionText'] = instructionText!.toJson();
// }
return data;
}
}
@ -706,25 +335,6 @@ class PreventiveVisitTimers {
}
}
class PreventiveVisitAttachments {
int? id;
String? attachmentName;
PreventiveVisitAttachments({this.id, this.attachmentName});
PreventiveVisitAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = attachmentName;
return data;
}
}
class PreventiveVisitCalibrations {
num? id;
Asset? asset;
@ -742,7 +352,6 @@ class PreventiveVisitCalibrations {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
if (asset != null) {
// data['asset'] = asset!.toJson();
data['assetId'] = asset?.id;
}
data['calibrationDateOfTesters'] = calibrationDateOfTesters;
@ -774,11 +383,9 @@ class PreventiveVisitSuppliers {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
if (supplier != null) {
// data['supplier'] = supplier!.toJson();
data['supplierId'] = supplier?.id;
}
if (suppPerson != null) {
// data['suppPerson'] = suppPerson!.toJson();
data['suppPersonId'] = suppPerson?.id;
}
data['startDateTime'] = startDateTime?.toIso8601String();
@ -788,170 +395,6 @@ class PreventiveVisitSuppliers {
}
}
// class Supplier {
// int? id;
// String? suppliername;
// String? name;
// String? website;
// String? email;
// String? code;
// int? suppNo;
// String? suppStatusId;
// String? cityId;
// String? person;
// String? comment;
// String? zipcode;
// String? contact;
// List<String>? telephones;
// List<String>? faxes;
// List<String>? addresses;
// List<String>? attachments;
// List<SuppPersons>? suppPersons;
// List<String>? suppTCodes;
//
// Supplier(
// {this.id,
// this.suppliername,
// this.name,
// this.website,
// this.email,
// this.code,
// this.suppNo,
// this.suppStatusId,
// this.cityId,
// this.person,
// this.comment,
// this.zipcode,
// this.contact,
// this.telephones,
// this.faxes,
// this.addresses,
// this.attachments,
// this.suppPersons,
// this.suppTCodes});
//
// Supplier.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// suppliername = json['suppliername'];
// name = json['name'];
// website = json['website'];
// email = json['email'];
// code = json['code'];
// suppNo = json['suppNo'];
// suppStatusId = json['suppStatusId'];
// cityId = json['cityId'];
// person = json['person'];
// comment = json['comment'];
// zipcode = json['zipcode'];
// contact = json['contact'];
// if (json['telephones'] != null) {
// telephones = <String>[];
// json['telephones'].forEach((v) {
// telephones!.add(v);
// });
// }
// if (json['faxes'] != null) {
// faxes = <String>[];
// json['faxes'].forEach((v) {
// faxes!.add(v);
// });
// }
// if (json['addresses'] != null) {
// addresses = <String>[];
// json['addresses'].forEach((v) {
// addresses!.add(v);
// });
// }
// if (json['attachments'] != null) {
// attachments = <String>[];
// json['attachments'].forEach((v) {
// attachments!.add(v);
// });
// }
// if (json['suppPersons'] != null) {
// suppPersons = <SuppPersons>[];
// json['suppPersons'].forEach((v) {
// suppPersons!.add(SuppPersons.fromJson(v));
// });
// }
// if (json['suppTCodes'] != null) {
// suppTCodes = <String>[];
// json['suppTCodes'].forEach((v) {
// suppTCodes!.add(v);
// });
// }
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = <String, dynamic>{};
// data['id'] = id;
// data['suppliername'] = suppliername;
// data['name'] = name;
// data['website'] = website;
// data['email'] = email;
// data['code'] = code;
// data['suppNo'] = suppNo;
// data['suppStatusId'] = suppStatusId;
// data['cityId'] = cityId;
// data['person'] = person;
// data['comment'] = comment;
// data['zipcode'] = zipcode;
// data['contact'] = contact;
// if (telephones != null) {
// data['telephones'] = telephones!.map((v) => v).toList();
// }
// if (faxes != null) {
// data['faxes'] = faxes!.map((v) => v).toList();
// }
// if (addresses != null) {
// data['addresses'] = addresses!.map((v) => v).toList();
// }
// if (attachments != null) {
// data['attachments'] = attachments!.map((v) => v).toList();
// }
// if (suppPersons != null) {
// data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList();
// }
// if (suppTCodes != null) {
// data['suppTCodes'] = suppTCodes!.map((v) => v).toList();
// }
// return data;
// }
// }
// class SuppPersons {
// int? id;
// int? supplierId;
// String? personName;
// int? personRoleId;
// String? contact;
// String? externalEngCode;
// String? email;
//
// SuppPersons({this.id, this.supplierId, this.personName, this.personRoleId, this.contact, this.externalEngCode, this.email});
//
// SuppPersons.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// supplierId = json['supplierId'];
// personName = json['personName'];
// personRoleId = json['personRoleId'];
// contact = json['contact'];
// externalEngCode = json['externalEngCode'];
// email = json['email'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = Map<String, dynamic>();
// data['id'] = this.id;
// data['supplierId'] = this.supplierId;
// data['personName'] = this.personName;
// data['personRoleId'] = this.personRoleId;
// data['contact'] = this.contact;
// data['externalEngCode'] = this.externalEngCode;
// data['email'] = this.email;
// return data;
// }
// }
class PreventiveVisitKits {
int? id;

@ -5,6 +5,7 @@ import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/ppm/ppm_attachment.dart';
import 'package:test_sa/models/ppm/ppm_calibration_tools.dart';
import 'package:test_sa/models/ppm/ppm_check_list.dart';
@ -173,7 +174,7 @@ class Ppm {
if (json['vAttachments'] != null) {
files = [];
json['vAttachments'].forEach((v) {
files!.add(PpmAttachments.fromJson(v));
files!.add(GenericAttachmentModel.fromPpmJson(v));
});
}
visitStatusId = json['visitStatusId'];
@ -286,7 +287,7 @@ class Ppm {
List<PpmKits>? vKits;
List<PpmContacts>? vContacts;
List<PpmChecklists>? vChecklists;
List<PpmAttachments>? files;
List<GenericAttachmentModel>? files;
num? visitStatusId;
List<VisitTimers>? visitTimers;
@ -380,7 +381,7 @@ class Ppm {
List<PpmKits>? vKits,
List<PpmContacts>? vContacts,
List<PpmChecklists>? vChecklists,
List<PpmAttachments>? files,
List<GenericAttachmentModel>? files,
num? visitStatusId,
List<VisitTimers>? visitTimers,
String? startDate,
@ -574,7 +575,7 @@ class Ppm {
if (files?.isNotEmpty ?? false) {
map["vAttachments"] = files!
.map((file) =>
{"attachmentName": _isLocalUrl(file.attachmentName!) ? ("${file.attachmentName!.split("/").last}|${base64Encode(File(file.attachmentName!).readAsBytesSync())}") : file.attachmentName})
{"attachmentName": _isLocalUrl(file.name!) ? ("${file.name!.split("/").last}|${base64Encode(File(file.name!).readAsBytesSync())}") : file.name})
.toList();
}
map['visitStatusId'] = visitStatusId;

@ -1,40 +1,42 @@
class PpmAttachments {
PpmAttachments({
this.id,
this.visitId,
this.attachmentName,
this.attachmentURL,
});
//TODO need to delete this
PpmAttachments.fromJson(dynamic json) {
id = json['id'];
visitId = json['visitId'];
attachmentName = json['attachmentName'] ?? json['attachmentURL']; // Handle potential null and prioritize'attachmentName'
}
num? id; // Now nullable
num? visitId; // Now nullable
String? attachmentName; // Now nullable
String? attachmentURL; // Now nullable
PpmAttachments copyWith({
num? id,
num? visitId,
String? attachmentName,
String? attachmentURL,
}) =>
PpmAttachments(
id: id ?? this.id,
visitId: visitId ?? this.visitId,
attachmentName: attachmentName ?? this.attachmentName,attachmentURL: attachmentURL ?? this.attachmentURL,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['visitId'] = visitId;
map['attachmentName'] = attachmentName;
map['attachmentURL'] = attachmentURL;
return map;
}
}
// class PpmAttachments {
// PpmAttachments({
// this.id,
// this.visitId,
// this.attachmentName,
// this.attachmentURL,
// });
//
// PpmAttachments.fromJson(dynamic json) {
// id = json['id'];
// visitId = json['visitId'];
// attachmentName = json['attachmentName'] ?? json['attachmentURL']; // Handle potential null and prioritize'attachmentName'
// }
//
// num? id; // Now nullable
// num? visitId; // Now nullable
// String? attachmentName; // Now nullable
// String? attachmentURL; // Now nullable
//
// PpmAttachments copyWith({
// num? id,
// num? visitId,
// String? attachmentName,
// String? attachmentURL,
// }) =>
// PpmAttachments(
// id: id ?? this.id,
// visitId: visitId ?? this.visitId,
// attachmentName: attachmentName ?? this.attachmentName,attachmentURL: attachmentURL ?? this.attachmentURL,
// );
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['id'] = id;
// map['visitId'] = visitId;
// map['attachmentName'] = attachmentName;
// map['attachmentURL'] = attachmentURL;
// return map;
// }
// }

@ -1,6 +1,7 @@
import 'dart:typed_data';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
@ -10,7 +11,6 @@ import 'package:test_sa/models/service_request/wo_call_request.dart';
import 'package:test_sa/models/service_request/wo_parent.dart';
import 'package:test_sa/models/timer_model.dart';
import '../../attachment.dart';
import '../fault_description.dart';
import '../new_models/assigned_employee.dart';
import '../new_models/assistant_employee.dart';
@ -41,12 +41,12 @@ class SearchWorkOrder {
this.travelingHours,
this.travelingExpenses,
this.faultDescription,
this.sparePartsWorkOrders,
this.reviewComment,
this.comment,
this.attachmentsWorkOrder,
this.equipmentStatus,
this.suppEngineerWorkOrders,
this.sparePartsWorkOrders,
this.reviewComment,
this.comment,
List<GenericAttachmentModel>? attachmentsWorkOrder,
this.equipmentStatus,
this.suppEngineerWorkOrders,
this.engSignature,
this.nurseSignature,
this.woParentDto,
@ -106,7 +106,7 @@ class SearchWorkOrder {
if (json['attachmentsWorkOrder'] != null) {
attachmentsWorkOrder = [];
json['attachmentsWorkOrder'].forEach((v) {
attachmentsWorkOrder!.add(Attachment.fromJson(v));
attachmentsWorkOrder!.add(GenericAttachmentModel.fromJson(v));
});
}
equipmentStatus = json['equipmentStatus'] != null ? Lookup.fromJson(json['equipmentStatus']) : null;
@ -155,8 +155,8 @@ class SearchWorkOrder {
sparePartsWorkOrders = (wo.sparePartsWorkOrders ?? sparePartsWorkOrders)?.map((e) => SparePartsWorkOrders.fromJson(e.toJson() ?? {})).toList() ?? [];
reviewComment = wo.reviewComment ?? reviewComment;
comment = wo.comment ?? comment;
attachmentsWorkOrder = (wo.attachmentsWorkOrder ?? attachmentsWorkOrder)?.map((e) => Attachment.fromJson(e.toJson() ?? {})).toList() ?? [];
equipmentStatus = Lookup.fromJson((wo.equipmentStatus ?? equipmentStatus)?.toJson() ?? {});
attachmentsWorkOrder = (wo.attachmentsWorkOrder ?? attachmentsWorkOrder)?.map((e) => GenericAttachmentModel.fromJson(e?.toJson() ?? {})).toList() ?? [];
equipmentStatus = wo.equipmentStatus ?? equipmentStatus;
suppEngineerWorkOrders = (wo.suppEngineerWorkOrders ?? suppEngineerWorkOrders)?.map((e) => SuppEngineerWorkOrders.fromJson(e.toJson() ?? {})).toList() ?? [];
engSignature = wo.engSignature ?? engSignature;
nurseSignature = wo.nurseSignature ?? nurseSignature;
@ -191,7 +191,7 @@ class SearchWorkOrder {
List<SparePartsWorkOrders>? sparePartsWorkOrders;
String? reviewComment;
String? comment;
List<Attachment>? attachmentsWorkOrder;
List<GenericAttachmentModel>? attachmentsWorkOrder;
Lookup? equipmentStatus;
List<SuppEngineerWorkOrders>? suppEngineerWorkOrders;
String? engSignature;
@ -233,7 +233,7 @@ class SearchWorkOrder {
List<SparePartsWorkOrders>? sparePartsWorkOrders,
String? reviewComment,
String? comment,
List<Attachment>? attachmentsWorkOrder,
List<GenericAttachmentModel>? attachmentsWorkOrder,
Lookup? equipmentStatus,
List<SuppEngineerWorkOrders>? suppEngineerWorkOrders,
String? engSignature,

@ -5,6 +5,7 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
@ -13,7 +14,6 @@ import 'package:test_sa/models/service_request/wo_call_request.dart';
import 'package:test_sa/models/service_request/wo_parent.dart';
import 'package:test_sa/models/timer_model.dart';
import '../../attachment.dart';
import '../device/asset.dart';
import '../fault_description.dart';
import '../new_models/assigned_employee.dart';
@ -118,7 +118,7 @@ class ServiceReport {
attachmentsWorkOrder = [];
json['attachmentsWorkOrder'].forEach((v) {
v["name"] = URLs.getFileUrl(v["name"]);
attachmentsWorkOrder!.add(Attachment.fromJson(v));
attachmentsWorkOrder!.add(GenericAttachmentModel.fromJson(v));
});
}
equipmentStatus = json['equipmentStatus'] != null ? Lookup.fromJson(json['equipmentStatus']) : null;
@ -163,7 +163,7 @@ class ServiceReport {
List<SparePartsWorkOrders>? sparePartsWorkOrders;
String? reviewComment;
String? comment;
List<Attachment>? attachmentsWorkOrder;
List<GenericAttachmentModel>? attachmentsWorkOrder;
Lookup? equipmentStatus;
List<SuppEngineerWorkOrders>? suppEngineerWorkOrders;
String? engSignature;
@ -204,7 +204,7 @@ class ServiceReport {
List<SparePartsWorkOrders>? sparePartsWorkOrders,
String? reviewComment,
String? comment,
List<Attachment>? attachmentsWorkOrder,
List<GenericAttachmentModel>? attachmentsWorkOrder,
Lookup? equipmentStatus,
List<SuppEngineerWorkOrders>? suppEngineerWorkOrders,
String? engSignature,
@ -311,7 +311,7 @@ class ServiceReport {
map['reviewComment'] = reviewComment;
map['comment'] = comment;
if (attachmentsWorkOrder != null) {
map['attachmentsWorkOrder'] = attachmentsWorkOrder!.map((v) => {"name": v.name!.getFileName}).toList();
map['attachmentsWorkOrder'] = attachmentsWorkOrder!.where((v) => v?.name != null).map((v) => {"name": v!.name!.getFileName}).toList();
}
if (equipmentStatus != null) {
map['equipmentStatus'] = equipmentStatus!.toJson();

@ -1,4 +1,5 @@
import 'package:test_sa/models/base.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
class SupplierDetails extends Base {
SupplierDetails({
@ -60,7 +61,7 @@ class SupplierDetails extends Base {
if (json['attachments'] != null) {
attachments = [];
json['attachments'].forEach((v) {
attachments!.add(Attachments.fromJson(v));
attachments!.add(GenericAttachmentModel.fromSupplierJson(v));
});
}
if (json['suppPersons'] != null) {
@ -93,7 +94,7 @@ class SupplierDetails extends Base {
List<Telephones>? telephones;
List<Faxes>? faxes;
List<Addresses>? addresses;
List<Attachments>? attachments;
List<GenericAttachmentModel>? attachments;
List<SuppPersons>? suppPersons;
List<SuppTCodes>? suppTCodes;
@ -114,7 +115,7 @@ class SupplierDetails extends Base {
List<Telephones>? telephones,
List<Faxes>? faxes,
List<Addresses>? addresses,
List<Attachments>? attachments,
List<GenericAttachmentModel>? attachments,
List<SuppPersons>? suppPersons,
List<SuppTCodes>? suppTCodes,
}) =>
@ -165,7 +166,7 @@ class SupplierDetails extends Base {
map['addresses'] = addresses!.map((v) => v.toJson()).toList();
}
if (attachments != null) {
map['attachments'] = attachments!.map((v) => v.toJson()).toList();
map['attachments'] = attachments!.map((v) => v.toSupplierJson()).toList();
}
if (suppPersons != null) {
map['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList();
@ -283,48 +284,48 @@ class SuppPersons extends Base {
}
}
class Attachments {
Attachments({
this.id,
this.supplierId,
this.attachmentName,
this.attachmentURL,
});
Attachments.fromJson(dynamic json) {
id = json['id'];
supplierId = json['supplierId'];
attachmentName = json['attachmentName'];
attachmentURL = json['attachmentURL'];
}
num? id;
num? supplierId;
String? attachmentName;
String? attachmentURL;
Attachments copyWith({
num? id,
num? supplierId,
String? attachmentName,
String? attachmentURL,
}) =>
Attachments(
id: id ?? this.id,
supplierId: supplierId ?? this.supplierId,
attachmentName: attachmentName ?? this.attachmentName,
attachmentURL: attachmentURL ?? this.attachmentURL,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['supplierId'] = supplierId;
map['attachmentName'] = attachmentName;
map['attachmentURL'] = attachmentURL;
return map;
}
}
// class Attachments {
// Attachments({
// this.id,
// this.supplierId,
// this.attachmentName,
// this.attachmentURL,
// });
//
// Attachments.fromJson(dynamic json) {
// id = json['id'];
// supplierId = json['supplierId'];
// attachmentName = json['attachmentName'];
// attachmentURL = json['attachmentURL'];
// }
//
// num? id;
// num? supplierId;
// String? attachmentName;
// String? attachmentURL;
//
// Attachments copyWith({
// num? id,
// num? supplierId,
// String? attachmentName,
// String? attachmentURL,
// }) =>
// Attachments(
// id: id ?? this.id,
// supplierId: supplierId ?? this.supplierId,
// attachmentName: attachmentName ?? this.attachmentName,
// attachmentURL: attachmentURL ?? this.attachmentURL,
// );
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['id'] = id;
// map['supplierId'] = supplierId;
// map['attachmentName'] = attachmentName;
// map['attachmentURL'] = attachmentURL;
// return map;
// }
// }
class Addresses {
Addresses({

@ -128,6 +128,8 @@ class _AssetDeliveryAttachmentViewState extends State<AssetDeliveryAttachmentVie
return GenericAttachmentModel(
id: item.id ?? 0,
name: name,
documentType: item.documentType,
);
}).toList();

@ -4,7 +4,7 @@ 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';
///TODO need to remove this after verifying we need to use the same for all modules ..
class AttachmentTypeLookupProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
@ -31,3 +31,33 @@ class AttachmentTypeLookupProvider extends LoadingListNotifier<Lookup> {
}
}
}
class AttachmentTypeLookupProviderLatest extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();
try {
// OPTIMIZATION: Enable caching for demo document types lookup
Response response = await ApiManager.instance.get(
URLs.getAttachmentTypesLookup,
useCache: true,
enableToastMessage: false,
);
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;
}
}
}

@ -1,5 +1,7 @@
import 'dart:developer';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
import 'package:test_sa/models/new_models/room_model.dart';
@ -106,7 +108,7 @@ class AssetInventoryModel {
Department? department;
Rooms? room;
SupplierDetails? supplier;
List<AssetInventoryDetailAssetAttachments> assetInventoryDetailAssetAttachments = [];
List<GenericAttachmentModel> assetInventoryDetailAssetAttachments = [];
AssetInventoryModel({
this.id,
@ -195,10 +197,10 @@ class AssetInventoryModel {
photo = json['photo'];
photoOriginName = json['photoOriginName'];
remarks = json['remarks'];
if (json['assetTransferAttachments'] != null) {
if (json['assetInventoryDetailAssetAttachments'] != null) {
assetInventoryDetailAssetAttachments = [];
json['assetInventoryDetailAssetAttachments'].forEach((v) {
assetInventoryDetailAssetAttachments.add(AssetInventoryDetailAssetAttachments.fromJson(v));
assetInventoryDetailAssetAttachments.add(GenericAttachmentModel.fromAssetJson(v));
});
}
@ -241,7 +243,7 @@ class AssetInventoryModel {
'photo': photo,
'remarks': remarks,
'assetInventoryDetailAssetAttachments': assetInventoryDetailAssetAttachments != null
? assetInventoryDetailAssetAttachments!.map((v) => v.toJson()).toList()
? assetInventoryDetailAssetAttachments!.map((v) => v?.toAssetJson() ?? {}).toList()
: [],
};
}
@ -307,39 +309,3 @@ class AssetInventoryModel {
}
class AssetInventoryDetailAssetAttachments {
AssetInventoryDetailAssetAttachments({
this.id,
this.name,
this.originalName,
});
AssetInventoryDetailAssetAttachments.fromJson(dynamic json) {
id = json['id'];
name = json['name'];
originalName = json['originalName'];
}
num? id;
String? name;
String? originalName;
AssetInventoryDetailAssetAttachments copyWith({
num? id, // Parameter is now nullable
String? name, // Parameter is now nullable
String? originalName, // Parameter is now nullable
}) =>
AssetInventoryDetailAssetAttachments(
id: id ?? this.id,
name: name??this.name,
originalName: originalName??this.originalName,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['name'] = name;
map['originalName'] = originalName;
return map;
}
}

@ -302,6 +302,7 @@ class _AssetInventoryFormViewState extends State<AssetInventoryFormView> {
AttachmentPicker(
label: context.translation.attachFiles,
attachment: attachments,
showAsListView: true,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
@ -406,7 +407,7 @@ class _AssetInventoryFormViewState extends State<AssetInventoryFormView> {
// try {
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_scannedAssetModel?.assetInventoryDetailAssetAttachments.add(AssetInventoryDetailAssetAttachments(id: item.id, name: fileName));
_scannedAssetModel?.assetInventoryDetailAssetAttachments.add(GenericAttachmentModel(id: item.id, name: fileName,documentType: item.documentType));
}
// // } catch (error) {
// // print(error);

@ -260,15 +260,15 @@ class CMDetailProvider extends ChangeNotifier {
}
//upload workorder attachment by engineer..
Future addWorkOrderAttachment({required int woId, required List<GenericAttachmentModel> attachments, required List<WorkOrderAttachments> otherAttachment}) async {
Future addWorkOrderAttachment({required int woId, required List<GenericAttachmentModel> attachments, required List<GenericAttachmentModel> otherAttachment}) async {
try {
List<WorkOrderAttachments> woAttachments = [];
List<GenericAttachmentModel> woAttachments = [];
if (otherAttachment.isNotEmpty) {
woAttachments.addAll(otherAttachment);
}
for (var file in attachments) {
String fileName = CMRequestUtils.isLocalUrl(file.name ?? '') ? ("${file.name ?? ''.split("/").last}|${base64Encode(File(file.name ?? '').readAsBytesSync())}") : file.name ?? '';
woAttachments.add(WorkOrderAttachments(id: file.id, name: fileName, createdBy: file.createdBy));
woAttachments.add(GenericAttachmentModel(id: file.id, name: fileName, createdBy: file.createdBy, documentType: file.documentType));
}
isLoading = true;

@ -157,6 +157,7 @@ class _CreateCMRequestState extends State<CreateCMRequest> with TickerProviderSt
24.height,
AttachmentPicker(
label: context.translation.attachImage,
showAsListView: true,
attachment: _deviceImages,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
@ -350,10 +351,10 @@ class _CreateCMRequestState extends State<CreateCMRequest> with TickerProviderSt
_serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}";
}
}
List<WorkOrderAttachments> attachement = [];
List<GenericAttachmentModel> attachement = [];
for (var item in _deviceImages) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
attachement.add(WorkOrderAttachments(id: 0, name: fileName));
attachement.add(GenericAttachmentModel(id: 0, name: fileName, documentType: item.documentType));
}
_requestDetailProvider.workOrderHelperModel = WorkOrderHelperModel(
assetId: _serviceRequest.device?.id,

@ -7,6 +7,7 @@ import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/helper_data_models/maintenance_request/activity_maintenance_model.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart';
import 'package:test_sa/models/new_models/assistant_employee.dart';
@ -172,7 +173,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
if (activity.activitySparePart?.acitiySparePartAttachments?.isNotEmpty ?? false) ...[
2.height,
const Divider().defaultStyle(context),
FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
],
],
).toShadowContainer(context, showShadow: false).onPress(() {

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
@ -41,7 +43,7 @@ class ServiceRequestDetailView extends StatefulWidget {
class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
List<GenericAttachmentModel> _userAttachments = [];
List<WorkOrderAttachments> _attachments = [];
List<GenericAttachmentModel> _attachments = [];
@override
void initState() {
@ -53,13 +55,20 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
return Consumer<CMDetailProvider>(builder: (pContext, requestProvider, _) {
if (userProvider.user?.type == UsersTypes.engineer) {
// _userAttachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments.where((e) => e.createdBy == _userProvider.user?.userID).map((e) => File(e.name ?? '')).toList() ?? [];
_userAttachments =
requestProvider.currentWorkOrder?.data?.workOrderAttachments.where((e) => e.createdBy == userProvider.user?.userID).map((e) => GenericAttachmentModel.fromJson(e.toJson())).toList() ?? [];
_attachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments.where((e) => e.createdBy != userProvider.user?.userID).toList() ?? [];
_userAttachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.createdBy == userProvider.user?.userID)
.map((e) => GenericAttachmentModel(id: e.id, name: e.name, createdBy: e.createdBy, documentType: e.documentType))
.toList() ?? [];
_attachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.createdBy != userProvider.user?.userID)
.toList() ?? [];
} else {
//show only nurse attachments
_attachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments.where((e) => e.createdBy == userProvider.user?.userID).toList() ?? [];
_attachments = requestProvider.currentWorkOrder?.data?.workOrderAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.createdBy == userProvider.user?.userID)
.toList() ?? [];
}
bool showInitialVisitCard = requestProvider.currentWorkOrder?.data?.needAVisitDateTime != null &&
@ -267,20 +276,20 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
const Divider().defaultStyle(context),
AttachmentPicker(
label: context.translation.attachments,
showAsListView: true,
attachment: _userAttachments,
buttonColor: AppColor.primary10,
onlyImages: false,
// showAsGrid: true,
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
onChange: (attachment) {
requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment, otherAttachment: _attachments);
requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment, otherAttachment: _attachments,);
},
),
],
] else ...[
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
FilesList(images: _attachments.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
FilesList(images: _attachments.map((toElement) => URLs.getFileUrl(toElement.name!)!).toList(),showAsListView: true,),
],
//handle nurse case..
],

@ -106,9 +106,10 @@ class _AssetRetiredState extends State<AssetRetired> with TickerProviderStateMix
AttachmentPicker(
label: context.translation.attachFiles,
attachment: _attachments,
showAsListView: true,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
buttonColor: AppColor.black10,
// buttonColor: AppColor.black10,
),
],
).paddingOnly(start: 13, end: 13, top: 14, bottom: 16),
@ -125,7 +126,8 @@ class _AssetRetiredState extends State<AssetRetired> with TickerProviderStateMix
for (var item in _attachments) {
String fileName =
CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
requestDetailProvider.assetRetiredHelperModel?.activityAssetToBeRetiredAttachments?.add(ActivityAssetToBeRetiredAttachments(id: item.id, name: fileName));
requestDetailProvider.assetRetiredHelperModel?.activityAssetToBeRetiredAttachments
?.add(GenericAttachmentModel(id: item.id, name: fileName, documentType: item.documentType));
}
int status = await requestDetailProvider.createActivityAssetToBeRetired();
if (status == 200) {

@ -83,7 +83,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
activityStatus = _requestDetailProvider?.sparePartHelperModel?.activityStatus?.value;
scheduleMicrotask(() async {
_isLoading = true;
attachments = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => GenericAttachmentModel(id: e.id!, name: e.name ?? '')).toList() ?? [];
attachments = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.where((e) => e?.id != null).map((e) => GenericAttachmentModel(id: e!.id!, name: e.name ?? '')).toList() ?? [];
setState(() {});
_spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
_isLoading = false;
@ -292,9 +292,10 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
12.height,
AttachmentPicker(
label: context.translation.attachQuotation,
showAsListView: true,
attachment: attachments,
buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10),
buttonColor: AppColor.primary10,
// buttonColor: AppColor.primary10,
),
],
).toShadowContainer(context),
@ -334,7 +335,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
requestDetailProvider.sparePartHelperModel?.sparePartAttachments?.add(
SparePartAttachments(id: item.id, name: fileName),
GenericAttachmentModel(id: item.id, name: fileName, documentType: item.documentType),
);
}

@ -25,7 +25,6 @@ import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/demo_module/models/demo_attachment_model.dart';
import 'package:test_sa/modules/demo_module/provider/demo_period_lookup_provider.dart';
import 'package:test_sa/modules/demo_module/provider/demo_provider.dart';
import 'package:test_sa/modules/loan_module/models/loan_form_model.dart';
@ -495,23 +494,23 @@ class _CreateDemoRequestPageState extends State<CreateDemoRequestPage> with Tick
List<Widget> attachmentSection() {
return [
InfoHeader16Widget('Attachments'.addTranslation),
SingleItemDropDownMenu<Lookup, DemoDocumentLookupProvider>(
context: context,
height: 56.toScreenHeight,
title: "Document Type",
initialValue: demoDocumentLookup,
showShadow: false,
validator: (value) {
if (value == null) return "Mandatory";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
demoDocumentLookup = value;
setState(() {});
},
),
// SingleItemDropDownMenu<Lookup, DemoDocumentLookupProvider>(
// context: context,
// height: 56.toScreenHeight,
// title: "Document Type",
// initialValue: demoDocumentLookup,
// showShadow: false,
// validator: (value) {
// if (value == null) return "Mandatory";
// return null;
// },
// backgroundColor: AppColor.fieldBgColor(context),
// showAsBottomSheet: true,
// onSelect: (value) {
// demoDocumentLookup = value;
// setState(() {});
// },
// ),
AttachmentPicker(
label: context.translation.attachments,
attachment: _attachments,
@ -520,11 +519,11 @@ class _CreateDemoRequestPageState extends State<CreateDemoRequestPage> with Tick
enabled: demoDocumentLookup != null,
documentType: demoDocumentLookup,
showAsListView: true,
buttonIcon: 'image-plus'.toSvgAsset(color: (AppColor.primary10).withOpacity(demoDocumentLookup != null ? 1 : .4)),
onChange: (attachments) {
_attachments = attachments;
setState(() {});
},
buttonIcon: 'image-plus'.toSvgAsset(color: (AppColor.primary10)),
// onChange: (attachments) {
// _attachments = attachments;
// setState(() {});
// },
),
];
}
@ -537,7 +536,12 @@ class _CreateDemoRequestPageState extends State<CreateDemoRequestPage> with Tick
_demoFormModel.demoAttachment = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_demoFormModel.demoAttachment?.add(DemoAttachments(id: 0, attachmentName: fileName, demoRequestId: 0, documentTypeId: item.documentTypeId!.id!));
_demoFormModel.demoAttachment?.add(GenericAttachmentModel(
id: 0,
name: fileName,
moduleReferenceId: 0,
documentType: item.documentType,
));
}
Utils.showLoading(context);
DemoProvider demoProvider = Provider.of<DemoProvider>(context, listen: false);

@ -6,6 +6,7 @@ import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/enums/demo_request_step.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
import 'package:test_sa/models/module_permissions_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
@ -91,8 +92,8 @@ class _DemoDetailViewPageState extends State<DemoDetailViewPage> {
if (snapshot.connectionState == ConnectionState.waiting) return CircularProgressIndicator(color: AppColor.loadingColor(context)).center;
if (snapshot.data == null) return const NoDataFound().center;
List<DemoAttachments> allAttachments = snapshot.data!.demoAttachments! ?? [];
List<DemoAttachments> suppAttachments = snapshot.data!.supplierDemoAttachments! ?? [];
List<GenericAttachmentModel> allAttachments = snapshot.data!.demoAttachments! ?? [];
List<GenericAttachmentModel> suppAttachments = snapshot.data!.supplierDemoAttachments! ?? [];
DemoRequestModel demoData = snapshot.data!;
@ -127,7 +128,7 @@ class _DemoDetailViewPageState extends State<DemoDetailViewPage> {
InfoHeader16Widget("Attachments"),
FilesList(
showAsListView: true,
images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList(),
types: allAttachments.map((e) => e.documentType?.name ?? '').toList()),
],
if (suppAttachments.isNotEmpty) ...[
@ -135,8 +136,8 @@ class _DemoDetailViewPageState extends State<DemoDetailViewPage> {
InfoHeader16Widget("Supplier Attachments"),
FilesList(
showAsListView: true,
images: suppAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList(),
types: suppAttachments.map((e) => e.documentType?.name ?? '').toList()),
images: suppAttachments.whereType<GenericAttachmentModel>().map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList(),
types: suppAttachments.whereType<GenericAttachmentModel>().map((e) => e.documentType?.name ?? '').toList()),
],
],
).toShadowContainer(context, padding: 12),

@ -6,7 +6,7 @@ import 'package:test_sa/providers/loading_list_notifier.dart';
import '../../controllers/api_routes/api_manager.dart';
import '../../controllers/api_routes/urls.dart';
import '../../models/lookup.dart';
///TODO need to remove this when we have real api for demo document types lookup
class DemoDocumentLookupProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int? id}) async {
@ -36,3 +36,4 @@ class DemoDocumentLookupProvider extends LoadingListNotifier<Lookup> {
}
}
}

@ -1,31 +1,33 @@
import 'package:test_sa/models/lookup.dart';
//TODO : need to remove this class
class DemoAttachments {
int? id;
num? demoRequestId;
num? documentTypeId;
Lookup? documentType;
String? attachmentName;
String? originalName;
DemoAttachments({this.id, this.documentTypeId, this.documentType, this.attachmentName, this.demoRequestId, this.originalName});
DemoAttachments.fromJson(dynamic json) {
id = json['id'];
documentTypeId = json['documentTypeId'];
documentType = json['documentType'] != null ? Lookup.fromJson(json['documentType']) : null;
demoRequestId = json['demoRequestId'];
attachmentName = json['attachmentName'];
originalName = json['originalName'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['documentTypeId'] = documentTypeId;
map['attachmentName'] = attachmentName;
map['demoRequestId'] = demoRequestId;
map['originalName'] = originalName;
return map;
}
}
// import 'package:test_sa/models/lookup.dart';
//
// class DemoAttachments {
// int? id;
// num? demoRequestId;
// Lookup? documentType;
// String? attachmentName;
// String? originalName;
//
// DemoAttachments({this.id, this.documentType, this.attachmentName, this.demoRequestId, this.originalName});
//
// DemoAttachments.fromJson(dynamic json) {
// id = json['id'];
// documentType = json['documentType'] != null ? Lookup.fromJson(json['documentType']) : null;
// demoRequestId = json['demoRequestId'];
// attachmentName = json['attachmentName'];
// originalName = json['originalName'];
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['id'] = id;
// if(documentType!=null){
// map['documentTypeId'] = documentType?.id;
// }
// map['attachmentName'] = attachmentName;
// map['demoRequestId'] = demoRequestId;
// map['originalName'] = originalName;
// return map;
// }
// }

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/building.dart';
import 'package:test_sa/models/new_models/floor.dart';
@ -32,7 +33,7 @@ class DemoFormModel {
Rooms? room;
SuppEngineerWorkOrders? supEngineer;
SupplierDetails? vendor;
List<DemoAttachments>? demoAttachment;
List<GenericAttachmentModel>? demoAttachment;
bool demoEaluationAcknowledge;
bool acknowledgeNotEquipment;
@ -87,34 +88,7 @@ class DemoFormModel {
"demoEaluationAcknowledge": demoEaluationAcknowledge,
"acknowledgeNotEquipment": acknowledgeNotEquipment,
"demoAttachments":
// [
// {
// "id": 3,
// // "documentType": {
// // "id": 7748,
// // "name": "February",
// // "value": 2
// // },
// "documentTypeId": 7748,
// "attachmentName": "6c9f50b0-1c92-4ae9-ae64-7c284c61ea72.jpg",
// "originalName": "scaled_d245df97-1289-4d0c-92a0-569abedfb0db8154518103327960943.jpg",
// "demoRequestId": 3
// },
// {
// "id": 4,
// // "documentType": {
// // "id": 7748,
// // "name": "February",
// // "value": 2
// // },
// "documentTypeId": 7748,
// "attachmentName": "346e04f6-0f9b-4004-ad85-4cdbf8318f7c.jpg",
// "originalName": "scaled_85790b6c-7b16-46e6-891c-11c316d5897a2973693360957767376.jpg",
// "demoRequestId": 3
// }
// ]
demoAttachment != null ? demoAttachment!.map((v) => v.toJson()).toList() : [],
demoAttachment != null ? demoAttachment!.map((v) => v.toDemoJson()).toList() : [],
};
}
@ -123,7 +97,7 @@ class DemoFormModel {
"id": id,
"supplierId": vendor?.id,
"suppPersonId": supEngineer?.id,
"demoAttachments": demoAttachment != null ? demoAttachment!.map((v) => v.toJson()).toList() : [],
"demoAttachments": demoAttachment != null ? demoAttachment!.whereType<GenericAttachmentModel>().map((v) => v.toDemoJson()).toList() : [],
};
}
}

@ -1,8 +1,8 @@
import 'package:test_sa/models/device/asset_by_id_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/modules/demo_module/models/demo_attachment_model.dart';
import 'package:test_sa/modules/loan_module/models/medical_department_model.dart';
class DemoRequestModel {
@ -29,8 +29,8 @@ class DemoRequestModel {
SuppEngineerWorkOrders? suppPerson;
Lookup? status;
Lookup? endUserStatus;
List<DemoAttachments>? demoAttachments;
List<DemoAttachments>? supplierDemoAttachments;
List<GenericAttachmentModel>? demoAttachments;
List<GenericAttachmentModel>? supplierDemoAttachments;
dynamic demoAsset;
dynamic demoInstallationTaskJob;
dynamic demoPullOutTaskJob;
@ -96,8 +96,8 @@ class DemoRequestModel {
suppPerson = json['suppPerson'] != null ? (SuppEngineerWorkOrders.fromJson(json['suppPerson'])) : null;
status = json['status'] != null ? (Lookup.fromJson(json['status'])) : null;
endUserStatus = json['endUserStatus'] != null ? (Lookup.fromJson(json['endUserStatus'])) : null;
demoAttachments = json['demoAttachments'] != null ? (json['demoAttachments'] as List).map((e) => DemoAttachments.fromJson(e)).toList() : null;
supplierDemoAttachments = json['supplierDemoAttachments'] != null ? (json['supplierDemoAttachments'] as List).map((e) => DemoAttachments.fromJson(e)).toList() : null;
demoAttachments = json['demoAttachments'] != null ? (json['demoAttachments'] as List).map((e) => GenericAttachmentModel.fromDemoJson(e)).toList() : null;
supplierDemoAttachments = json['supplierDemoAttachments'] != null ? (json['supplierDemoAttachments'] as List).map((e) => GenericAttachmentModel.fromDemoJson(e)).toList() : null;
demoAsset = json['demoAsset'];
demoInstallationTaskJob = json['demoInstallationTaskJob'];
demoPullOutTaskJob = json['demoPullOutTaskJob'];
@ -124,8 +124,8 @@ class DemoRequestModel {
"demoPeriodId": demoPeriod?.id,
"supplierId": supplier?.id,
"suppPersonId": suppPerson?.id,
"demoAttachments": demoAttachments != null ? demoAttachments!.map((v) => v.toJson()).toList() : [],
"supplierDemoAttachments": supplierDemoAttachments != null ? supplierDemoAttachments!.map((v) => v.toJson()).toList() : [],
"demoAttachments": demoAttachments != null ? demoAttachments!.whereType<GenericAttachmentModel>().map((v) => v.toDemoJson()).toList() : [],
"supplierDemoAttachments": supplierDemoAttachments != null ? supplierDemoAttachments!.whereType<GenericAttachmentModel>().map((v) => v.toDemoJson()).toList() : [],
};
}
}

@ -20,7 +20,6 @@ import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/demo_module/models/demo_attachment_model.dart';
import 'package:test_sa/modules/demo_module/models/demo_request_model.dart';
import 'package:test_sa/modules/demo_module/provider/demo_period_lookup_provider.dart';
import 'package:test_sa/modules/demo_module/provider/demo_provider.dart';
@ -161,9 +160,9 @@ class _UpdateDemoRequestViewState extends State<UpdateDemoRequestView> with Tick
attachments.clear();
if (widget.dataModel.demoAttachments?.isNotEmpty ?? false) {
for (final item in widget.dataModel.demoAttachments!) {
if ((item.attachmentName ?? '').isNotEmpty) {
if ((item.name ?? '').isNotEmpty) {
attachments.add(
GenericAttachmentModel(name: item.attachmentName, id: item.id ?? 0, originalName: item.originalName, documentTypeId: item.documentType),
GenericAttachmentModel(name: item.name, id: item.id ?? 0, originalName: item.originalName, documentType: item.documentType),
);
}
}
@ -201,33 +200,35 @@ class _UpdateDemoRequestViewState extends State<UpdateDemoRequestView> with Tick
16.height,
"Attachments".bodyText(context).custom(color: AppColor.black10),
8.height,
SingleItemDropDownMenu<Lookup, DemoDocumentLookupProvider>(
context: context,
height: 56.toScreenHeight,
title: "Document Type",
initialValue: demoDocumentLookup,
showShadow: false,
validator: (value) {
if (value == null) return "Mandatory";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
demoDocumentLookup = value;
setState(() {});
},
),
16.height,
///Need to confirm we can use same lookup..
// SingleItemDropDownMenu<Lookup, DemoDocumentLookupProvider>(
// context: context,
// height: 56.toScreenHeight,
// title: "Document Type",
// initialValue: demoDocumentLookup,
// showShadow: false,
// validator: (value) {
// if (value == null) return "Mandatory";
// return null;
// },
// backgroundColor: AppColor.fieldBgColor(context),
// showAsBottomSheet: true,
// onSelect: (value) {
// demoDocumentLookup = value;
// setState(() {});
// },
// ),
// 16.height,
AttachmentPicker(
label: context.translation.attachments,
attachment: attachments,
buttonColor: AppColor.black10.withOpacity(demoDocumentLookup != null ? 1 : .4),
onlyImages: false,
documentType: demoDocumentLookup,
enabled: demoDocumentLookup != null,
// documentType: demoDocumentLookup,
// enabled: demoDocumentLookup != null,
showAsListView: true,
buttonIcon: 'image-plus'.toSvgAsset(color: (AppColor.primary10).withOpacity(demoDocumentLookup != null ? 1 : .4)),
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
),
],
).toShadowContainer(context, borderRadius: 20),
@ -615,7 +616,13 @@ class _UpdateDemoRequestViewState extends State<UpdateDemoRequestView> with Tick
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
//Todo need to pass attachmentType id as well.
_demoFormModel.demoAttachment?.add(DemoAttachments(id: item.id, demoRequestId: _demoFormModel.id ?? 0, attachmentName: fileName,originalName: fileName, documentTypeId: item.documentTypeId!.id));
_demoFormModel.demoAttachment?.add(GenericAttachmentModel(
id: item.id,
name: fileName,
originalName: fileName,
moduleReferenceId: _demoFormModel.id ?? 0,
documentType: item.documentType,
));
}
Utils.showLoading(context);
DemoProvider demoProvider = Provider.of<DemoProvider>(context, listen: false);

@ -41,7 +41,6 @@ import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import '../../models/new_models/department.dart';
import '../../new_views/swipe_module/dialoge/info_dialog.dart';
import 'flow_medical_department_provider.dart';
import 'incident_attachment_model.dart';
class CreateIncidentRequestPage extends StatefulWidget {
static const String id = "/create-incident";
@ -694,16 +693,16 @@ class _CreateIncidentRequestPageState extends State<CreateIncidentRequestPage> {
payload["occurrenceDate"] = occurrenceDate!.toIso8601String();
_formKey.currentState!.save();
List<IncidentAttachments> attachmentList = [];
List<GenericAttachmentModel> attachmentList = [];
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
attachmentList.add(IncidentAttachments(id: 0, attachmentName: fileName, incidentId: 0));
attachmentList.add(GenericAttachmentModel(id: 0, name: fileName, moduleReferenceId: 0,documentType: item.documentType));
}
Utils.showLoading(context);
IncidentProvider incidentProvider = Provider.of<IncidentProvider>(context, listen: false);
payload["incidentAttachments"] = attachmentList.map((v) => v.toJson()).toList();
payload["incidentAttachments"] = attachmentList.map((v) => v.toIncidentJson()).toList();
bool isSuccess = await incidentProvider.addIncidentRequest(payload);
Utils.hideLoading(context);
if (isSuccess) {

@ -1,24 +1,26 @@
class IncidentAttachments {
num? id;
num? incidentId;
String? attachmentName;
String? attachmentDescription;
//TODO : need to delete this
IncidentAttachments({this.id, this.attachmentName, this.incidentId, this.attachmentDescription});
IncidentAttachments.fromJson(dynamic json) {
id = json['id'];
incidentId = json['incidentId'];
attachmentName = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['attachmentName'] = attachmentName;
map['incidentId'] = incidentId;
map['attachmentDescription'] = attachmentDescription;
return map;
}
}
// class IncidentAttachments {
// num? id;
// num? incidentId;
// String? attachmentName;
// String? attachmentDescription;
//
// IncidentAttachments({this.id, this.attachmentName, this.incidentId, this.attachmentDescription});
//
// IncidentAttachments.fromJson(dynamic json) {
// id = json['id'];
// incidentId = json['incidentId'];
// attachmentName = json['attachmentName'];
// attachmentDescription = json['attachmentDescription'];
// }
//
// Map<String, dynamic> toJson() {
// final map = <String, dynamic>{};
// map['id'] = id;
// map['attachmentName'] = attachmentName;
// map['incidentId'] = incidentId;
// map['attachmentDescription'] = attachmentDescription;
// return map;
// }
// }

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/incident_module/incident_attachment_model.dart';
class IncidentDataModel {
@ -73,7 +74,7 @@ class IncidentDataModel {
String? approvalSignature;
String? occurrenceDate;
String? createdDate;
List<IncidentAttachments>? incidentAttachments;
List<GenericAttachmentModel>? incidentAttachments;
int? workOrderId;
String? workOrderNo;
@ -230,9 +231,9 @@ class IncidentDataModel {
workOrderId = json['workOrderId'];
workOrderNo = json['workOrderNo'];
if (json['incidentAttachments'] != null) {
incidentAttachments = <IncidentAttachments>[];
incidentAttachments = <GenericAttachmentModel>[];
json['incidentAttachments'].forEach((v) {
incidentAttachments!.add(IncidentAttachments.fromJson(v));
incidentAttachments!.add(GenericAttachmentModel.fromIncidentJson(v));
});
}
}
@ -314,7 +315,7 @@ class IncidentDataModel {
data['workOrderId'] = this.workOrderId;
data['workOrderNo'] = this.workOrderNo;
if (this.incidentAttachments != null) {
data['incidentAttachments'] = this.incidentAttachments!.map((v) => v.toJson()).toList();
data['incidentAttachments'] = this.incidentAttachments!.map((v) => v.toIncidentJson()).toList();
}
return data;
}

@ -9,6 +9,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/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cm_module/cm_detail_page.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/incident_module/incident_attachment_model.dart';
@ -39,7 +40,7 @@ class IncidentDetailPage extends StatelessWidget {
if (snapshot.connectionState == ConnectionState.waiting) return CircularProgressIndicator(color: AppColor.loadingColor(context)).center;
if (snapshot.data == null) return const NoDataFound().center;
List<IncidentAttachments> allAttachments = snapshot.data!.incidentAttachments!;
List<GenericAttachmentModel> allAttachments = (snapshot.data!.incidentAttachments ?? []).whereType<GenericAttachmentModel>().toList();
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
@ -70,7 +71,7 @@ class IncidentDetailPage extends StatelessWidget {
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context),

@ -1,4 +1,4 @@
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
class EngineerData {
int? id;
@ -9,7 +9,7 @@ class EngineerData {
bool? isComplete;
int? statusId;
int? requestId;
List<InternalAuditAttachments>? attachments;
List<GenericAttachmentModel>? attachments;
EngineerData({
this.id,
@ -32,7 +32,7 @@ class EngineerData {
isComplete = json['isComplete'];
statusId = json['statusId'];
requestId = json['requestId'];
attachments = json['attachments'] != null ? (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList() : [];
attachments = json['attachments'] != null ? (json['attachments'] as List).map((e) => GenericAttachmentModel.fromInternalAuditJson(e)).toList() : [];
}
Map<String, dynamic> toJson() {
@ -46,7 +46,7 @@ class EngineerData {
data['statusId'] = statusId;
data['requestId'] = requestId;
if (attachments != null) {
data['attachments'] = attachments!.map((e) => e.toJson()).toList();
data['attachments'] = attachments!.whereType<GenericAttachmentModel>().map((e) => e.toInternalAuditJson()).toList();
}
return data;
}

@ -1,6 +1,5 @@
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/engineer_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
class EquipmentInternalAuditDataModel {
@ -15,7 +14,7 @@ class EquipmentInternalAuditDataModel {
dynamic manufacture;
String? remarks;
List<EquipmentsFinding>? equipmentsFindings;
List<InternalAuditAttachments>? attachments;
List<GenericAttachmentModel>? attachments;
EngineerData? engineerData;
@ -54,7 +53,7 @@ class EquipmentInternalAuditDataModel {
}
attachments = json['attachments'] != null
? (json['attachments'] as List)
.map((e) => InternalAuditAttachments.fromJson(e))
.map((e) => GenericAttachmentModel.fromInternalAuditJson(e))
.where((e) => e.name != null) // optional filter if you want to skip null names
.toList()
: [];
@ -86,7 +85,9 @@ class EquipmentInternalAuditDataModel {
data['equipmentsFindings'] =
equipmentsFindings!.map((v) => v.toJson()).toList();
}
data['attachments'] = attachments;
if (attachments != null) {
data['attachments'] = attachments!.whereType<GenericAttachmentModel>().map((v) => v.toInternalAuditJson()).toList();
}
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
return data;
}

@ -5,7 +5,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
class EquipmentInternalAuditFormModel {
int? id=0;
@ -14,7 +14,7 @@ class EquipmentInternalAuditFormModel {
String? woOrderNo;
List<String>? devicePhotos;
List<Lookup> findings =[];
List<InternalAuditAttachments> attachments = [];
List<GenericAttachmentModel> attachments = [];
String? remarks;
Asset? device;
EquipmentInternalAuditFormModel({
@ -32,7 +32,7 @@ class EquipmentInternalAuditFormModel {
'assetId': device?.id,
'auditorId': auditorId,
'findings': findings.map((e) => {'findingId': e.value}).toList(),
'attachments': attachments.map((e) => e.toJson()).toList(),
'attachments': attachments.whereType<GenericAttachmentModel>().map((e) => e.toInternalAuditJson()).toList(),
'remarks': remarks,
};
}

@ -1,26 +1,32 @@
import 'dart:developer';
class InternalAuditAttachments {
InternalAuditAttachments({this.id, this.originalName, this.name, this.createdBy});
int? id;
String? name;
String? originalName;
String? createdBy;
InternalAuditAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
originalName = json['originalName'];
createdBy = json['createdBy'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['name'] = name;
data['originalName'] = originalName;
// data['createdBy'] = createdBy;
return data;
}
}
//TODO : need to remove this class.
// import 'dart:developer';
//
// import 'package:test_sa/models/lookup.dart';
//
// class InternalAuditAttachments {
// InternalAuditAttachments({this.id, this.originalName, this.name, this.createdBy,this.documentType});
//
// int? id;
// String? name;
// String? originalName;
// String? createdBy;
// Lookup ? documentType;
//
// InternalAuditAttachments.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
// originalName = json['originalName'];
// createdBy = json['createdBy'];
// documentType =json['documentType'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = <String, dynamic>{};
// data['id'] = id;
// data['name'] = name;
// data['originalName'] = originalName;
// data['documentTypeId'] = documentType?.id;
// // data['createdBy'] = createdBy;
// return data;
// }
// }

@ -1,6 +1,6 @@
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/internal_audit_module/models/engineer_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
class SystemInternalAuditDataModel {
@ -19,7 +19,7 @@ class SystemInternalAuditDataModel {
String? createdDate;
String? modifiedBy;
String? modifiedDate;
List<InternalAuditAttachments>? attachments;
List<GenericAttachmentModel>? attachments;
EngineerData? engineerData;
SystemInternalAuditDataModel({
@ -60,7 +60,7 @@ class SystemInternalAuditDataModel {
modifiedDate = json['modifiedDate'];
attachments = json['attachments'] != null
? (json['attachments'] as List)
.map((e) => InternalAuditAttachments.fromJson(e))
.map((e) => GenericAttachmentModel.fromInternalAuditJson(e))
.where((e) => e.name != null) // optional filter if you want to skip null names
.toList()
: [];
@ -84,6 +84,9 @@ class SystemInternalAuditDataModel {
data['createdDate'] = createdDate;
data['modifiedBy'] = modifiedBy;
data['modifiedDate'] = modifiedDate;
if (attachments != null) {
data['attachments'] = attachments!.whereType<GenericAttachmentModel>().map((v) => v.toInternalAuditJson()).toList();
}
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
return data;
}

@ -1,7 +1,7 @@
import 'dart:developer';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
class SystemInternalAuditFormModel {
int? id;
@ -13,7 +13,7 @@ class SystemInternalAuditFormModel {
int? correctiveMaintenanceId;
int? planPreventiveVisitId;
int? assetTransferId;
List<InternalAuditAttachments>? attachments = [];
List<GenericAttachmentModel>? attachments = [];
int? taskJobId;
int? taskAlertJobId;
int? gasRefillId;
@ -56,7 +56,7 @@ class SystemInternalAuditFormModel {
'gasRefillId': gasRefillId,
'planRecurrentTaskId': planRecurrentTaskId,
'statusId': statusId,
'attachments': attachments?.map((e) => e.toJson()).toList(),
'attachments': attachments?.whereType<GenericAttachmentModel>().map((e) => e.toInternalAuditJson()).toList(),
};
}
}

@ -1,5 +1,5 @@
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
class AuditFormModel {
@ -10,7 +10,7 @@ class AuditFormModel {
DateTime? startTime;
DateTime? endTime;
double? totalHours;
List<InternalAuditAttachments>? attachments;
List<GenericAttachmentModel>? attachments;
bool? isComplete;
TimerModel? auditTimerModel = TimerModel();
List<InternalAuditTimerModel>? auditTimers = [];
@ -40,7 +40,7 @@ class AuditFormModel {
endTime = json['endTime'] != null ? DateTime.tryParse(json['endTime']) : null;
totalHours = json['totalHours']?.toDouble();
if (json['attachments'] != null) {
attachments = (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList();
attachments = (json['attachments'] as List).map((e) => GenericAttachmentModel.fromInternalAuditJson(e)).toList();
}
isComplete = json['isComplete'];
}
@ -54,7 +54,7 @@ class AuditFormModel {
'endTime': endTime?.toIso8601String(),
// 'auditTimer': auditTimers,
'totalHours': totalHours,
'attachments': attachments?.map((e) => e.toJson()).toList(),
'attachments': attachments?.whereType<GenericAttachmentModel>().map((e) => e.toInternalAuditJson()).toList(),
'isComplete': isComplete,
};
}

@ -12,8 +12,8 @@ import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@ -119,6 +119,7 @@ class _CreateEquipmentInternalAuditFormState extends State<CreateEquipmentIntern
AttachmentPicker(
label: context.translation.attachments,
attachment: _attachments,
showAsListView: true,
buttonColor: AppColor.primary10,
onlyImages: false,
onChange: (value) {},
@ -144,7 +145,11 @@ class _CreateEquipmentInternalAuditFormState extends State<CreateEquipmentIntern
_equipmentinternalAuditModel.attachments = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_equipmentinternalAuditModel.attachments.add(InternalAuditAttachments(id: item.id, name: fileName));
_equipmentinternalAuditModel.attachments.add(GenericAttachmentModel(
id: item.id,
name: fileName,
documentType: item.documentType,
));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
_equipmentinternalAuditModel.auditorId = context.userProvider.user?.userID;

@ -10,7 +10,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
@ -41,7 +41,7 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
bool isWoType = true;
EquipmentInternalAuditDataModel? model;
late InternalAuditProvider _internalAuditProvider;
List<InternalAuditAttachments> allAttachments = [];
List<GenericAttachmentModel> allAttachments = [];
@override
void initState() {
@ -56,8 +56,8 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
model = await _internalAuditProvider.getEquipmentInternalAuditById(widget.auditId);
allAttachments.clear();
allAttachments = [
...(model?.attachments ?? []),
...(model?.engineerData?.attachments ?? []),
...(model?.attachments?.whereType<GenericAttachmentModel>() ?? []),
...(model?.engineerData?.attachments?.whereType<GenericAttachmentModel>() ?? []),
];
}

@ -14,10 +14,9 @@ import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
@ -62,7 +61,7 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
formModel.requestId = widget.model?.id;
formModel.id = widget.model?.id;
formModel.debrief = widget.model?.engineerData?.debrief;
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
_attachments = widget.model?.engineerData?.attachments?.whereType<GenericAttachmentModel>().map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name ?? '')).toList() ?? [];
calculateWorkingTime();
}
@ -129,9 +128,10 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name?.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
formModel.attachments!.add(
InternalAuditAttachments(
GenericAttachmentModel(
id: item.id,
originalName: fileName,
documentType: item.documentType,
name: fileName,
),
);
@ -221,6 +221,7 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
AttachmentPicker(
label: 'Upload Attachment',
attachment: _attachments,
showAsListView: true,
buttonColor: AppColor.primary10,
onlyImages: false,
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),

@ -14,8 +14,8 @@ import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_mo
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_audit_work_order_auto_complete_field.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
@ -152,6 +152,7 @@ class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAudi
16.height,
AttachmentPicker(
label: context.translation.attachments,
showAsListView: true,
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
@ -178,10 +179,14 @@ class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAudi
InternalAuditProvider internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
_model.attachments=[];
_model.attachments = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_model.attachments?.add(InternalAuditAttachments(id: item.id, name: fileName));
_model.attachments?.add(GenericAttachmentModel(
id: item.id,
name: fileName,
documentType: item.documentType,
));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
_model.auditorId = context.userProvider.user?.userID;

@ -9,7 +9,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/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/update_system_internal_audit_page.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
@ -39,7 +39,7 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
bool isWoType = true;
SystemInternalAuditDataModel? model;
late InternalAuditProvider _internalAuditProvider;
List<InternalAuditAttachments> allAttachments = [];
List<GenericAttachmentModel> allAttachments = [];
@override
void initState() {
@ -54,8 +54,8 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
model = await _internalAuditProvider.getInternalSystemAuditById(widget.auditId);
allAttachments.clear();
allAttachments = [
...(model?.attachments ?? []),
...(model?.engineerData?.attachments ?? []),
...(model?.attachments?.whereType<GenericAttachmentModel>() ?? []),
...(model?.engineerData?.attachments?.whereType<GenericAttachmentModel>() ?? []),
];
}

@ -14,10 +14,8 @@ import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
@ -62,7 +60,7 @@ class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAudi
formModel.requestId = widget.model?.id;
formModel.id = widget.model?.id;
formModel.debrief = widget.model?.engineerData?.debrief;
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
_attachments = widget.model?.engineerData?.attachments?.whereType<GenericAttachmentModel>().map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name ?? '')).toList() ?? [];
calculateWorkingTime();
}
@ -130,8 +128,9 @@ class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAudi
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name?.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
formModel.attachments!.add(
InternalAuditAttachments(
GenericAttachmentModel(
id: item.id,
documentType: item.documentType,
// originalName: fileName,
name: fileName,
),
@ -211,6 +210,7 @@ class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAudi
16.height,
AttachmentPicker(
label: 'Upload Attachment',
showAsListView: true,
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,

@ -1,39 +1,40 @@
class LoanAttachmentModel {
int? loanId;
String? attachmentName;
int? loanAttachmentTypeId;
String? attachmentDescription;
int? id;
String? createdBy;
String? createdDate;
String? modifiedBy;
String? modifiedDate;
LoanAttachmentModel({this.loanId, this.attachmentName, this.loanAttachmentTypeId, this.attachmentDescription, this.id, this.createdBy, this.createdDate, this.modifiedBy, this.modifiedDate});
LoanAttachmentModel.fromJson(Map<String, dynamic> json) {
loanId = json['loanId'];
attachmentName = json['attachmentName'];
loanAttachmentTypeId = json['loanAttachmentTypeId'];
attachmentDescription = json['attachmentDescription'];
id = json['id'];
createdBy = json['createdBy'];
createdDate = json['createdDate'];
modifiedBy = json['modifiedBy'];
modifiedDate = json['modifiedDate'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['loanId'] = this.loanId;
data['attachmentName'] = this.attachmentName;
data['loanAttachmentTypeId'] = this.loanAttachmentTypeId;
data['attachmentDescription'] = this.attachmentDescription;
data['id'] = this.id;
data['createdBy'] = this.createdBy;
data['createdDate'] = this.createdDate;
data['modifiedBy'] = this.modifiedBy;
data['modifiedDate'] = this.modifiedDate;
return data;
}
}
//TODO need to delete this .
// class LoanAttachmentModel {
// int? loanId;
// String? attachmentName;
// int? loanAttachmentTypeId;
// String? attachmentDescription;
// int? id;
// String? createdBy;
// String? createdDate;
// String? modifiedBy;
// String? modifiedDate;
//
// LoanAttachmentModel({this.loanId, this.attachmentName, this.loanAttachmentTypeId, this.attachmentDescription, this.id, this.createdBy, this.createdDate, this.modifiedBy, this.modifiedDate});
//
// LoanAttachmentModel.fromJson(Map<String, dynamic> json) {
// loanId = json['loanId'];
// attachmentName = json['attachmentName'];
// loanAttachmentTypeId = json['loanAttachmentTypeId'];
// attachmentDescription = json['attachmentDescription'];
// id = json['id'];
// createdBy = json['createdBy'];
// createdDate = json['createdDate'];
// modifiedBy = json['modifiedBy'];
// modifiedDate = json['modifiedDate'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['loanId'] = this.loanId;
// data['attachmentName'] = this.attachmentName;
// data['loanAttachmentTypeId'] = this.loanAttachmentTypeId;
// data['attachmentDescription'] = this.attachmentDescription;
// data['id'] = this.id;
// data['createdBy'] = this.createdBy;
// data['createdDate'] = this.createdDate;
// data['modifiedBy'] = this.modifiedBy;
// data['modifiedDate'] = this.modifiedDate;
// return data;
// }
// }

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/mapped_sites.dart';
import 'package:test_sa/models/new_models/site.dart';
@ -24,7 +25,7 @@ class LoanFormModel {
SupplierDetails? supplier;
SuppEngineerWorkOrders? supEngineer;
MedicalDepartmentModel? department;
List<LoanAttachments>? loanAttachment;
List<GenericAttachmentModel>? loanAttachment;
MappedSite? mappedSite;
TrafDepartment? mappedDepartment;
@ -51,40 +52,6 @@ class LoanFormModel {
this.mappedDepartment,
});
//{
// "id": 0,
// "employeeId": "fa29a9de-1337-4729-b823-68c6ecffdd33",
// "requestorUserID": "fa29a9de-1337-4729-b823-68c6ecffdd33",
// "employeeName": "engineer-dev",
// "employeeEmail": "Engineer_Dev@yahoo.com",
// "positionName": "High",
// "requesterExtensionNumber": "7726",
// "requesterContactNumber": "72132197",
// "siteId": 1,
// "departmentId": 5,
// "loanTypeId": 6448,
// "doctorName": "Doctor A",
// "doctorContact": "0561432451",
// "doctorEmail": "doctor@test.com",
// "itemDescription": "Test item",
// "requestDescription": "Test request",
// "loanPeriodId": 6453,
// "assetId": null,
// "assetNumber": "",
// "assetName": "",
// "assetSerialNumber": "",
// "model": "Model A",
// "manufacturer": "Siemens",
// "vendorName": "Vendor A",
// "vendorRepName": "Vendor Rep A",
// "vendorContact": "0561432455",
// "vendorEmail": "vendor@test.com",
// "loanStatusId": 1,
// "loanAttachments": [],
// "submittedAt": "2025-11-13T12:11:12.673Z",
// "updatedAt": null,
// "cMWOItemId": null
// }
Map<String, dynamic> toJson() {
return {
@ -103,50 +70,10 @@ class LoanFormModel {
"vendorContact": vendorNumber,
"vendorEmail": vendorEmail,
"isNewVendor": isNewVendor,
// 'siteId': site?.id,
'siteId': mappedSite?.id,
// 'departmentId': department?.id,
'departmentId': mappedDepartment?.id,
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toLoanJson()).toList() : [],
};
}
}
class LoanAttachments {
num? id;
num? loanAttachmentTypeId;
num? loanId;
String? attachmentName;
String? attachmentDescription;
LoanAttachments({this.id, this.loanAttachmentTypeId, this.attachmentName, this.loanId, this.attachmentDescription});
LoanAttachments.fromJson(dynamic json) {
id = json['id'];
loanAttachmentTypeId = json['loanAttachmentTypeId'];
loanId = json['loanId'];
attachmentName = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
}
// LoanAttachments copyWith({
// num? id, // Parameter is now nullable
// String? name, // Parameter is now nullable
// String? originalName, // Parameter is now nullable
// }) =>
// LoanAttachments(
// id: id ?? this.id,
// name: name ?? this.name,
// originalName: originalName ?? this.originalName,
// );
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = id;
map['loanAttachmentTypeId'] = loanAttachmentTypeId;
map['attachmentName'] = attachmentName;
map['loanId'] = loanId;
map['attachmentDescription'] = attachmentDescription;
return map;
}
}

@ -1,14 +1,14 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/loan_module/models/loan_form_model.dart';
class LoanInstallationPullOutFormModel {
String? snNo;
DateTime? date;
Uint8List? signature;
List<LoanAttachments>? loanAttachment;
List<GenericAttachmentModel>? loanAttachment;
TimerModel? timerModel = TimerModel();
DateTime? startTime;
DateTime? endTime;
@ -32,13 +32,11 @@ class LoanInstallationPullOutFormModel {
});
Map<String, dynamic> toJson() {
//Need to check payload parm they need
return {
// 'snNo': snNo,
'serialNumber': snNo,
'installationDate': date?.toIso8601String(),
'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toLoanJson()).toList() : [],
"installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
@ -53,16 +51,11 @@ class LoanInstallationPullOutFormModel {
}
Map<String, dynamic> toInstallationJson() {
//Need to check payload parm they need
return {
// 'snNo': snNo,
'serialNumber': snNo,
'installationDate': date?.toIso8601String(),
// 'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toLoanJson()).toList() : [],
"installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
'totalHours': totalHours,
@ -74,15 +67,10 @@ class LoanInstallationPullOutFormModel {
}
Map<String, dynamic> toPulloutJson() {
//Need to check payload parm they need
return {
// 'snNo': snNo,
'serialNumber': snNo,
// 'installationDate': date?.toIso8601String(),
'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
// "installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toLoanJson()).toList() : [],
"pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),

@ -1,3 +1,4 @@
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/lookup.dart';
import 'loan_attachment_model.dart';
@ -34,7 +35,7 @@ class LoanRequestModel {
String? vendorRepName;
String? vendorContact;
String? vendorEmail;
List<LoanAttachmentModel>? loanAttachments;
List<GenericAttachmentModel>? loanAttachments;
int? loanStatusId;
String? loanStatusName;
int? loanStatusValue;
@ -154,11 +155,11 @@ class LoanRequestModel {
vendorRepName = json['vendorRepName'];
vendorContact = json['vendorContact'];
vendorEmail = json['vendorEmail'];
loanAttachments = <LoanAttachmentModel>[];
loanAttachments = <GenericAttachmentModel>[];
if (json['loanAttachments'] != null) {
loanAttachments = <LoanAttachmentModel>[];
loanAttachments = <GenericAttachmentModel>[];
json['loanAttachments'].forEach((v) {
loanAttachments!.add(new LoanAttachmentModel.fromJson(v));
loanAttachments!.add(GenericAttachmentModel.fromLoanDetailJson(v));
});
}
loanStatusId = json['loanStatusId'];
@ -222,8 +223,8 @@ class LoanRequestModel {
data['vendorRepName'] = this.vendorRepName;
data['vendorContact'] = this.vendorContact;
data['vendorEmail'] = this.vendorEmail;
if (this.loanAttachments != null) {
data['loanAttachments'] = this.loanAttachments!.map((v) => v.toJson()).toList();
if (loanAttachments != null) {
data['loanAttachments'] = loanAttachments!.map((v) => v.toLoanDetailJson()).toList();
}
data['loanStatusId'] = this.loanStatusId;
data['loanStatusName'] = this.loanStatusName;

@ -627,7 +627,7 @@ class _CreateLoanRequestPageState extends State<CreateLoanRequestPage> with Tick
_loanFormModel.loanAttachment = [];
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_loanFormModel.loanAttachment?.add(LoanAttachments(id: 0, attachmentName: fileName, loanId: 0));
_loanFormModel.loanAttachment?.add(GenericAttachmentModel(id: 0, name: fileName, moduleReferenceId: 0));
}
Utils.showLoading(context);
LoanProvider loanProvider = Provider.of<LoanProvider>(context, listen: false);

@ -209,7 +209,7 @@ class _InstallationFormViewState extends State<InstallationFormView> {
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formData.loanAttachment!.add(LoanAttachments(id: 0, attachmentName: fileName, loanId: widget.loanData?.id));
_formData.loanAttachment!.add(GenericAttachmentModel(id: 0, name: fileName, moduleReferenceId: widget.loanData?.id, documentType: item.documentType));
}
Utils.showLoading(context);
_formData.loanStatusId = widget.loanData?.loanStatusValue;

@ -217,7 +217,7 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formData.loanAttachment!.add(LoanAttachments(id: 0, attachmentName: fileName, loanId: widget.loanData?.id));
_formData.loanAttachment!.add(GenericAttachmentModel(id: 0, name: fileName, moduleReferenceId: widget.loanData?.id));
}
Utils.showLoading(context);
LoanProvider loanProvider = Provider.of<LoanProvider>(context, listen: false);

@ -84,7 +84,7 @@ class InstallationDetailsView extends StatelessWidget {
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
8.height,
FilesList(showAsListView: true, images: loanData.loanAttachments?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
FilesList(showAsListView: true, images: loanData.loanAttachments?.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context, borderRadius: 20),

@ -6,6 +6,8 @@ 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/modules/loan_module/provider/loan_provider.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/loan_module/models/loan_attachment_model.dart';
@ -59,7 +61,7 @@ class _LoanEquipmentDetailPageState extends State<LoanEquipmentDetailPage> {
if (snapshot.connectionState == ConnectionState.waiting) return CircularProgressIndicator(color: AppColor.loadingColor(context)).center;
if (snapshot.data == null) return const NoDataFound().center;
List<LoanAttachmentModel> allAttachments = snapshot.data!.loanAttachments!;
List<GenericAttachmentModel> allAttachments = (snapshot.data!.loanAttachments ?? []).whereType<GenericAttachmentModel>().toList();
return Column(children: [
ListView(
@ -95,7 +97,7 @@ class _LoanEquipmentDetailPageState extends State<LoanEquipmentDetailPage> {
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context)

@ -72,7 +72,7 @@ class _UpdateDeliveryNotesState extends State<UpdateDeliveryNotes> {
deliveryNoteNumber: dataModel.deliveryNote);
if (dataModel.deliveryNoteAttachmentDto.isNotEmpty) {
_attachments.addAll(dataModel.deliveryNoteAttachmentDto.map((e) => GenericAttachmentModel(id: e.id, name: e.name)).toList());
_attachments.addAll(dataModel.deliveryNoteAttachmentDto.map((e) => GenericAttachmentModel(id: e.id, documentType: e.documentType, name: e.name)).toList());
}
//Need to Confirm this condition
// selectedItemList = dataModel.requestDetailDtos.where((item) => item.deliveredQuantity != null && item.deliveredQuantity! > 0).toList();
@ -211,8 +211,8 @@ class _UpdateDeliveryNotesState extends State<UpdateDeliveryNotes> {
AttachmentPicker(
label: 'Upload Attachment',
attachment: _attachments,
showAsListView: true,
buttonColor: AppColor.primary10,
// showAsListView: true,
onlyImages: false,
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
),
@ -331,7 +331,7 @@ class _UpdateDeliveryNotesState extends State<UpdateDeliveryNotes> {
try {
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
formModel.attachments.add(GenericAttachmentModel(id: item.id, name: fileName));
formModel.attachments.add(GenericAttachmentModel(id: item.id, name: fileName, documentType: item.documentType));
}
} catch (error) {
print(error);

@ -11,7 +11,6 @@ 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/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/update_system_internal_audit_page.dart';

@ -10,6 +10,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/models/generic_attachment_model.dart';
import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart';
import 'package:test_sa/models/ppm/ppm.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
@ -51,7 +52,11 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = [];
for (var item in ppmProvider.ppmPlanAttachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
ppmProvider.planPreventiveVisit?.preventiveVisitAttachments?.add(PreventiveVisitAttachments(id: item.id, attachmentName: fileName));
ppmProvider.planPreventiveVisit?.preventiveVisitAttachments?.add(GenericAttachmentModel(
id: item.id,
name: fileName,
documentType: item.documentType,
));
}
ppmProvider.planPreventiveVisit?.preventiveVisitTimers = ppmProvider.planPreventiveVisit?.preventiveVisitTimers ?? [];

@ -61,7 +61,7 @@ class _WoInfoFormState extends State<WoInfoForm> {
calculateWorkingTime();
if (widget.planPreventiveVisit.preventiveVisitAttachments != null && widget.planPreventiveVisit.preventiveVisitAttachments!.isNotEmpty) {
ppmProvider.ppmPlanAttachments = [];
ppmProvider.ppmPlanAttachments.addAll(widget.planPreventiveVisit.preventiveVisitAttachments!.map((e) => GenericAttachmentModel(id: e.id, name: e.attachmentName!)).toList());
ppmProvider.ppmPlanAttachments.addAll(widget.planPreventiveVisit.preventiveVisitAttachments!.whereType<GenericAttachmentModel>().map((e) => GenericAttachmentModel(id: e.id, name: e.name ?? '',documentType: e.documentType)).toList());
}
});
@ -350,6 +350,7 @@ class _WoInfoFormState extends State<WoInfoForm> {
16.height,
AttachmentPicker(
label: context.translation.attachments,
showAsListView: true,
attachment: ppmProvider.ppmPlanAttachments,
buttonColor: AppColor.black10,
onlyImages: false,

@ -74,10 +74,10 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
return;
}
_formKey.currentState!.save();
List<AssetTransferAttachment> attachement = [];
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(AssetTransferAttachment(id: item.id, attachmentName: fileName));
attachement.add(GenericAttachmentModel(id: item.id, name: fileName, documentType: item.documentType));
}
_transferModel.attachments = attachement;
@ -245,6 +245,7 @@ class _CreateDeviceTransferRequestState extends State<CreateDeviceTransferReques
23.height,
AttachmentPicker(
label: context.translation.attachImage,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,

@ -64,8 +64,8 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
if (snapshot.connectionState == ConnectionState.waiting) {
return const ALoading();
} else {
_model = snapshot.data as DeviceTransfer?;
_attachments = _model?.assetTransferAttachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? [];
_model = snapshot.data;
_attachments = _model?.assetTransferAttachments?.map((e) => File(e.name ?? '')).toList() ?? [];
return _model != null
? Form(
key: _formKey,
@ -121,7 +121,7 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: _model?.assetTransferAttachments?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
FilesList(images: _model?.assetTransferAttachments?.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
]
],
),

@ -116,11 +116,14 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
_formModel.assetTransferEngineerTimers = _formModel.receiverVisitTimers;
}
try {
_formModel.assetTransferAttachments ??= [];
List<GenericAttachmentModel> newAttachments = [];
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formModel.assetTransferAttachments!.add(AssetTransferAttachment(id: item.id, attachmentName: fileName));
_formModel.attachments = _formModel.assetTransferAttachments;
newAttachments.add(GenericAttachmentModel(id: item.id, documentType: item.documentType, name: fileName));
}
_formModel.assetTransferAttachments = [...?_formModel.assetTransferAttachments, ...newAttachments];
_formModel.attachments = _formModel.assetTransferAttachments;
} catch (error) {
print(error);
}
@ -204,7 +207,7 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
@override
void initState() {
_formModel.fromDetails(widget.model);
attachments = widget.model.assetTransferAttachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt()??0, name: e.attachmentName!)).toList() ?? [];
attachments = widget.model.assetTransferAttachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt()??0, name: e.name!)).toList() ?? [];
calculateWorkingTime();
super.initState();
}
@ -293,6 +296,7 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
8.height,
AttachmentPicker(
label: context.translation.attachFiles,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,

@ -3,14 +3,19 @@ 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/controllers/providers/api/gas_refill_provider.dart';
import 'package:test_sa/controllers/providers/api/gas_refill_comments.dart';
import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/cx_module/chat/chat_widget.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
@ -92,7 +97,7 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
return const ALoading();
} else if (snap.hasData) {
_model = snap.data as GasRefillModel;
_attachments = _model.gasRefillAttachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? [];
_attachments = _model.gasRefillAttachments?.whereType<GenericAttachmentModel>().map((e) => File(e.name ?? '')).toList() ?? [];
isDataUpdated = false;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -233,7 +238,7 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: _model.gasRefillAttachments?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
FilesList(images: _model.gasRefillAttachments?.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((e) => URLs.getFileUrl(e.name!) ?? '').toList() ?? []),
],
],
).expanded,

@ -216,6 +216,7 @@ class _GasRefillRequestFormState extends State<GasRefillRequestForm> {
8.height,
AttachmentPicker(
label: context.translation.attachFiles,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
@ -238,7 +239,7 @@ class _GasRefillRequestFormState extends State<GasRefillRequestForm> {
_gasModel.gasRefillAttachments = [];
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_gasModel.gasRefillAttachments?.add(GasRefillAttachments(id: item.id, gasRefillId: _gasModel.id ?? 0, attachmentName: fileName));
_gasModel.gasRefillAttachments?.add(GenericAttachmentModel(id: item.id, moduleReferenceId: _gasModel.id ?? 0, name: fileName, documentType: item.documentType));
}
await _gasRefillProvider?.addGasRefillRequest(
context: context,

@ -86,7 +86,7 @@ class _UpdateGasRefillRequestState extends State<UpdateGasRefillRequest> {
} catch (ex) {}
}
if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) {
_attachments.addAll(_formModel.gasRefillAttachments!.map((e) => GenericAttachmentModel(id: e.id, name: e.attachmentName!)).toList());
_attachments.addAll(_formModel.gasRefillAttachments!.whereType<GenericAttachmentModel>().where((e) => e.id != null && e.name != null).map((e) => GenericAttachmentModel(id: e.id, name: e.name, documentType: e.documentType)).toList());
}
}
@ -182,7 +182,7 @@ class _UpdateGasRefillRequestState extends State<UpdateGasRefillRequest> {
_formModel.gasRefillAttachments = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formModel.gasRefillAttachments?.add(GasRefillAttachments(id: item.id, gasRefillId: _formModel.id ?? 0, attachmentName: fileName));
_formModel.gasRefillAttachments?.add(GenericAttachmentModel(id: item.id, moduleReferenceId: _formModel.id ?? 0, name: fileName, documentType: item.documentType));
}
await _gasRefillProvider?.updateGasRefill(status: status, model: _formModel).then((success) {
@ -292,6 +292,7 @@ class _UpdateGasRefillRequestState extends State<UpdateGasRefillRequest> {
AttachmentPicker(
label: context.translation.attachFiles,
attachment: _attachments,
showAsListView: true,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),

@ -44,7 +44,7 @@ class CreateTaskView extends StatefulWidget {
}
class _CreateTaskViewState extends State<CreateTaskView> with TickerProviderStateMixin {
final List<GenericAttachmentModel> attachments = [];
List<GenericAttachmentModel> attachments = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
List<Asset> _deviceList = [];
@ -117,13 +117,9 @@ class _CreateTaskViewState extends State<CreateTaskView> with TickerProviderStat
label: context.translation.attachImage,
attachment: attachments,
buttonColor: AppColor.black10,
showAsListView: true,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
//verify this if not required delete this ..
onChange: (attachments) {
attachments = attachments;
setState(() {});
},
),
],
).toShadowContainer(context).paddingAll(16),
@ -457,7 +453,7 @@ class _CreateTaskViewState extends State<CreateTaskView> with TickerProviderStat
}
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_addTaskModel?.attachments?.add(TaskJobAttachment(id: item.id, name: fileName));
_addTaskModel?.attachments?.add(GenericAttachmentModel(id: item.id, name: fileName, documentType: item.documentType));
}
TaskRequestProvider taskRequestProvider = Provider.of<TaskRequestProvider>(context, listen: false);
await taskRequestProvider.addTask(context: context, task: _addTaskModel!);

@ -9,6 +9,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/all_requests_and_count_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/new_models/task_request/task_request_model.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
@ -159,7 +160,7 @@ class _TaskRequestDetailsViewState extends State<TaskRequestDetailsView> {
if (taskProvider.taskRequestModel?.taskJobAttachments?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: taskProvider.taskRequestModel!.taskJobAttachments!.map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()),
FilesList(images: taskProvider.taskRequestModel!.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()),
],
buildTechnicalComments(taskModel: taskModel),
],

@ -63,7 +63,7 @@ class _UpdateTaskRequestState extends State<UpdateTaskRequest> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
List<GenericAttachmentModel> attachments = [];
List<TaskJobAttachment> otherAttachments = [];
List<GenericAttachmentModel> otherAttachments = [];
bool installationType = true;
String comments = '';
List<TimerHistoryModel> timerList = [];
@ -87,8 +87,8 @@ class _UpdateTaskRequestState extends State<UpdateTaskRequest> {
_taskProvider?.refresh();
calculateWorkingTime(helperModel: taskModel!);
if (taskModel.taskJobAttachments != null) {
attachments = taskModel.taskJobAttachments!.where((e) => e.createdBy == _userProvider.user?.userID).map((e) => GenericAttachmentModel(id: e.id, name: e.name ?? '')).toList();
otherAttachments = taskModel.taskJobAttachments?.where((e) => e.createdBy != _userProvider.user?.userID).toList() ?? [];
attachments = taskModel.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.createdBy == _userProvider.user?.userID && e.id != null).map((e) => GenericAttachmentModel(id: e.id, name: e.name ?? '',documentType: e.documentType)).toList();
otherAttachments = taskModel.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.createdBy != _userProvider.user?.userID).toList();
}
}
@ -191,6 +191,7 @@ class _UpdateTaskRequestState extends State<UpdateTaskRequest> {
20.height,
AttachmentPicker(
label: context.translation.attachFiles,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
@ -254,13 +255,13 @@ class _UpdateTaskRequestState extends State<UpdateTaskRequest> {
if (validate(model: taskModel)) {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
List<TaskJobAttachment> taskAttachment = [];
List<GenericAttachmentModel> taskAttachment = [];
if (otherAttachments.isNotEmpty) {
taskAttachment.addAll(otherAttachments);
}
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
taskAttachment.add(TaskJobAttachment(id: item.id, name: fileName));
taskAttachment.add(GenericAttachmentModel(id: item.id, name: fileName,documentType: item.documentType));
}
taskModel.taskJobAttachments = taskAttachment;
taskModel.taskJobActivityEngineerTimers = [];

@ -516,6 +516,7 @@ class _CreateTRAFRequestPageState extends State<CreateTRAFRequestPage> {
12.height,
AttachmentPicker(
label: context.translation.attachFiles,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
@ -622,7 +623,7 @@ class _CreateTRAFRequestPageState extends State<CreateTRAFRequestPage> {
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
trafRequest?.attachments!.add(
Attachments(id: 0, trafId: 0, attachmentName: fileName),
GenericAttachmentModel(id: 0, moduleReferenceId: 0, name: fileName, documentType: item.documentType),
);
}

@ -10,6 +10,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/enums/user_types.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/traf_module/traf_request_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
@ -63,7 +64,7 @@ class _TrafRequestDetailPageState extends State<TrafRequestDetailPage> {
if (isLoading) return const ALoading();
TrafRequestProvider trafProvider = Provider.of<TrafRequestProvider>(context, listen: false);
if (trafProvider.trafRequestDataModel?.attachments != null) {
_attachments = trafProvider.trafRequestDataModel!.attachments!.map((e) => File(URLs.getFileUrl(e.attachmentName ?? '') ?? '')).toList();
_attachments = trafProvider.trafRequestDataModel!.attachments!.whereType<GenericAttachmentModel>().map((e) => File(URLs.getFileUrl(e.name ?? '') ?? '')).toList();
}
return trafProvider.trafRequestDataModel == null
? const NoDataFound().center

@ -1,3 +1,6 @@
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
class TrafRequestModel {
List<TrafRequestDataModel>? trafRequestDataModel;
int? totalRows;
@ -92,7 +95,7 @@ class TrafRequestDataModel {
String? isCombinationName;
String? usedWithCombination;
String? comment;
List<Attachments>? attachments;
List<GenericAttachmentModel>? attachments;
bool? isFromMobile;
int? isBudgetId;
String? isBudgetName;
@ -309,9 +312,9 @@ class TrafRequestDataModel {
comment = json['comment'];
isFromMobile = json['isFromMobile'];
if (json['attachments'] != null) {
attachments = <Attachments>[];
attachments = <GenericAttachmentModel>[];
json['attachments'].forEach((v) {
attachments!.add(new Attachments.fromJson(v));
attachments!.add(GenericAttachmentModel.fromTrafJson(v));
});
}
isBudgetId = json['isBudgetId'];
@ -426,8 +429,8 @@ class TrafRequestDataModel {
data['usedWithCombination'] = this.usedWithCombination;
data['comment'] = this.comment;
data['isFromMobile'] = this.isFromMobile;
if (this.attachments != null) {
data['attachments'] = this.attachments!.map((v) => v.toJson()).toList();
if (attachments != null) {
data['attachments'] = attachments!.map((v) => v.toTrafJson()).toList();
} else {
data['attachments'] = [];
}
@ -536,7 +539,7 @@ class TrafRequestDataModel {
data['isBudgetId'] = isBudgetId;
data['attachments'] =
attachments?.map((v) => v.toJson()).toList() ?? [];
attachments?.map((v) => v.toTrafJson() ?? {}).toList() ?? [];
return data;
}
@ -632,25 +635,28 @@ class Departments {
return data;
}
}
class Attachments {
int? id;
int? trafId;
String? attachmentName;
Attachments({this.id, this.trafId, this.attachmentName});
Attachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
trafId = json['trafId'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['trafId'] = this.trafId;
data['attachmentName'] = this.attachmentName;
return data;
}
}
//TODO need to remove this
// class Attachments {
// int? id;
// int? trafId;
// String? attachmentName;
// Lookup ? documentType;
//
// Attachments({this.id, this.trafId, this.attachmentName,this.documentType});
//
// Attachments.fromJson(Map<String, dynamic> json) {
// id = json['id'];
// trafId = json['trafId'];
// attachmentName = json['attachmentName'];
// documentType = json['documentType'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['id'] = this.id;
// data['trafId'] = this.trafId;
// data['attachmentName'] = this.attachmentName;
// data['documentTypeId'] = this.documentType?.id;
// return data;
// }
// }

@ -58,7 +58,7 @@ class _UpdateTrafRequestPageState extends State<UpdateTrafRequestPage> {
Provider.of<RecommendationLookupProvider>(context, listen: false).reset();
trafRequestProvider = Provider.of<TrafRequestProvider>(context, listen: false);
trafRequest = trafRequestProvider.trafRequestDataModel!;
attachments = trafRequest.attachments?.map((item) => GenericAttachmentModel(id: item.id, name: item.attachmentName)).toList() ?? [];
attachments = trafRequest.attachments?.whereType<GenericAttachmentModel>().map((item) => GenericAttachmentModel(id: item.id, name: item.name ?? '')).toList() ?? [];
}
@override
@ -212,6 +212,7 @@ class _UpdateTrafRequestPageState extends State<UpdateTrafRequestPage> {
12.height,
AttachmentPicker(
label: context.translation.attachFiles,
showAsListView: true,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
@ -233,7 +234,7 @@ class _UpdateTrafRequestPageState extends State<UpdateTrafRequestPage> {
for (var item in attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
trafRequest.attachments!.add(
Attachments(id: item.id, trafId: item.id, attachmentName: fileName),
GenericAttachmentModel(id: item.id, moduleReferenceId: item.id, name: fileName, documentType: item.documentType),
);
}
}

@ -1,29 +1,20 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/devices_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/device/asset_by_id_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/equipment/asset_details_view.dart';
import 'package:test_sa/views/widgets/equipment/asset_document_history_view.dart';
import 'package:test_sa/views/widgets/equipment/asset_image_upload_page.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/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/failed_loading.dart';
import '../../../new_views/app_style/app_color.dart';
import '../requests/request_status.dart';
class AssetDetailPage extends StatefulWidget {
static const String id = "/asset-details";
@ -35,28 +26,11 @@ class AssetDetailPage extends StatefulWidget {
}
}
class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
class _AssetDetailPageState extends State<AssetDetailPage> {
int? assetId;
AssetProvider? _assetProvider;
AssetByIdModel? assetModel;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 1400),
vsync: this,
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
List<GenericAttachmentModel> attachments = [];
@override
Widget build(BuildContext context) {
@ -81,311 +55,53 @@ class _AssetDetailPageState extends State<AssetDetailPage> with SingleTickerProv
} else if (snapshot.hasData) {}
if (snapshot.hasData) {
assetModel = snapshot.data!;
attachments = assetModel?.assetAttachments
?.map((attachment) => GenericAttachmentModel(
id: attachment.id,
name: attachment.attachmentName,
originalName: attachment.originalName,
))
.toList() ??
[];
if (!_animationController.isCompleted) {
_animationController.forward(from: 0.0);
}
// Image animation - fade in with scale
final imageAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.4, curve: Curves.easeOut),
),
);
final imageScaleAnimation = Tween<double>(begin: 0.92, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.4, curve: Curves.easeOutCubic),
),
);
// Status label animation
final statusAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.15, 0.5, curve: Curves.easeOut),
),
);
final statusSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.2),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.15, 0.5, curve: Curves.easeOutCubic),
),
);
// Header animation
final headerAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.25, 0.6, curve: Curves.easeOut),
),
);
final headerSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.2),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.25, 0.6, curve: Curves.easeOutCubic),
),
);
// Details row animation
final detailsAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.35, 0.75, curve: Curves.easeOut),
),
);
final detailsSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.15),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.35, 0.75, curve: Curves.easeOutCubic),
),
);
// Dates section animation
final datesAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.50, 0.9, curve: Curves.easeOut),
),
);
final datesSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.15),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.50, 0.9, curve: Curves.easeOutCubic),
),
);
// Description animation (if exists)
final descAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.65, 1.0, curve: Curves.easeOut),
),
);
final descSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.1),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.65, 1.0, curve: Curves.easeOutCubic),
),
);
final attachmentAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.80, 1.0, curve: Curves.easeOut),
),
);
final attachmentSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.1),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.80, 1.0, curve: Curves.easeOutCubic),
),
);
return Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
return DefaultTabController(
length: 2,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 16.toScreenWidth, right: 16.toScreenWidth, top: 12.toScreenHeight),
decoration: BoxDecoration(
color: AppColor.tabBarBackground(context),
border: Border.all(color: AppColor.tabBarBorder(context)),
borderRadius: BorderRadius.circular(20),
),
child: TabBar(
padding: EdgeInsets.symmetric(vertical: 6.toScreenHeight, horizontal: 6.toScreenWidth),
labelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelColor: context.isDark ? AppColor.neutral30 : AppColor.black20,
unselectedLabelStyle: AppTextStyles.bodyText,
labelStyle: AppTextStyles.bodyText,
indicatorPadding: EdgeInsets.zero,
indicatorSize: TabBarIndicatorSize.tab,
dividerColor: Colors.transparent,
overlayColor: WidgetStateProperty.all(Colors.transparent),
indicator: BoxDecoration(
color: AppColor.background(context),
borderRadius: BorderRadius.circular(15),
boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.03), blurRadius: 5, offset: const Offset(0, 0), spreadRadius: 0)]),
onTap: (index) {
// setState(() {});
},
tabs: [
Tab(text: context.translation.assetDetails, height: 57.toScreenHeight),
Tab(text: 'Document history'.addTranslation, height: 57.toScreenHeight),
],
),
),
12.height,
TabBarView(
children: [
// Animated image
FadeTransition(
opacity: imageAnimation,
child: ScaleTransition(
scale: imageScaleAnimation,
child: AspectRatio(
aspectRatio: 159 / 94,
child: Container(
width: 95,
height: 95,
decoration: ShapeDecoration(
color: AppColor.neutral30,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(assetModel?.assetPhoto != null ? URLs.getFileUrl(assetModel!.assetPhoto!)! : "https://www.lasteelcraft.com/images/no-image-available.png"),
)),
),
),
),
),
6.height,
// Animated content column
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Status label with animation
if (assetModel?.commissioningStatus != null)
FadeTransition(
opacity: statusAnimation,
child: SlideTransition(
position: statusSlideAnimation,
child: StatusLabel(
label: assetModel!.commissioningStatus!.name,
textColor: AppColor.getRequestStatusTextColorByName(context, assetModel!.commissioningStatus!.name!),
backgroundColor: AppColor.getRequestStatusColorByName(context, assetModel!.commissioningStatus!.name!),
),
),
),
if (assetModel?.commissioningStatus != null) 8.height,
// Header with animation
FadeTransition(
opacity: headerAnimation,
child: SlideTransition(
position: headerSlideAnimation,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 2,
children: [
InfoHeader16Widget(assetModel?.modelDefinition?.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"),
if (context.userProvider.isEngineer && !(assetModel?.hasTrainingImageData ?? true))
const InfoTextLabelWidget(label: '*Upload Images for this asset', color: AppColor.red30),
],
),
),
),
8.height,
// Details row with animation
FadeTransition(
opacity: detailsAnimation,
child: SlideTransition(
position: detailsSlideAnimation,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.assetNo, value: assetModel!.multiAssets!.first.assetNumber, showEmptyValue: true, copyValue: true),
InfoTextWidget(label: context.translation.modelName, value: assetModel!.modelDefinition!.modelName, showEmptyValue: true),
InfoTextWidget(label: context.translation.supplier, value: assetModel!.supplier?.suppliername, showEmptyValue: true),
InfoTextWidget(label: context.translation.manufacture, value: assetModel!.modelDefinition!.manufacturerName, showEmptyValue: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.snNo, value: assetModel!.multiAssets!.first.assetSerialNo, showEmptyValue: true),
InfoTextWidget(label: context.translation.site, value: assetModel!.site?.custName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.building, value: assetModel!.building?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.floor, value: assetModel!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.md, value: assetModel!.department?.departmentName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.room, value: assetModel!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
],
).expanded,
],
),
),
),
// 8.height,
// Divider with animation
FadeTransition(
opacity: datesAnimation,
child: const Divider().defaultStyle(context),
),
// 8.height,
// Dates section with animation
FadeTransition(
opacity: datesAnimation,
child: SlideTransition(
position: datesSlideAnimation,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.installationDate, value: assetModel?.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.nextPmDate, value: assetModel?.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.lastPmDate, value: assetModel?.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
],
),
),
),
// Description with animation (if exists)
if ((assetModel?.modelDefinition?.assetDescription ?? "").isNotEmpty) ...[
// 8.height,
FadeTransition(
opacity: descAnimation,
child: const Divider().defaultStyle(context),
),
FadeTransition(
opacity: descAnimation,
child: SlideTransition(
position: descSlideAnimation,
child: InfoTextWidget(label: assetModel!.modelDefinition!.assetDescription!, showEmptyValue: true, isMsg: true),
),
),
],
if (attachments.isNotEmpty) ...[
// 8.height,
FadeTransition(
opacity: attachmentAnimation,
child: const Divider().defaultStyle(context),
),
FadeTransition(
opacity: attachmentAnimation,
child: SlideTransition(
position: attachmentSlideAnimation,
child: FilesList(images: attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
),
),
]
],
AssetDetailsView(
assetModel: assetModel!,
onUpload: _upload,
),
const AssetDocumentHistoryView(),
],
).toShadowContainer(context),
).expanded,
if (context.userProvider.isEngineer && !(assetModel!.hasTrainingImageData ?? true))
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: "Upload Images",
onPressed: _upload,
),
),
],
).expanded,
],
),
);
}
return const Center(child: ALoading());

@ -0,0 +1,346 @@
import 'package:flutter/material.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset_by_id_model.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class AssetDetailsView extends StatefulWidget {
final AssetByIdModel assetModel;
final VoidCallback onUpload;
const AssetDetailsView({
Key? key,
required this.assetModel,
required this.onUpload,
}) : super(key: key);
@override
State<AssetDetailsView> createState() => _AssetDetailsViewState();
}
class _AssetDetailsViewState extends State<AssetDetailsView> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
List<GenericAttachmentModel> attachments = [];
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 1400),
vsync: this,
);
attachments = widget.assetModel.assetAttachments?.whereType<GenericAttachmentModel>().toList() ?? [];
_animationController.forward(from: 0.0);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Image animation - fade in with scale
final imageAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.4, curve: Curves.easeOut),
),
);
final imageScaleAnimation = Tween<double>(begin: 0.92, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.4, curve: Curves.easeOutCubic),
),
);
// Status label animation
final statusAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.15, 0.5, curve: Curves.easeOut),
),
);
final statusSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.2),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.15, 0.5, curve: Curves.easeOutCubic),
),
);
// Header animation
final headerAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.25, 0.6, curve: Curves.easeOut),
),
);
final headerSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.2),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.25, 0.6, curve: Curves.easeOutCubic),
),
);
// Details row animation
final detailsAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.35, 0.75, curve: Curves.easeOut),
),
);
final detailsSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.15),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.35, 0.75, curve: Curves.easeOutCubic),
),
);
// Dates section animation
final datesAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.50, 0.9, curve: Curves.easeOut),
),
);
final datesSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.15),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.50, 0.9, curve: Curves.easeOutCubic),
),
);
// Description animation (if exists)
final descAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.65, 1.0, curve: Curves.easeOut),
),
);
final descSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.1),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.65, 1.0, curve: Curves.easeOutCubic),
),
);
final attachmentAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.80, 1.0, curve: Curves.easeOut),
),
);
final attachmentSlideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.1),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.80, 1.0, curve: Curves.easeOutCubic),
),
);
return Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Animated image
FadeTransition(
opacity: imageAnimation,
child: ScaleTransition(
scale: imageScaleAnimation,
child: AspectRatio(
aspectRatio: 159 / 94,
child: Container(
width: 95,
height: 95,
decoration: ShapeDecoration(
color: AppColor.neutral30,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(widget.assetModel.assetPhoto != null ? URLs.getFileUrl(widget.assetModel.assetPhoto!)! : "https://www.lasteelcraft.com/images/no-image-available.png"),
)),
),
),
),
),
6.height,
// Animated content column
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Status label with animation
if (widget.assetModel.commissioningStatus != null)
FadeTransition(
opacity: statusAnimation,
child: SlideTransition(
position: statusSlideAnimation,
child: StatusLabel(
label: widget.assetModel.commissioningStatus!.name,
textColor: AppColor.getRequestStatusTextColorByName(context, widget.assetModel.commissioningStatus!.name!),
backgroundColor: AppColor.getRequestStatusColorByName(context, widget.assetModel.commissioningStatus!.name!),
),
),
),
if (widget.assetModel.commissioningStatus != null) 8.height,
// Header with animation
FadeTransition(
opacity: headerAnimation,
child: SlideTransition(
position: headerSlideAnimation,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 2,
children: [
InfoHeader16Widget(widget.assetModel.modelDefinition?.assetName?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"),
if (context.userProvider.isEngineer && !(widget.assetModel.hasTrainingImageData ?? true))
const InfoTextLabelWidget(label: '*Upload Images for this asset', color: AppColor.red30),
],
),
),
),
8.height,
// Details row with animation
FadeTransition(
opacity: detailsAnimation,
child: SlideTransition(
position: detailsSlideAnimation,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.assetNo, value: widget.assetModel.multiAssets!.first.assetNumber, showEmptyValue: true, copyValue: true),
InfoTextWidget(label: context.translation.modelName, value: widget.assetModel.modelDefinition!.modelName, showEmptyValue: true),
InfoTextWidget(label: context.translation.supplier, value: widget.assetModel.supplier?.suppliername, showEmptyValue: true),
InfoTextWidget(label: context.translation.manufacture, value: widget.assetModel.modelDefinition!.manufacturerName, showEmptyValue: true),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.snNo, value: widget.assetModel.multiAssets!.first.assetSerialNo, showEmptyValue: true),
InfoTextWidget(label: context.translation.site, value: widget.assetModel.site?.custName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.building, value: widget.assetModel.building?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.floor, value: widget.assetModel.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.md, value: widget.assetModel.department?.departmentName?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
InfoTextWidget(label: context.translation.room, value: widget.assetModel.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, showEmptyValue: true),
],
).expanded,
],
),
),
),
// Divider with animation
FadeTransition(
opacity: datesAnimation,
child: const Divider().defaultStyle(context),
),
// Dates section with animation
FadeTransition(
opacity: datesAnimation,
child: SlideTransition(
position: datesSlideAnimation,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InfoTextWidget(label: context.translation.installationDate, value: widget.assetModel.installationDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.nextPmDate, value: widget.assetModel.nextPMDate?.toAssetDetailsFormat, showEmptyValue: true),
InfoTextWidget(label: context.translation.lastPmDate, value: widget.assetModel.lastPMDate?.toAssetDetailsFormat, showEmptyValue: true),
],
),
),
),
// Description with animation (if exists)
if ((widget.assetModel.modelDefinition?.assetDescription ?? "").isNotEmpty) ...[
FadeTransition(
opacity: descAnimation,
child: const Divider().defaultStyle(context),
),
FadeTransition(
opacity: descAnimation,
child: SlideTransition(
position: descSlideAnimation,
child: InfoTextWidget(label: widget.assetModel.modelDefinition!.assetDescription!, showEmptyValue: true, isMsg: true),
),
),
],
if (attachments.isNotEmpty) ...[
FadeTransition(
opacity: attachmentAnimation,
child: const Divider().defaultStyle(context),
),
FadeTransition(
opacity: attachmentAnimation,
child: SlideTransition(
position: attachmentSlideAnimation,
child: FilesList(images: attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
),
),
]
],
),
],
).toShadowContainer(context),
).expanded,
if (context.userProvider.isEngineer && !(widget.assetModel.hasTrainingImageData ?? true))
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: "Upload Images",
onPressed: widget.onUpload,
),
),
],
);
}
}

@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
class AssetDocumentHistoryView extends StatelessWidget {
const AssetDocumentHistoryView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final List<String> dummyDocuments = [
'https://picsum.photos/200/300?random=1',
'https://picsum.photos/200/300?random=2',
'https://picsum.photos/200/300?random=3',
'https://picsum.photos/200/300?random=4',
'https://picsum.photos/200/300?random=5',
];
return SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
child: FilesList(
showAsListView: true,
// itemGap: 12.toScreenHeight,
showDownloadButton: true,
images: dummyDocuments,
).toShadowContainer(context),
);
}
}

@ -112,6 +112,7 @@ class _AssetImageUploadPageState extends State<AssetImageUploadPage> {
attachment: trainingImageData.additionalImages!,
buttonColor: AppColor.black10,
onlyImages: true,
showAsListView: true,
pickMultiple: true,
// showAsGrid: true,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
@ -164,6 +165,7 @@ class _AssetImageUploadPageState extends State<AssetImageUploadPage> {
child: AttachmentPicker(
label: "",
pickerTitle: title,
showAsListView:true,
onlyImages: true,
checkQuality: true,
enabled: attachment == null,

@ -10,8 +10,8 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/views/widgets/loaders/image_loader.dart';
import 'package:url_launcher/url_launcher.dart';
@ -20,15 +20,18 @@ class FilesList extends StatelessWidget {
final List<String> types;
final EdgeInsets? padding;
final bool showAsListView;
final bool showDownloadButton;
final double? itemGap;
const FilesList({Key? key, this.images = const <String>[], this.types = const <String>[], this.padding, this.showAsListView = false}) : super(key: key);
const FilesList({Key? key, this.images = const <String>[], this.types = const <String>[], this.padding, this.showAsListView = false, this.showDownloadButton = false, this.itemGap})
: super(key: key);
@override
Widget build(BuildContext context) {
return showAsListView
? ListView.separated(
shrinkWrap: true,
padding: const EdgeInsets.only(top: 8),
padding: padding ?? const EdgeInsets.only(top: 8),
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cxt, itemIndex) {
if (!images[itemIndex].contains(".")) {
@ -105,14 +108,25 @@ class FilesList extends StatelessWidget {
),
),
],
).expanded
).expanded,
showDownloadButton
? 'download'.toSvgAsset().onPress(() async {
if (Utils.isLocalFile(images[itemIndex])) {
await OpenFile.open(images[itemIndex]);
} else {
await Utils.downloadFile(images[itemIndex], autoOpen: true, showToast: true);
}
})
: const SizedBox.shrink()
],
);
},
separatorBuilder: (cxt, index) => 8.height,
separatorBuilder: (cxt, index) => SizedBox(
height: itemGap ?? 8.toScreenHeight,
),
itemCount: images.length)
: GridView.builder(
padding: const EdgeInsets.only(top: 8, bottom: 8),
padding: padding ?? const EdgeInsets.only(top: 8, bottom: 8),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6, mainAxisSpacing: 8, crossAxisSpacing: 8),

@ -1,18 +1,19 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_blur_detection/image_blur_detection.dart';
import 'package:image_picker/image_picker.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.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/provider/attachment_type_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/views/widgets/item_views/info_header_widget.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import '../../../new_views/common_widgets/app_dashed_button.dart';
import 'multi_image_picker_item.dart';
@ -62,12 +63,13 @@ class AttachmentPicker extends StatefulWidget {
this.pickerTitle = "Attach File",
this.error = false,
this.buttonHeight,
required this.showAsListView,
this.buttonIcon,
this.enabled = true,
this.onlyImages = false,
this.onChange,
this.documentType,
this.showAsListView = false,
// this.showAsListView = false,
this.pickMultiple = false,
this.checkQuality = false,
this.child,
@ -80,6 +82,7 @@ class AttachmentPicker extends StatefulWidget {
class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
Lookup? documentLookup;
@override
void initState() {
@ -123,7 +126,7 @@ class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerPr
file: image,
showAsListView: widget.showAsListView,
enabled: widget.enabled,
documentType: widget.attachment[index].documentTypeId?.name,
documentType: widget.attachment[index].documentType?.name,
onRemoveTap: (image) {
if (!widget.enabled) {
return;
@ -173,7 +176,7 @@ class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerPr
);
if (result != null) {
for (var path in result.paths) {
widget.attachment.add(GenericAttachmentModel(id: 0, name: File(path!).path, documentTypeId: widget.documentType));
widget.attachment.add(GenericAttachmentModel(id: 0, name: File(path!).path, documentType: documentLookup));
}
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
@ -206,111 +209,151 @@ class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerPr
}
onFilePicker(bool checkQuality) async {
// Reset and restart animation for bottom sheet
_animationController.reset();
_animationController.forward();
documentLookup = null;
ImageSource? source = await showModalBottomSheet<ImageSource>(
context: context,
builder: (BuildContext context) {
Widget listCard({required String icon, required String label, required VoidCallback onTap}) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.background(context),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColor.borderColor(context), width: 2),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
icon.toSvgAsset(width: 24, height: 24, color: AppColor.icon2Color(context)),
label.bodyText2(context).custom(color: AppColor.labelTextStyleColor(context), fontSize: context.isTablet() ? 10.toScreenWidth : null),
],
),
).onPress(onTap);
}
return StatefulBuilder(
builder: (BuildContext context, StateSetter setModalState) {
Widget listCard({required String icon, required String label, required VoidCallback onTap}) {
bool isEnabled = documentLookup != null;
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isEnabled ? AppColor.background(context) : AppColor.tabBarBackground(context),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColor.borderColor(context), width: 2),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
icon.toSvgAsset(width: 24, height: 24, color: isEnabled ? AppColor.icon2Color(context) : AppColor.icon2Color(context).withOpacity(0.4)),
label.bodyText2(context).custom(
color: isEnabled ? AppColor.labelTextStyleColor(context) : AppColor.labelTextStyleColor(context).withOpacity(0.4), fontSize: context.isTablet() ? 10.toScreenWidth : null),
],
),
).onPress(() {
if (!isEnabled) return;
onTap();
});
}
List<Widget> listItems = [
listCard(
icon: 'camera_icon',
label: '${context.translation.open}\n${context.translation.camera}',
onTap: () {
Navigator.of(context).pop(ImageSource.camera);
},
),
listCard(
icon: 'gallery_icon',
label: '${context.translation.open}\n${context.translation.gallery}',
onTap: () {
Navigator.of(context).pop(ImageSource.gallery);
},
),
listCard(
icon: 'file_icon',
label: '${context.translation.open}\n${context.translation.files}',
onTap: () async {
await fromFilePicker();
Navigator.pop(context);
},
),
];
List<Widget> listItems = [
listCard(
icon: 'camera_icon',
label: '${context.translation.open}\n${context.translation.camera}',
onTap: () {
Navigator.of(context).pop(ImageSource.camera);
},
),
listCard(
icon: 'gallery_icon',
label: '${context.translation.open}\n${context.translation.gallery}',
onTap: () {
Navigator.of(context).pop(ImageSource.gallery);
},
),
listCard(
icon: 'file_icon',
label: '${context.translation.open}\n${context.translation.files}',
onTap: () async {
await fromFilePicker();
Navigator.pop(context);
},
),
];
return SafeArea(
top: false,
child: Container(
width: double.infinity,
color: AppColor.bottomSheetColor(context),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.pickerTitle.heading4(context),
GridView.builder(
padding: const EdgeInsets.only(top: 16, bottom: 0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 16, mainAxisSpacing: 16),
itemCount: listItems.length,
itemBuilder: (context, index) {
// Calculate staggered animation delay
final delay = index * 0.08;
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOut,
),
return SafeArea(
top: false,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: AppColor.bottomSheetColor(context),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30),
),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(alignment: AlignmentDirectional.center,
child: Container(
width: 40.toScreenWidth,
height: 5.toScreenHeight,
decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)),
),
);
),
8.height,
InfoHeader16Widget(widget.pickerTitle),
8.height,
SingleItemDropDownMenu<Lookup, AttachmentTypeLookupProviderLatest>(
context: context,
height: 56.toScreenHeight,
title: "Document Type",
initialValue: documentLookup,
showShadow: false,
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
documentLookup = value;
setModalState(() {});
},
),
if (documentLookup == null) ...[
4.height,
const InfoTextLabelWidget(label: 'Please Select Document Type before picking file', color: AppColor.red30),
],
GridView.builder(
padding: const EdgeInsets.only(top: 16, bottom: 0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 16, mainAxisSpacing: 16),
itemCount: listItems.length,
itemBuilder: (context, index) {
final delay = index * 0.08;
final animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOut,
),
),
);
final slideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.3),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOutCubic,
),
),
);
final slideAnimation = Tween<Offset>(
begin: const Offset(0.0, 0.3),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: _animationController,
curve: Interval(
delay.clamp(0.0, 0.8),
(delay + 0.3).clamp(0.0, 1.0),
curve: Curves.easeOutCubic,
),
),
);
return FadeTransition(
opacity: animation,
child: SlideTransition(position: slideAnimation, child: listItems[index]),
);
},
return FadeTransition(
opacity: animation,
child: SlideTransition(position: slideAnimation, child: listItems[index]),
);
},
),
],
),
],
),
),
),
);
},
);
},
);
@ -321,7 +364,8 @@ class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerPr
if (pickedFiles.isNotEmpty) {
pickedFiles.forEach((pickedFile) {
File fileImage = File(pickedFile.path);
widget.attachment.add(GenericAttachmentModel(id: 0, name: fileImage.path, documentTypeId: widget.documentType));
widget.attachment.add(GenericAttachmentModel(id: 0, name: fileImage.path, documentType: documentLookup));
});
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
@ -348,13 +392,11 @@ class _AttachmentPickerState extends State<AttachmentPicker> with SingleTickerPr
}
}
widget.attachment.add(GenericAttachmentModel(id: 0, name: fileImage.path, documentTypeId: widget.documentType));
widget.attachment.add(GenericAttachmentModel(id: 0, name: fileImage.path, documentType: documentLookup));
if (widget.onChange != null) {
widget.onChange!(widget.attachment);
}
setState(() {});
}
// setState(() {});
}
}

Loading…
Cancel
Save