From 6b93479170be31ac7f6b82ef4cc329430bbbc07f Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Tue, 25 Mar 2025 13:06:03 +0300 Subject: [PATCH] work order attachment added --- lib/controllers/api_routes/urls.dart | 2 + .../workorder/work_order_helper_models.dart | 8 ++++ .../service_request_detail_provider.dart | 28 +++++++++++ .../utilities/service_request_utils.dart | 1 - .../service_request_detail_view.dart | 46 +++++++++++++++---- .../components/internal_request.dart | 7 +++ .../service_request_detail_main_view.dart | 4 +- 7 files changed, 83 insertions(+), 13 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index aaba34ee..3481dc79 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -76,6 +76,8 @@ class URLs { static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; + static get uploadWorkOrderAttachmentsUrl=> '$_baseUrl/ServiceRequest/UploadAttachmentsWorkOrder'; + static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; diff --git a/lib/models/helper_data_models/workorder/work_order_helper_models.dart b/lib/models/helper_data_models/workorder/work_order_helper_models.dart index f851e5c3..2eae7084 100644 --- a/lib/models/helper_data_models/workorder/work_order_helper_models.dart +++ b/lib/models/helper_data_models/workorder/work_order_helper_models.dart @@ -41,6 +41,14 @@ class WorkOrderHelperModel { } return data; } + Map toUploadAttachmentJson(int? workOrderId,List? workOrderAttachments) { + final Map data = {}; + data['workOrderId'] = workOrderId; + if (workOrderAttachments != null) { + data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList(); + } + return data; + } } class WorkOrderAttachments { diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index ffaca293..fad2e78a 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:http/src/response.dart'; @@ -14,6 +15,7 @@ import 'package:test_sa/models/new_models/arrival_verification_type_model.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; class ServiceRequestDetailProvider extends ChangeNotifier { final pageItemNumber = 10; @@ -226,6 +228,32 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + //upload workorder attachment by engineer.. + Future addWorkOrderAttachment({required int woId, required List attachments}) async { + try { + List woAttachments = []; + for (var file in attachments) { + String fileName = ServiceRequestUtils.isLocalUrl(file.path) ? ("${file.path.split("/").last}|${base64Encode(File(file.path).readAsBytesSync())}") : file.path; + woAttachments.add(WorkOrderAttachments(id: 0, name: fileName)); + } + + isLoading = true; + notifyListeners(); + final response = await ApiManager.instance.post(URLs.uploadWorkOrderAttachmentsUrl, body: WorkOrderHelperModel().toUploadAttachmentJson(woId, woAttachments)); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + } + isLoading = false; + notifyListeners(); + } catch (e) { + log("getWorkOrder [error] : $e"); + isLoading = false; + notifyListeners(); + return null; + } + } + //getQrCode...... Future getQrCode({required int workOrderId}) async { try { diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index b18f5ee8..9deccbfa 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -457,7 +457,6 @@ class ConfirmArrivalNotificationModel { this.accept, }); - // Factory constructor to create an instance from a Map (e.g., JSON) factory ConfirmArrivalNotificationModel.fromJson(Map json) { return ConfirmArrivalNotificationModel( transactionType: json['transactionType'], diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index e804e248..61111bdd 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; @@ -19,13 +22,27 @@ import 'package:test_sa/service_request_latest/views/components/asset_detail_car import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart'; import 'package:test_sa/service_request_latest/views/components/timer_widget.dart'; import 'package:test_sa/service_request_latest/views/forms/asset_retired/asset_retired.dart'; -import 'package:test_sa/views/widgets/images/files_list.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; -class ServiceRequestDetailView extends StatelessWidget { - const ServiceRequestDetailView({Key? key}) : super(key: key); +class ServiceRequestDetailView extends StatefulWidget { + ServiceRequestDetailView({Key? key}) : super(key: key); + + @override + State createState() => _ServiceRequestDetailViewState(); +} + +class _ServiceRequestDetailViewState extends State { + List _workOrderAttachments = []; + + @override + void initState() { + ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? []; + super.initState(); + } @override Widget build(BuildContext context) { @@ -45,7 +62,7 @@ class ServiceRequestDetailView extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider), + workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), 20.height, @@ -69,7 +86,7 @@ class ServiceRequestDetailView extends StatelessWidget { }); } - Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider) { + Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider, ServiceRequestDetailProvider requestProvider) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -230,11 +247,20 @@ class ServiceRequestDetailView extends StatelessWidget { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], - if (workOrder.workOrderAttachments.isNotEmpty ?? false) ...[ - 8.height, - const Divider().defaultStyle(context), - FilesList(images: workOrder.workOrderAttachments.map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()), - ], + + 8.height, + const Divider().defaultStyle(context), + MultiFilesPicker( + label: context.translation.attachments, + files: _workOrderAttachments, + buttonColor: AppColor.primary10, + onlyImages: false, + buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), + onChange: (attachment) { + requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: attachment); + }, + ), + if (workOrder.voiceNote?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 16.height, diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart index c611ec97..4ea023f1 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; @@ -32,11 +34,15 @@ class _InternalMaintenanceRequestState extends State final TextEditingController _travellingHoursController = TextEditingController(); Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1}); + + @override void initState() { _requestDetailProvider = Provider.of(context, listen: false); super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { + //need to confirm with backend api data... + // _deviceImages.addAll(_serviceRequest.devicePhotos!.map((e) => File(e)).toList()); _travellingHoursController.text = _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : ''; }); @@ -280,6 +286,7 @@ class _InternalMaintenanceRequestState extends State requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; }, ), + ], ), ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), diff --git a/lib/service_request_latest/views/service_request_detail_main_view.dart b/lib/service_request_latest/views/service_request_detail_main_view.dart index 13e6e432..4ea8d260 100644 --- a/lib/service_request_latest/views/service_request_detail_main_view.dart +++ b/lib/service_request_latest/views/service_request_detail_main_view.dart @@ -128,10 +128,10 @@ class _ServiceRequestDetailMainState extends State { ), ), 12.height, - const TabBarView( + TabBarView( children: [ ServiceRequestDetailView(), - HistoryLogView(), + const HistoryLogView(), ], ).expanded, ],