Document library CR completed ready for test

main_production_attahment_type
WaseemAbbasi22 2 months ago
parent 1d4ed83a4b
commit 392136dbe4

@ -4,11 +4,11 @@ class URLs {
static const String appReleaseBuildNumber = "50";
// 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://atomsmdev.hmg.com"; // local DEV 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
@ -374,6 +374,8 @@ class URLs {
static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateEngineerAssetTransferNew"; // get
static get assetTransferAssignEngineerToHimself => "$_baseUrl/AssetTransfer/AssignEngineerToHimself"; // get
static get assetTransferEngineerReject => "$_baseUrl/AssetTransfer/EngineerReject"; // get
static get assetDocumentHistory => "$_baseUrl/DocumentLibrary/SearchDocuments";
// employee
static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get

@ -31,6 +31,7 @@ class AssetProvider extends ChangeNotifier {
final pageItemNumber = 10;
final searchPageItemNumber = 10;
final documentPageItemNumber = 20;
bool nextPage = true;
@ -257,4 +258,39 @@ class AssetProvider extends ChangeNotifier {
return false;
}
}
Future<({List<GenericAttachmentModel> documents, int totalRows})> getAssetDocumentHistory({
required int assetId,
int pageNumber = 1,
}) async {
Response response;
List<GenericAttachmentModel> documents = [];
try {
var body = {
"pageSize": documentPageItemNumber,
"pageNumber": pageNumber,
"assetIds": [assetId]
};
response = await ApiManager.instance.post(URLs.assetDocumentHistory, body: body);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body);
List attachmentJson = jsonData["data"] ?? [];
int totalRows = jsonData["totalRows"] ?? 0;
documents = attachmentJson
.map<GenericAttachmentModel>((request) =>
GenericAttachmentModel.fromAssetDocumentJson(request))
.toList();
nextPage = documents.length < totalRows;
return (documents: documents, totalRows: totalRows);
}
return (documents: documents, totalRows: 0);
} catch (e) {
log('Error in getAssetDocumentHistory: $e');
return (documents: documents, totalRows: 0);
}
}
}

