You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudsolutions-atoms/lib/cm_module/views/components/service_request_detail_view...

499 lines
26 KiB
Dart

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/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/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/service_request_latest/views/components/asset_detail_card.dart';
import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart';
import 'package:test_sa/service_request_latest/views/forms/asset_retired/asset_retired.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<ServiceRequestDetailView> createState() => _ServiceRequestDetailViewState();
}
class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
List<File> _workOrderAttachments = [];
@override
void initState() {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(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<UserProvider>(context, listen: false);
return Consumer<ServiceRequestDetailProvider>(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,
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<SettingProvider>(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: 16);
}
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();
}
}
void showToast({required UserProvider userProvider, required WorkOrderNextStepEnum nextStep, required BuildContext context}) {
if (userProvider.user?.type == UsersTypes.engineer) {
if (nextStep == WorkOrderNextStepEnum.nTakeAction) {
const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: '');
}
}
}
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();
}
}
}