From 705dff245d6d09e51878f51b76094a3834bfbd0c Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Wed, 23 Jul 2025 12:00:25 +0300 Subject: [PATCH] multiple assistant employee structure added --- .../new_models/work_order_detail_model.dart | 49 +++- .../components/assistant_employee_list.dart | 246 ++++++++++++++++++ .../components/internal_request.dart | 4 +- 3 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_list.dart diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index 43e3dfae..8b26ec59 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -3,6 +3,7 @@ import 'package:test_sa/models/fault_description.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'; +import 'package:test_sa/models/new_models/assistant_employee.dart'; class WorkOrderDetail { WorkOrderDetail({ @@ -827,15 +828,29 @@ class ActivityMaintenanceAssistantEmployees { double? workingHours; String? technicalComment; AssignedEmployee? user; + AssistantEmployees ?employee; - ActivityMaintenanceAssistantEmployees({this.startDate, this.endDate, this.workingHours, this.technicalComment, this.user}); + ActivityMaintenanceAssistantEmployees({this.startDate, this.endDate, this.workingHours, this.technicalComment, this.user,this.employee}); ActivityMaintenanceAssistantEmployees.fromJson(Map json) { + Map assistEmpData={}; + + startDate = json['startDate'] != null ? DateTime.parse(json['startDate']) : null; endDate = json['endDate'] != null ? DateTime.parse(json['endDate']) : null; workingHours = json['workingHours']; technicalComment = json['technicalComment']; user = json['user'] != null ? AssignedEmployee.fromJson(json['user']) : null; + if(json['user']!=null) { + assistEmpData = { + 'id': null, + 'user': { + 'id': user?.userId, + 'name': user?.userName, + }, + }; + } + employee = AssistantEmployees.fromJson(assistEmpData); } Map toJson() { @@ -851,6 +866,38 @@ class ActivityMaintenanceAssistantEmployees { } } + +// class ActivityMaintenanceAssistantEmployees { +// DateTime? startDate; +// DateTime? endDate; +// double? workingHours; +// String? technicalComment; +// AssignedEmployee? user; +// +// +// ActivityMaintenanceAssistantEmployees({this.startDate, this.endDate, this.workingHours, this.technicalComment, this.user}); +// +// ActivityMaintenanceAssistantEmployees.fromJson(Map json) { +// startDate = json['startDate'] != null ? DateTime.parse(json['startDate']) : null; +// endDate = json['endDate'] != null ? DateTime.parse(json['endDate']) : null; +// workingHours = json['workingHours']; +// technicalComment = json['technicalComment']; +// user = json['user'] != null ? AssignedEmployee.fromJson(json['user']) : null; +// } +// +// Map toJson() { +// final Map data = {}; +// data['startDate'] = startDate?.toIso8601String(); +// data['endDate'] = endDate?.toIso8601String(); +// data['workingHours'] = workingHours; +// data['technicalComment'] = technicalComment; +// if (user != null) { +// data['userId'] = user?.userId; +// } +// return data; +// } +// } + class ActivityMaintenanceTimers { int? id; String? startTime; diff --git a/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_list.dart b/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_list.dart new file mode 100644 index 00000000..a65b3f70 --- /dev/null +++ b/lib/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_list.dart @@ -0,0 +1,246 @@ +import 'package:flutter/material.dart'; +import 'package:provider/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/new_models/work_order_detail_model.dart'; +import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart'; +import 'package:test_sa/modules/cm_module/utilities/service_request_utils.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/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; + +class AssistantEmployeeList extends StatefulWidget { + List? assistantEmployeeList; + + AssistantEmployeeList({super.key, this.assistantEmployeeList = const []}); + + @override + State createState() => _AssistantEmployeeListState(); +} + +class _AssistantEmployeeListState extends State { + bool status = false; + final TextEditingController _workingHoursController = TextEditingController(text: ''); + bool isCurrentUserIsAssistantEmp = false; + bool isExpanded = false; + + void _addNewEntry() { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + widget.assistantEmployeeList!.add(ActivityMaintenanceAssistantEmployees()); + }); + }); + } + + void _removeEntry(int index) { + setState(() { + setState(() { + widget.assistantEmployeeList!.removeAt(index); + }); + }); + } + + @override + void dispose() { + _workingHoursController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, requestDetailProvider, child) { + return ListView.builder( + itemCount: widget.assistantEmployeeList!.length + 1, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(16), + itemBuilder: (context, index) { + if (index == widget.assistantEmployeeList!.length) { + return Visibility( + visible: !requestDetailProvider.isReadOnlyRequest, + child: AppFilledButton( + label: "Add Assistant Employee".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: _addNewEntry, + ), + ); + } + ActivityMaintenanceAssistantEmployees model = widget.assistantEmployeeList![index]; + return employeeCard(model: model, requestDetailProvider: requestDetailProvider, index: index) + .toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16, vertical: 12)) + .paddingOnly(bottom: 12); + }, + ); + }); + } + + Widget employeeCard({required ActivityMaintenanceAssistantEmployees model, required ServiceRequestDetailProvider requestDetailProvider, required int index}) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + context.translation.assistantEmployee.bodyText(context).custom(color: AppColor.black20), + Container( + height: 32, + width: 32, + padding: const EdgeInsets.all(6), + child: "trash".toSvgAsset(height: 20, width: 20), + ).onPress(() { + _removeEntry(index); + }), + ], + ), + 8.height, + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ServiceReportAssistantEmployeeMenu( + title: context.translation.select, + backgroundColor: AppColor.neutral100, + assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!, + initialValue: model.employee, + onSelect: (employee) { + if (employee != null) { + model.employee = employee.copyWith(id: 0); + model.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: model.startDate, + formatDateWithTime: true, + from: requestDetailProvider.currentWorkOrder?.data?.requestedDate, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); + if (requestDetailProvider.currentWorkOrder?.data?.requestedDate != null && selectedDateTime.isBefore(requestDetailProvider.currentWorkOrder!.data!.requestedDate!)) { + "Start time is before the request time.".showToast; + selectedTime = null; + return; + } + if (selectedDateTime.isAfter(DateTime.now())) { + "Start time is after than current time".showToast; + selectedTime = null; + return; + } + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + model.startDate = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: model.startDate, + endTime: model.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + model.workingHours = hours; + }); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: model.endDate, + from: requestDetailProvider.currentWorkOrder?.data?.requestedDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + selectedDate = selectedDate.add(Duration(hours: selectedTime.hour, minutes: selectedTime.minute)); + bool isBeforeCurrentTime = selectedDate.isBefore(DateTime.now()); + bool isAfterStartTime = selectedDate.isAfter(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!); + if (!isBeforeCurrentTime) { + "Please select a time before the current time.".showToast; + return; + } + if (!isAfterStartTime) { + "End Date time must be greater then start date".showToast; + return; + } + + model.endDate = selectedDate; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: model.startDate, + endTime: model.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + model.workingHours = hours; + }); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: model.workingHours != null ? model.workingHours.toString() : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: model.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + model.technicalComment = value; + }, + onSaved: (value) { + model.technicalComment = value; + }, + ), + 8.height, + ], + ) + // : const SizedBox(), + ], + ); + } +} diff --git a/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart b/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart index 92d42146..90d0d0ca 100644 --- a/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/modules/cm_module/views/forms/maintenance_request/components/internal_request.dart @@ -8,6 +8,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart'; import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart'; +import 'package:test_sa/modules/cm_module/views/forms/maintenance_request/components/assistant_employee_list.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; @@ -298,7 +299,8 @@ class _InternalMaintenanceRequestState extends State ], ), ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), - const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), + AssistantEmployeeList(assistantEmployeeList: requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployList,), + // const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), 100.height, ], ),