@ -1,10 +1,14 @@
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/lookup.dart';
class GenericAttachmentModel {
GenericAttachmentModel({
this.id,
this.name,
this.module,
this.subModule,
this.uploadedBy,
this.originalName,
this.createdBy,
this.documentType,
@ -20,6 +24,9 @@ class GenericAttachmentModel {
int? id;
String? name;
String ? module;
String ? subModule;
String ? uploadedBy;
String? createdBy;
String? originalName;
Lookup? documentType;
@ -36,17 +43,32 @@ class GenericAttachmentModel {
id = json['id'];
name = json['name'] ?? json['attachmentName'] ?? json['imageName'];
createdBy = json['createdBy'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
originalName = json['originalName'] ?? json['imageOriginalName'];
if (convertToLink) {
name = URLs.getFileUrl(name);
}
}
GenericAttachmentModel.fromAssetDocumentJson(Map<String, dynamic> json, {bool convertToLink = false}) {
id = json['id'];
name = json['attachmentName'] ?? json['name'] ?? json['imageName'];
module = json['module'];
subModule = json['subModule'];
createdBy = json['createdBy'];
createdDate = json['createdDate'];
uploadedBy = json['uploadedBy'];
originalName = json['originalName'] ?? json['imageOriginalName'];
documentType = json['attachmentType'] != null ? Lookup(name: json['attachmentType'], id: 0) : null;
if (convertToLink && name != null) {
name = URLs.getFileUrl(name);
}
}
GenericAttachmentModel.fromWorkOrderJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
createdBy = json['createdBy'];
}
@ -54,7 +76,7 @@ class GenericAttachmentModel {
id = json['id']?.toInt();
name = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
moduleReferenceId = json['loanId'];
attachmentTypeId = json['loanAttachmentTypeId'];
}
@ -64,6 +86,7 @@ class GenericAttachmentModel {
name = json['attachmentName'];
attachmentDescription = json['attachmentDescription'];
moduleReferenceId = json['loanId'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
attachmentTypeId = json['loanAttachmentTypeId'];
createdBy = json['createdBy'];
createdDate = json['createdDate'];
@ -75,13 +98,16 @@ class GenericAttachmentModel {
id = json['id'];
name = json['attachmentName'] ?? json['name'];
moduleReferenceId = json['visitId'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
attachmentURL = json['attachmentURL'];
}
GenericAttachmentModel.fromSupplierJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'] ?? json['name'];
supplierId = json['supplierId'];
moduleReferenceId = json['visitId'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
attachmentURL = json['attachmentURL'];
}
@ -89,7 +115,7 @@ class GenericAttachmentModel {
id = json['id'];
name = json['attachmentName'];
moduleReferenceId = json['gasRefillId'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
GenericAttachmentModel.fromIncidentJson(Map<String, dynamic> json) {
@ -97,19 +123,21 @@ class GenericAttachmentModel {
name = json['attachmentName'];
moduleReferenceId = json['incidentId'];
attachmentDescription = json['attachmentDescription'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
GenericAttachmentModel.fromAssetTransferJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
GenericAttachmentModel.fromDemoJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
originalName = json['originalName'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
moduleReferenceId = json['demoRequestId'];
documentType = json['documentType'] != null ? Lookup.fromJson(json['documentType']) : null;
}
GenericAttachmentModel.fromInternalAuditJson(Map<String, dynamic> json) {
@ -117,19 +145,20 @@ class GenericAttachmentModel {
name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
originalName = json['originalName'];
createdBy = json['createdBy'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
GenericAttachmentModel.fromPreventiveVisitJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
GenericAttachmentModel.fromAssetJson(Map<String, dynamic> json) {
id = json['id'];
name = json['attachmentName'];
attachmentURL = json['attachmentURL'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
originalName = json['originalName'];
}
@ -137,10 +166,9 @@ class GenericAttachmentModel {
id = json['id'];
name = json['attachmentName'];
moduleReferenceId = json['trafId'];
documentType = json['documentType'];
documentType = json['attachmentType'] != null ? Lookup.fromJson(json['attachmentType']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
@ -156,6 +184,7 @@ class GenericAttachmentModel {
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;
@ -189,6 +218,7 @@ class GenericAttachmentModel {
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>{};

@ -97,7 +97,12 @@ class _AssetDeliveryAttachmentViewState extends State<AssetDeliveryAttachmentVie
padding: 12,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
)
: FilesList(images: _attachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []).toShadowContainer(
: FilesList( showAsListView: true,
types: _attachments.map((doc) {
final attachmentType = doc.documentType?.name ?? '';
return attachmentType.isNotEmpty ? attachmentType : 'Asset Guide';
}).toList(),
images: _attachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '',).toList() ?? []).toShadowContainer(
context,
borderRadius: 20,
padding: 12,

@ -173,7 +173,18 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
if (activity.activitySparePart?.acitiySparePartAttachments?.isNotEmpty ?? false) ...[
2.height,
const Divider().defaultStyle(context),
FilesList(images: activity.activitySparePart!.acitiySparePartAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => URLs.getFileUrl(toElement.name!)!).toList()),
FilesList(
showAsListView: true,
types: activity.activitySparePart!.acitiySparePartAttachments!
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: activity.activitySparePart!.acitiySparePartAttachments!
.whereType<GenericAttachmentModel>()
.where((e) => e.name != null)
.map((toElement) => URLs.getFileUrl(toElement.name!)!)
.toList()),
],
],
).toShadowContainer(context, showShadow: false).onPress(() {
@ -217,7 +228,6 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
),
],
),
if (showActionButtons)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
@ -252,7 +262,6 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
label: context.translation.assistantEmployee,
value: activity.activityMaintenance?.assistantEmployees?.first.user?.userName,
),
] else ...[
InfoTextWidget(
label: context.translation.assignedEmployee,

@ -270,7 +270,15 @@ class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: _attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
FilesList(
showAsListView: true,
images: _attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList(),
types: _attachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
),
],
if (!requestProvider.isReadOnlyRequest && workOrder.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) ...[
const Divider().defaultStyle(context),

@ -3,6 +3,7 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import '../../controllers/api_routes/urls.dart';
@ -57,10 +58,17 @@ class DemoActivitiesPage extends StatelessWidget {
"Attachments".addTranslation,
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: allAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e ?? '') ?? '').toList()),
],
],
).toShadowContainer(context, borderRadius: 14, backgroundColor: Color(0xffF4F8FC), showShadow: false),
).toShadowContainer(context, borderRadius: 14, backgroundColor: const Color(0xffF4F8FC), showShadow: false),
16.height,
Column(
crossAxisAlignment: CrossAxisAlignment.start,

@ -71,7 +71,14 @@ class IncidentDetailPage extends StatelessWidget {
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: allAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context),

@ -118,7 +118,10 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
if (model?.remarks?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Remarks"),
Text(model!.remarks??'',style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context)),),
Text(
model!.remarks ?? '',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.lightTextColor(context)),
),
8.height,
],
if (allAttachments.isNotEmpty) ...[
@ -128,7 +131,14 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
8.height,
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: allAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).paddingAll(0).toShadowContainer(context),

@ -117,7 +117,14 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: allAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).paddingAll(0).toShadowContainer(context),

@ -97,7 +97,14 @@ class _LoanEquipmentDetailPageState extends State<LoanEquipmentDetailPage> {
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: allAttachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context)

@ -6,6 +6,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/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/medical_gas_inspection/create_medical_gas_request_page.dart';
import 'package:test_sa/modules/medical_gas_inspection/models/medical_gas_data_model.dart';
@ -103,7 +104,14 @@ class _MedicalGasInspectionDetailPageState extends State<MedicalGasInspectionDet
if (model!.deliveryNoteAttachmentDto.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: model!.deliveryNoteAttachmentDto.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: model!.deliveryNoteAttachmentDto
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: model!.deliveryNoteAttachmentDto.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context,),

@ -10,6 +10,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/device/device_transfer.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/modules/cx_module/chat/chat_widget.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/views/widgets/bottom_sheets/rejection_reason_bottom_sheet.dart';
@ -121,7 +122,14 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: _model?.assetTransferAttachments?.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: _model?.assetTransferAttachments!=null?
_model!.assetTransferAttachments!.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList():[],
images: _model?.assetTransferAttachments?.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
]
],
),

@ -238,7 +238,10 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
if (_attachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: _model.gasRefillAttachments?.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((e) => URLs.getFileUrl(e.name!) ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: _model.gasRefillAttachments?.whereType<GenericAttachmentModel>().where((e) => e.documentType != null && e.documentType!.name != null).map((toElement) => toElement.documentType!.name!).toList() ?? [],
images: _model.gasRefillAttachments?.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((e) => URLs.getFileUrl(e.name!) ?? '').toList() ?? []),
],
],
).expanded,

@ -160,7 +160,10 @@ class _TaskRequestDetailsViewState extends State<TaskRequestDetailsView> {
if (taskProvider.taskRequestModel?.taskJobAttachments?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
InfoHeader16Widget("Attachments".addTranslation),
FilesList(images: taskProvider.taskRequestModel!.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()),
FilesList(
showAsListView: true,
types: taskProvider.taskRequestModel!.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => toElement.documentType?.name ?? '').toList(),
images: taskProvider.taskRequestModel!.taskJobAttachments!.whereType<GenericAttachmentModel>().where((e) => e.name != null).map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()),
],
buildTechnicalComments(taskModel: taskModel),
],

@ -155,7 +155,14 @@ class _TrafRequestDetailPageState extends State<TrafRequestDetailPage> {
style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
// 8.height,
FilesList(images: _attachments.map((e) => URLs.getFileUrl(e.path ?? '') ?? '').toList() ?? []),
FilesList(
showAsListView: true,
types: _attachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: _attachments.map((e) => URLs.getFileUrl(e.path ?? '') ?? '').toList() ?? []),
],
],
).toShadowContainer(context);

