import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/cm_module/service_request_detail_provider.dart'; import 'package:test_sa/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/cm_module/views/components/asset_detail_card.dart'; import 'package:test_sa/cm_module/views/components/initial_visit_card.dart'; import 'package:test_sa/cm_module/views/forms/asset_retired/asset_retired.dart'; import 'package:test_sa/cm_module/views/forms/cost/cost_detail_form_screen.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/work_order_next_step.dart'; import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.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/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 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() ?? []; // _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? []; super.initState(); } @override Widget build(BuildContext context) { UserProvider _userProvider = Provider.of(context, listen: false); return Consumer(builder: (pContext, requestProvider, _) { return requestProvider.isLoading ? const CircularProgressIndicator(color: AppColor.primary10).center : requestProvider.currentWorkOrder == null ? const NoDataFound() : Stack( children: [ Column( children: [ SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), 12.height, costCard(context, requestProvider), 12.height, contactInfoCard(context, requestProvider.currentWorkOrder!.data!), 20.height, ], ), ).expanded, FooterActionButton.requestDetailsFooterWidget( workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, status: requestProvider.currentWorkOrder?.data?.status, isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null, activities: requestProvider.currentWorkOrder!.data?.activities ?? [], userProvider: _userProvider, context: context), ], ), //no need to show timer as discussed with backend // if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ // const TimerWidget(), // ] ], ); }); } Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider, ServiceRequestDetailProvider requestProvider) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ if (Provider.of(context, listen: false).showPriority) ...[ StatusLabel( label: workOrder.priority?.name, id: workOrder.priority!.id!, radius: 4, textColor: AppColor.getPriorityStatusTextColor(context, workOrder.priority!.id!), backgroundColor: AppColor.getPriorityStatusColor(context, workOrder.priority!.id!), ), 8.width, ], StatusLabel( radius: 4, label: workOrder.status!.name, textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!), backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!), ), if (workOrder.since != null) ...[ 8.width, StatusLabel( radius: 4, label: '${workOrder.since} days', textColor: AppColor.neutral50, backgroundColor: AppColor.orange30, ), ], 1.width.expanded, Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ // if (userProvider.user!.type == UsersTypes.normal_user) // context.translation.code.toSvgAsset(width: 48).onPress(() { // // Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest))); // }), if (userProvider.user!.type == UsersTypes.engineer) 16.height, Text( workOrder.requestedDate!.toString().toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), ], ) ], ), Text( context.translation.assetInformation, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, Text( '${context.translation.assetName}: ${workOrder.assetNdModel!.name?.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), // 8.height, Text( '${context.translation.assetNumber}: ${workOrder.asset!.assetNumber}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), // Text( // '${context.translation.equipmentStatus}: ${workOrder.defectType?.name}', // todo ask ahmed // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), // ), Text( '${context.translation.manufacture}: ${workOrder.manufacturer?.name?.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.model}: ${workOrder.model?.name!.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.site}: ${workOrder.site?.siteName?.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.building}: ${workOrder.building?.name?.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.floor}: ${workOrder.floor?.name?.cleanupWhitespace?.capitalizeFirstOfEach ?? ""}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.department}: ${workOrder.department?.name?.cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.room}: ${(workOrder.room?.toString() ?? "").cleanupWhitespace?.capitalizeFirstOfEach}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], ).expanded, ], ), 8.height, const Divider().defaultStyle(context), //... request details starts here.... Text( context.translation.callDetails, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, // Text( // '${context.translation.requestType}: ${workOrder.typeofRequest?.name}', // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), // ), Text( '${context.translation.cmNumber}: ${workOrder.workOrderNo}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.requesterName}: ${workOrder.workOrderCreatedBy?.userName ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( 'Requested Date: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), ), Text( '${context.translation.arrivedDate}: ${workOrder.iHaveArrivedDate != null ? workOrder.iHaveArrivedDate.toString().toServiceRequestDetailsFormat : '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), ), Text( '${context.translation.closedDate}: ${workOrder.closedDate != null ? workOrder.closedDate!.toString().toServiceRequestDetailsFormat : '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), ), const Divider().defaultStyle(context), //... call response details starts here.... Text( context.translation.callResponse, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, Text( '${context.translation.assignedTo}: ${workOrder.assignedEmployee?.userName ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.assetStatus}: ${workOrder.equipmentStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.callResponse}: ${workOrder.callResponse ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), // Text( // '${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}', // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), // ), 8.height, if (workOrder.rejectReason != null) ...[ const Divider().defaultStyle(context), 8.height, Text( context.translation.rejectionDetails, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, Text( '${context.translation.rejectionReason}: ${workOrder.rejectReason?.name ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), 8.height, Text( '${context.translation.comment}: ${workOrder.rejectComment ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], 8.height, if ((workOrder.comments ?? "").isNotEmpty) ...[ const Divider().defaultStyle(context), 8.height, Text( context.translation.callComments, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, Text( workOrder.comments!, style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], if (!requestProvider.isReadOnlyRequest) ...[ 8.height, const Divider().defaultStyle(context), MultiFilesPicker( label: context.translation.attachments, files: _workOrderAttachments, // attachment: _workOrderAttachments, buttonColor: AppColor.primary10, onlyImages: false, buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), onChange: (attachment) { requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); }, ), ], if (workOrder.voiceNote?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 16.height, ASoundPlayer(audio: URLs.getFileUrl(workOrder.voiceNote!)!), 8.height, ], ], ).paddingOnly(start: 16, end: 16, top: 16, bottom: 8), // (userProvider.user!.type == UsersTypes.normal_user // ? Container( // height: 50, // padding: const EdgeInsets.only(left: 16, right: 16), // alignment: Alignment.center, // width: double.infinity, // decoration: ShapeDecoration( // color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, // shape: const RoundedRectangleBorder( // borderRadius: BorderRadius.only( // bottomLeft: Radius.circular(20), // bottomRight: Radius.circular(20), // ), // ), // ), // child: Row( // children: [ // Text( // '${context.translation.commentHere}...', // style: AppTextStyles.heading6.copyWith( // color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), // ), // ).expanded, // "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), // ], // ), // ) // : Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // const Divider().defaultStyle(context), // 16.height, // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Text( // context.translation.viewComments, // style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), // ), // 4.width, // Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) // ], // ), // ], // ).paddingOnly(bottom: 16, start: 16, end: 16)) // .onPress(() { // // showModalBottomSheet( // // context: context, // // useSafeArea: true, // // isScrollControlled: true, // // useRootNavigator: true, // // backgroundColor: Colors.transparent, // // builder: (context) => CommentsBottomSheet(requestId: serviceRequest.id!), // // ); // }), //set condition for show asset detail button... if ((workOrder.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.verifyAssetDetail || workOrder.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) && userProvider.user?.type == UsersTypes.engineer) ...[ assetRetiredButton(context: context), ] ], ).toShadowContainer(context, padding: 0); } Widget contactInfoCard(BuildContext context, WorkOrderData workOrder) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Contact Info", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), // 8.height, ListView.separated( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: EdgeInsets.zero, itemBuilder: (cxt, index) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${workOrder.workOrderContactPerson[index].name ?? '-'}', style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), Text( '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( 'Job: ${workOrder.workOrderContactPerson[index].position ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( 'Extension: ${workOrder.workOrderContactPerson[index].extension ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], ), separatorBuilder: (cxt, index) => const Divider().defaultStyle(context), itemCount: workOrder.workOrderContactPerson.length), ], ).toShadowContainer(context, padding: 12); } Widget costCard(BuildContext context, ServiceRequestDetailProvider provider) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( "Cost", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ).expanded, if (!provider.isReadOnlyRequest) "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async { provider.refreshTimer = false; await Navigator.push(context, MaterialPageRoute(builder: (context) => CostDetailFormScreen(isEdit: true))); provider.refreshTimer = true; }), ], ), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( 'Spare Part Cost: ${provider.currentWorkOrder!.data?.sparePartCost ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( 'Labour Cost: ${provider.currentWorkOrder!.data?.labourCost ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( 'Travel Cost: ${provider.currentWorkOrder!.data?.travelCost ?? '-'}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], ), ], ).toShadowContainer(context, padding: 12); } Widget assetRetiredButton({required BuildContext context}) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth), child: AppFilledButton( label: context.translation.assetToBeRetired, maxWidth: true, buttonColor: Colors.white54, textColor: AppColor.red30, showBorder: true, onPressed: () async { Navigator.push(context, MaterialPageRoute(builder: (context) => const AssetRetired())); }), ); } Widget initialVisitCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) { if (requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime != null && userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { // requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel( // workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, // visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime, // comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment, // ); return const InitialVisitCard(); } else { return const SizedBox(); } } Widget assetDetailCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) { if ((userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) || requestDetailProvider.isReadOnlyRequest) { WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!; requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel( workOrderId: currentWorkOrderData.requestId, equipmentStatus: currentWorkOrderData.equipmentStatus, loanAvailability: currentWorkOrderData.loanAvailablity, failureReason: currentWorkOrderData.failureReasone, faultDescription: currentWorkOrderData.faultDescription, solution: currentWorkOrderData.faultDescription?.workPerformed, returnToService: currentWorkOrderData.returnToService, serviceType: currentWorkOrderData.serviceType, descriptionOfFinding: currentWorkOrderData.descriptionOfFinding, actionTaken: currentWorkOrderData.actionTaken, ); return const AssetDetailCard(); } else { return const SizedBox(); } } }