@ -93,7 +93,7 @@ class _AssetDetailPageState extends State<AssetDetailPage> {
TabBarView(
children: [
AssetDetailsView(assetModel: assetModel!, onUpload: _upload),
const AssetDocumentHistoryView(),
AssetDocumentHistoryView(assetId: assetId!),
],
).expanded,
],

@ -321,7 +321,14 @@ class _AssetDetailsViewState extends State<AssetDetailsView> with SingleTickerPr
opacity: attachmentAnimation,
child: SlideTransition(
position: attachmentSlideAnimation,
child: FilesList(images: attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
child: FilesList(
showAsListView: true,
types: attachments
.whereType<GenericAttachmentModel>()
.where((e) => e.documentType != null && e.documentType!.name!.isNotEmpty)
.map((toElement) => toElement.documentType!.name!)
.toList(),
images: attachments.map((toElement) => URLs.getFileUrl(toElement.name!) ?? '').toList()),
),
),
]

@ -1,29 +1,155 @@
import 'dart:developer';
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/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/item_views/info_text_widget.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class AssetDocumentHistoryView extends StatelessWidget {
const AssetDocumentHistoryView({Key? key}) : super(key: key);
class AssetDocumentHistoryView extends StatefulWidget {
final int assetId;
const AssetDocumentHistoryView({
Key? key,
required this.assetId,
}) : super(key: key);
@override
State<AssetDocumentHistoryView> createState() => _AssetDocumentHistoryViewState();
}
class _AssetDocumentHistoryViewState extends State<AssetDocumentHistoryView> {
late AssetProvider _assetProvider;
final ScrollController _scrollController = ScrollController();
List<GenericAttachmentModel> _documents = [];
bool _isLoading = false;
int _currentPage = 1;
int _totalRows = 0;
@override
void initState() {
super.initState();
_assetProvider = context.read<AssetProvider>();
_scrollController.addListener(_onScroll);
_loadDocuments();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _onScroll() {
final pixels = _scrollController.position.pixels;
final maxScroll = _scrollController.position.maxScrollExtent;
if (pixels >= maxScroll * 0.8) {
if (!_isLoading && _hasMore) {
_loadMore();
}
}
}
bool get _hasMore => _documents.length < _totalRows;
Future<void> _loadDocuments({bool refresh = false, bool loadMore = false}) async {
if (_isLoading) return;
setState(() {
_isLoading = true;
if (refresh) {
_documents.clear();
_currentPage = 1;
}
if (loadMore) {
_currentPage++;
}
});
try {
final result = await _assetProvider.getAssetDocumentHistory(
assetId: widget.assetId,
pageNumber: _currentPage,
);
if (mounted) {
setState(() {
if (refresh) {
_documents = result.documents;
} else {
_documents.addAll(result.documents);
}
_totalRows = result.totalRows;
_isLoading = false;
});
}
} catch (e) {
log('Error loading documents: $e');
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
Future<void> _loadMore() async {
await _loadDocuments(loadMore: true);
}
Future<void> _onRefresh() async {
await _loadDocuments(refresh: true);
}
@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: const EdgeInsets.symmetric(horizontal: 16),
child: FilesList(
showAsListView: true,
showDownloadButton: true,
images: dummyDocuments,
separator: const Divider().defaultStyle(context),
).toShadowContainer(context),
if (_isLoading && _documents.isEmpty) {
return const Center(child: ALoading());
}
if (_documents.isEmpty && !_isLoading) {
return const Center(child: NoDataFound());
}
return RefreshIndicator(
onRefresh: _onRefresh,
child: ListView(
controller: _scrollController,
padding: EdgeInsets.symmetric(
horizontal: 16.toScreenWidth,
),
children: [
FilesList(
showAsListView: true,
showDownloadButton: true,
itemGap: 12.toScreenHeight,
images: _documents
.map((doc) {
return URLs.getFileUrl(doc.name) ?? '';
}).where((url) => url.isNotEmpty).toList(),
types: _documents.map((doc) {
final attachmentType = doc.documentType?.name ?? '';
return attachmentType.isNotEmpty ? attachmentType : 'Asset Guide';
}).toList(),
).toShadowContainer(context),
if (_isLoading && _documents.isNotEmpty&&_hasMore) ...[
16.height,
Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const ALoading(),
8.height,
const InfoTextLabelWidget(label: 'Loading more...'),
],
),
),
),
],
],
),
);
}
}

@ -1,5 +1,4 @@
import 'dart:io';
import 'package:ellipsized_text/ellipsized_text.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@ -10,7 +9,6 @@ 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/loaders/image_loader.dart';
import 'package:url_launcher/url_launcher.dart';
@ -24,7 +22,7 @@ class FilesList extends StatelessWidget {
final double? itemGap;
final Widget? separator;
const FilesList({Key? key, this.separator, this.images = const <String>[], this.types = const <String>[], this.padding, this.showAsListView = false, this.showDownloadButton = false, this.itemGap})
const FilesList({Key? key, this.separator, this.images = const <String>[], this.types = const <String>[], this.padding, required this.showAsListView, this.showDownloadButton = false, this.itemGap})
: super(key: key);
@override
@ -75,8 +73,9 @@ class FilesList extends StatelessWidget {
children: [
EllipsizedText(
images[itemIndex].split("/").last,
style: AppTextStyles.bodyText.copyWith(color: AppColor.textStyleColor(context)),
type: EllipsisType.start, // or EllipsisType.middle
style: AppTextStyles.bodyText2.copyWith(color: AppColor.labelTextStyleColor(context)),
// style: AppTextStyles.bodyText.copyWith(color: AppColor.textStyleColor(context)),
type: EllipsisType.start,
),
2.height,
RichText(

Loading…
Cancel
Save