From 0095facdf519980df8580fa01be4ce8689eee9cc Mon Sep 17 00:00:00 2001 From: "muhammad.abbasi" Date: Wed, 2 Oct 2024 12:18:42 +0300 Subject: [PATCH] maintenance request flow in progress --- lib/controllers/api_routes/urls.dart | 3 + lib/extensions/widget_extensions.dart | 4 +- .../activity_maintenance_model.dart | 93 ++++ lib/models/new_models/assistant_employee.dart | 19 + .../single_item_drop_down_menu.dart | 4 +- .../work_order/activity_status_provider.dart | 1 + .../request_detail_provider.dart | 56 ++ .../components/assistant_employee_card.dart | 212 ++++++++ .../components/external_request.dart | 269 ++++++---- .../components/internal_request.dart | 501 ++++++++++-------- .../widgets/status/single_status_menu.dart | 3 +- pubspec.lock | 88 +-- pubspec.yaml | 1 + 13 files changed, 878 insertions(+), 376 deletions(-) create mode 100644 lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart create mode 100644 lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 60839cb1..43ad4bf3 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -48,10 +48,13 @@ class URLs { static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById'; static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; + static get deleteActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart'; + static get createActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; static get createActivityAssetToBeRetiredUrl=> '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired'; static get createWorkOrderUrl=> '$_baseUrl/ServiceRequest/CreateWorkOrder'; static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; + static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 86e5f975..5e99724a 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -79,9 +79,9 @@ extension WidgetExtensions on Widget { ).toShadowContainer(context) : this; - Widget toShadowContainer(BuildContext context, {bool showShadow = true,Color? backgroundColor, double padding = 16}) => showShadow + Widget toShadowContainer(BuildContext context, {bool showShadow = true,Color? backgroundColor, double padding = 16,EdgeInsets ?paddingValue}) => showShadow ? Container( - padding: EdgeInsets.all(padding), + padding:paddingValue?? EdgeInsets.all(padding), width: double.infinity, decoration: ShapeDecoration( color: backgroundColor?? AppColor.background(context), diff --git a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart new file mode 100644 index 00000000..279e8542 --- /dev/null +++ b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart @@ -0,0 +1,93 @@ +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/assigned_employee.dart'; + +class ActivityMaintenanceHelperModel { + int? workOrderId; + int? lastSituationId; + Lookup? activityStatus; + DateTime? startTime; + DateTime? endTime; + int? workingHour; + int? travelHours; + Lookup? repairLocation; + String? assignedEmployeeId; + String? technicalComment; + int? supplierId; + int? supplierEngineerId; + DateTime? supplierStartTime; + DateTime? supplierEndTime; + int? supplierWorkingHour; + AssignedEmployee? assignedEmployee; + List? assistantEmployees; + + ActivityMaintenanceHelperModel( + {this.workOrderId, + this.lastSituationId, + this.startTime, + this.endTime, + this.workingHour, + this.travelHours, + this.repairLocation, + this.assignedEmployeeId, + this.technicalComment, + this.supplierId, + this.supplierEngineerId, + this.supplierStartTime, + this.supplierEndTime, + this.supplierWorkingHour, + this.assignedEmployee, + this.assistantEmployees}); + + + Map toJson() { + final Map data = {}; + data['workOrderId'] = workOrderId; + data['lastSituationId'] = lastSituationId; + data['activityStatusId'] = activityStatus?.id; + data['startTime'] = startTime?.toIso8601String(); + data['endTime'] = endTime?.toIso8601String(); + data['workingHour'] = workingHour; + data['travelHours'] = travelHours; + data['repairLocationId'] = repairLocation?.id; + data['assignedEmployeeId'] = assignedEmployeeId; + data['technicalComment'] = technicalComment; + data['supplierId'] = supplierId; + data['supplierEngineerId'] = supplierEngineerId; + data['supplierStartTime'] = supplierStartTime?.toIso8601String(); + data['supplierEndTime'] = supplierEndTime?.toIso8601String(); + data['supplierWorkingHour'] = supplierWorkingHour; + if (assistantEmployees != null) { + data['assistantEmployees'] = + assistantEmployees!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class AssistantEmployees { + int? id; + String? userId; + DateTime? startDate; + DateTime? endDate; + int? workingHours; + String? technicalComment; + + AssistantEmployees( + {this.id, + this.userId, + this.startDate, + this.endDate, + this.workingHours, + this.technicalComment}); + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['userId'] = userId; + data['startDate'] = startDate?.toIso8601String(); + data['endDate'] = endDate?.toIso8601String(); + data['workingHours'] = workingHours; + data['technicalComment'] = technicalComment; + return data; + } +} diff --git a/lib/models/new_models/assistant_employee.dart b/lib/models/new_models/assistant_employee.dart index 4ef825ef..570f9d66 100644 --- a/lib/models/new_models/assistant_employee.dart +++ b/lib/models/new_models/assistant_employee.dart @@ -1,16 +1,35 @@ import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/new_models/assigned_employee.dart'; +// int? id; +// String? userId; +// DateTime? startDate; +// DateTime? endDate; +// int? workingHours; +// String? technicalComment; + class AssistantEmployees extends Base { + String? userId; + DateTime? startDate; + DateTime? endDate; + int? workingHours; + String? technicalComment; AssistantEmployees({ this.id, this.user, + this.startDate, + this.technicalComment, + this.workingHours, + this.endDate, + this.userId, }) : super(name: user?.name, identifier: user?.id); AssistantEmployees.fromJson(dynamic json) { id = json['id']; user = json['user'] != null ? AssignedEmployee.fromJson(json['user']) : null; name = user?.name; + userId = user?.id; + identifier = user?.id; } diff --git a/lib/new_views/common_widgets/single_item_drop_down_menu.dart b/lib/new_views/common_widgets/single_item_drop_down_menu.dart index 8673277c..00377aea 100644 --- a/lib/new_views/common_widgets/single_item_drop_down_menu.dart +++ b/lib/new_views/common_widgets/single_item_drop_down_menu.dart @@ -53,10 +53,9 @@ class _SingleItemDropDownMenuState(widget.context, listen: false); } - print('initial value i got is ${widget.initialValue?.identifier}'); if (widget.initialValue != null) { final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier); - print('result value i got is ${result?.length}'); + if (result?.isNotEmpty ?? false) _selectedItem = result!.first as T?; if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) { widget.onSelect!(_selectedItem); // Non-null assertion after null check @@ -72,7 +71,6 @@ class _SingleItemDropDownMenuState oldWidget) { - if (widget.initialValue != null) { final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier); if (result?.isNotEmpty ?? false) { diff --git a/lib/providers/work_order/activity_status_provider.dart b/lib/providers/work_order/activity_status_provider.dart index 77907d95..82420bfd 100644 --- a/lib/providers/work_order/activity_status_provider.dart +++ b/lib/providers/work_order/activity_status_provider.dart @@ -16,6 +16,7 @@ class ActivityStatusProvider extends LoadingListNotifier { notifyListeners(); try { Response response = await ApiManager.instance.get(URLs.getServiceReportActivityStatus); + stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { List categoriesListJson = json.decode(response.body)["data"]; diff --git a/lib/service_request_latest/request_detail_provider.dart b/lib/service_request_latest/request_detail_provider.dart index 6a9c9aed..23a95aa3 100644 --- a/lib/service_request_latest/request_detail_provider.dart +++ b/lib/service_request_latest/request_detail_provider.dart @@ -7,6 +7,7 @@ import 'package:http/src/response.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/helper_data_models/asset_retired/asset_retired_model.dart'; +import 'package:test_sa/models/helper_data_models/maintenance_request/activity_maintenance_model.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/new_models/arrival_verification_type_model.dart'; @@ -64,6 +65,7 @@ class RequestDetailProvider extends ChangeNotifier { //UI models WorkOrderDetail? currentWorkOrder; AssetRetiredHelperModel? assetRetiredHelperModel=AssetRetiredHelperModel(); + ActivityMaintenanceHelperModel? activityMaintenanceHelperModel=ActivityMaintenanceHelperModel(); SparePartHelperModel? sparePartHelperModel; FixRemotelyHelperModel? fixRemotelyHelperModel=FixRemotelyHelperModel(); NeedVisitHelperModel? needVisitHelperModel=NeedVisitHelperModel(); @@ -76,6 +78,10 @@ class RequestDetailProvider extends ChangeNotifier { assetRetiredHelperModel = value; notifyListeners(); } + void updateActivityMaintenanceHelperModel(ActivityMaintenanceHelperModel? value) { + activityMaintenanceHelperModel = value; + notifyListeners(); + } void updateSparePartHelperModel(SparePartHelperModel? value) { sparePartHelperModel = value; @@ -510,6 +516,34 @@ class RequestDetailProvider extends ChangeNotifier { return -1; } } + Future deleteActivityMaintenance({required int id, required int workOrderId}) async { + isLoading = true; + var body = { + 'id': id, + 'workOrderId': workOrderId, + }; + try { + //TODO replace with delete model... + final response = await ApiManager.instance.post( + URLs.deleteActivityMaintenanceUrl, + body: body, + ); + stateCode = response.statusCode; + print('response of delete activity spare part is ${response.statusCode}'); + if (response.statusCode >= 200 && response.statusCode < 300) { + //map to the model... + + notifyListeners(); + } + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + notifyListeners(); + return -1; + } + } Future createActivitySparePart() async { isLoading = true; @@ -533,6 +567,28 @@ class RequestDetailProvider extends ChangeNotifier { return -1; } } + Future createActivityMaintenanceRequest() async { + isLoading = true; + try { + final response = await ApiManager.instance.post( + URLs.createActivityMaintenanceUrl, + body: activityMaintenanceHelperModel!.toJson(), + ); + stateCode = response.statusCode; + print('add maintenance activity response i got is ${response.body}'); + if (response.statusCode >= 200 && response.statusCode < 300) { + + notifyListeners(); + } + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + notifyListeners(); + return -1; + } + } //create asset retired request.. Future createActivityAssetToBeRetired() async { isLoading = true; diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart new file mode 100644 index 00000000..8e9d03a0 --- /dev/null +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -0,0 +1,212 @@ + +import 'package:expansion_tile_card/expansion_tile_card.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; +import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.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/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/service_request_latest/request_detail_provider.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 AssistantEmployeeCard extends StatefulWidget { + + const AssistantEmployeeCard({super.key}); + + @override + State createState() => _AssistantEmployeeCardState(); +} + +class _AssistantEmployeeCardState extends State { + final GlobalKey cardA = GlobalKey(); + bool status = false; + final TextEditingController _workingHoursController = TextEditingController(); + + @override + void initState() { + // TODO: implement initState + WidgetsBinding.instance.addPostFrameCallback((_) { + getInitialData(); + }); + super.initState(); + } + + Future getInitialData() async { + + } + + @override + void dispose() { + // TODO: implement dispose + _workingHoursController.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, requestDetailProvider, child) { + return ExpansionTileCard( + key: cardA, + initialElevation: 0, + borderRadius: BorderRadius.zero, + expandedTextColor: AppColor.black20, + shadowColor: AppColor.white10, + baseColor: AppColor.white10, + contentPadding: EdgeInsets.zero, + expandedColor: AppColor.white10, + duration: Duration.zero, + elevation: 0, + title:context.translation.assistantEmployee.bodyText(context).custom(color: AppColor.black20), + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // ServiceReportAssistantEmployeeMenu( + // title: context.translation.assignAssistant, + // assetId: widget.workOrder!.callRequest!.asset!.id!.toInt(), + // + // initialValue: (_subWorkOrders.assistantEmployees?.isNotEmpty ?? false) ? _subWorkOrders.assistantEmployees?.first : null, + // // initialValue: !isCurrentAssigned + // // ? (widget.workOrder.assistantEmployees?.first) + // // : (_subWorkOrders.assistantEmployees?.isNotEmpty ?? false) + // // ? _subWorkOrders.assistantEmployees?.first + // // : null, + // enable: !isCurrentUserIsAssistantEmp, + // onSelect: (employee) { + // if (employee == null) { + // _subWorkOrders.assistantEmployees = []; + // } else { + // _subWorkOrders.assistantEmployees = [employee.copyWith(id: 0)]; + // } + // }, + // ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, + formatDateWithTime: true, + 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, + ); + requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, + formatDateWithTime: true, + 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.activityMaintenanceHelperModel!.startTime!=null&&selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + + } + }); + }, + ).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: requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString(), + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value){ + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + ), + ], + ), + ], + ); + }); + } + int calculateWorkingHours(DateTime? startTime, DateTime? endTime) { + if(startTime!=null&&endTime!=null){ + Duration difference = endTime.difference(startTime); + int hours = difference.inHours; + int minutes = difference.inMinutes % 60; + return hours; + }else{ + return -1; + } + } + + assignWorkingHours({required RequestDetailProvider requestDetailProvider}){ + int hours = calculateWorkingHours(requestDetailProvider.activityMaintenanceHelperModel!.startTime,requestDetailProvider.activityMaintenanceHelperModel!.endTime); + if(hours!=-1){ + _workingHoursController.text = hours.toString(); + requestDetailProvider.activityMaintenanceHelperModel!.workingHour=hours; + } + } + + final ButtonStyle flatButtonStyle = TextButton.styleFrom( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4.0)), + ), + ); + } \ No newline at end of file diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart index eab0f519..d2ededfc 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart @@ -7,6 +7,7 @@ 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/device/asset.dart'; @@ -17,7 +18,9 @@ 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/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/work_order/reason_provider.dart'; +import 'package:test_sa/service_request_latest/request_detail_provider.dart'; import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; @@ -42,10 +45,8 @@ class _ExternalMaintenanceRequestState extends State ServiceStatusProvider? _assetTypeProvider; ServiceReport ?_serviceReport; bool _isLoading = false; - TimeOfDay ?_startTime; int _selectedValue = 1; - - TimeOfDay ?_endTime; + final TextEditingController _workingHoursController = TextEditingController(); final GlobalKey _formKey = GlobalKey(); final TextEditingController _faultController = TextEditingController(); @@ -93,123 +94,153 @@ class _ExternalMaintenanceRequestState extends State @override Widget build(BuildContext context) { - _serviceRequestsProvider = Provider.of(context); - _assetTypeProvider = Provider.of(context); - if (_serviceReport?.callRequest == null) { - getRequestForWorkOrder(); - } - _serviceReport?.assetType = _assetTypeProvider?.statuses?.firstWhere( - (element) => element.value == _serviceReport?.callRequest?.assetType, - orElse: () => Lookup(), - ); + // _serviceRequestsProvider = Provider.of(context); + // _assetTypeProvider = Provider.of(context); + // if (_serviceReport?.callRequest == null) { + // getRequestForWorkOrder(); + // } + // _serviceReport?.assetType = _assetTypeProvider?.statuses?.firstWhere( + // (element) => element.value == _serviceReport?.callRequest?.assetType, + // orElse: () => Lookup(), + // ); - return LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Stack( - children: [ - SingleChildScrollView( - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - SingleItemDropDownMenu( - context: context, - height: 56.toScreenHeight, - title: context.translation.supplier, - showShadow: false, - backgroundColor: AppColor.neutral100, - staticData: Provider.of(context).calls, - initialValue: _serviceReport?.calllastSituation, - onSelect: (status) { - _serviceReport?.calllastSituation = status; - }, - ), - 8.height, - AppTextFormField( - labelText: context.translation.engineerName, - backgroundColor: AppColor.neutral100, - initialValue: _serviceReport?.assignedEmployee?.name.toString(), - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, + return Consumer( + builder: (context, RequestDetailProvider requestDetailProvider,child) { + return LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Stack( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - ATimePicker( - label: context.translation.startTime, - hint: context.translation.select, - withBorder: false, - icon: 'clock', - withIcon: true, - backgroundColor: AppColor.neutral100, + //TODO replace with correct component.. + SingleItemDropDownMenu( + context: context, height: 56.toScreenHeight, - time: _startTime, - onTimePicker: (selectedTime) { - if (selectedTime != null) { - print('time selected $selectedTime'); - setState(() { - _startTime = selectedTime; - }); - } - }, - ).expanded, - 8.width, - ATimePicker( - label: context.translation.endTime, - hint: context.translation.select, - icon: 'clock', - withIcon: true, + title: context.translation.supplier, + showShadow: false, backgroundColor: AppColor.neutral100, - withBorder: false, - height: 56.toScreenHeight, - time: _endTime, - onTimePicker: (selectedTime) { - if (selectedTime != null) { - setState(() { - _endTime = selectedTime; - }); - } + staticData: Provider.of(context).calls, + initialValue: _serviceReport?.calllastSituation, + onSelect: (status) { + _serviceReport?.calllastSituation = status; }, - ).expanded, + ), + 8.height, + AppTextFormField( + labelText: context.translation.engineerName, + backgroundColor: AppColor.neutral100, + initialValue: _serviceReport?.assignedEmployee?.name.toString(), + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime, + formatDateWithTime: true, + 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, + ); + requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, + formatDateWithTime: true, + 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.activityMaintenanceHelperModel!.supplierStartTime!=null&&selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + + } + }); + }, + ).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: requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString(), + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - labelStyle: AppTextStyles.textFieldLabelStyle, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: _serviceReport?.workingHours.toString(), - textAlign: TextAlign.center, - showShadow: false, - enable: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, + ), + ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), + FooterActionButton.footerContainer( + child: AppFilledButton( + label:context.translation.addExternalActivity, // Use the dynamic label + buttonColor: AppColor.primary10, + onPressed: () async { + // Handle button press - ], + }, + ), ), - ), - ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), - FooterActionButton.footerContainer( - child: AppFilledButton( - label:context.translation.addExternalActivity, // Use the dynamic label - buttonColor: AppColor.primary10, - onPressed: () async { - // Handle button press - - }, - ), + ], ), - ], - ), + ); + } ); } Widget repairLocationWidget(BuildContext context) { @@ -251,4 +282,22 @@ class _ExternalMaintenanceRequestState extends State ], ); } + int calculateWorkingHours(DateTime? startTime, DateTime? endTime) { + if(startTime!=null&&endTime!=null){ + Duration difference = endTime.difference(startTime); + int hours = difference.inHours; + int minutes = difference.inMinutes % 60; + return hours; + }else{ + return -1; + } + } + + assignWorkingHours({required RequestDetailProvider requestDetailProvider}){ + int hours = calculateWorkingHours(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime); + if(hours!=-1){ + _workingHoursController.text = hours.toString(); + requestDetailProvider.activityMaintenanceHelperModel!.workingHour=hours; + } + } } 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 5c61999c..9adea551 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,15 +1,18 @@ - import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/parts_provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.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/device/asset.dart'; +import 'package:test_sa/models/helper_data_models/maintenance_request/activity_maintenance_model.dart'; import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; @@ -17,7 +20,10 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/work_order/activity_status_provider.dart'; import 'package:test_sa/providers/work_order/reason_provider.dart'; +import 'package:test_sa/service_request_latest/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/forms/maintenance_request/components/assistant_employee_card.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; @@ -29,28 +35,24 @@ import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart' class InternalMaintenanceRequest extends StatefulWidget { static const String id = "/add-internal-activity"; - const InternalMaintenanceRequest({Key ?key}) : super(key: key); + const InternalMaintenanceRequest({Key? key}) : super(key: key); @override _InternalMaintenanceRequestState createState() => _InternalMaintenanceRequestState(); } class _InternalMaintenanceRequestState extends State with TickerProviderStateMixin { - ServiceRequest? _request; - ServiceRequestsProvider ?_serviceRequestsProvider; + ServiceRequestsProvider? _serviceRequestsProvider; + RequestDetailProvider? _requestDetailProvider; ServiceStatusProvider? _assetTypeProvider; ActivityStatusProvider? _activityStatusProvider; - ServiceReport ?_serviceReport; + ServiceReport? _serviceReport; bool _isLoading = false; - TimeOfDay ?_startTime; - int _selectedValue = 1; - - TimeOfDay ?_endTime; + bool isCurrentUserIsAssignedEmployee=false; final GlobalKey _formKey = GlobalKey(); - final TextEditingController _faultController = TextEditingController(); - final TextEditingController _workPreformedController = TextEditingController(); + final TextEditingController _workingHoursController = TextEditingController(); final TextEditingController _partQtyController = TextEditingController(); @override @@ -61,34 +63,37 @@ class _InternalMaintenanceRequestState extends State // device: widget.request.device, sparePartsWorkOrders: [], ); - _activityStatusProvider = Provider.of(context,listen: false); + _activityStatusProvider = Provider.of(context, listen: false); + _requestDetailProvider = Provider.of(context, listen: false); super.initState(); - if (context.mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { getInitialData(); - _request = Provider.of(context, listen: false).currentSelectedRequest; - Provider.of(context, listen: false).reset(); - Provider.of(context, listen: false).reset(); - Provider.of(context, listen: false).serviceRequestId = _request?.id??'0'; - } + }); // _isLoading = true; } @override void dispose() { - _faultController.dispose(); - _workPreformedController.dispose(); + _workingHoursController.dispose(); _partQtyController.dispose(); super.dispose(); } - Future getInitialData()async { - _activityStatusProvider?.getDate(); + + Future getInitialData() async { + _activityStatusProvider?.getDate(); + Provider.of(context,listen: false).getTypes(); + final user = Provider.of(context).user!; + isCurrentUserIsAssignedEmployee = (user.userID != _requestDetailProvider?.currentWorkOrder?.data?.assignedEmployee?.userId); + if (isCurrentUserIsAssignedEmployee) { + // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; + } } void getRequestForWorkOrder() async { _isLoading = true; setState(() {}); - _serviceReport?.callRequest = await _serviceRequestsProvider?.getCallRequestForWorkOrder(callId: _request?.id??'0'); + _serviceReport?.callRequest = await _serviceRequestsProvider?.getCallRequestForWorkOrder(callId: _request?.id ?? '0'); await _assetTypeProvider?.getTypes(); _serviceReport?.assignedEmployee = _serviceReport?.callRequest?.assignedEmployee; _serviceReport?.equipmentStatus = _serviceReport?.callRequest?.defectType; @@ -99,214 +104,270 @@ class _InternalMaintenanceRequestState extends State @override Widget build(BuildContext context) { - // _serviceRequestsProvider = Provider.of(context); - // _assetTypeProvider = Provider.of(context); - // if (_serviceReport?.callRequest == null) { - // getRequestForWorkOrder(); - // } - // _serviceReport?.assetType = _assetTypeProvider?.statuses?.firstWhere( - // (element) => element.value == _serviceReport?.callRequest?.assetType, - // orElse: () => Lookup(), - // ); - return LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Stack( - children: [ - SingleChildScrollView( - child: Form( - key: _formKey, + return Consumer(builder: (context, requestDetailProvider, child) { + return LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Stack( + children: [ + SingleChildScrollView( child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - SingleItemDropDownMenu( - context: context, - height: 56.toScreenHeight, - title: context.translation.activityStatus, - showShadow: false, - backgroundColor: AppColor.neutral100, - staticData: Provider.of(context).calls, - initialValue: _serviceReport?.calllastSituation, - onSelect: (status) { - _serviceReport?.calllastSituation = status; - }, - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ATimePicker( - label: context.translation.startTime, - hint: context.translation.select, - withBorder: false, - icon: 'clock', - withIcon: true, - backgroundColor: AppColor.neutral100, - height: 56.toScreenHeight, - time: _startTime, - onTimePicker: (selectedTime) { - if (selectedTime != null) { - print('time selected $selectedTime'); - setState(() { - _startTime = selectedTime; - }); - } - }, - ).expanded, - 8.width, - ATimePicker( - label: context.translation.endTime, - hint: context.translation.select, - icon: 'clock', - withIcon: true, - backgroundColor: AppColor.neutral100, - withBorder: false, - height: 56.toScreenHeight, - time: _endTime, - onTimePicker: (selectedTime) { - if (selectedTime != null) { - setState(() { - _endTime = selectedTime; - }); - } - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), - initialValue: _serviceReport?.workingHours.toString(), - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - - //TODO need to be selected when submit... - // SingleItemDropDownMenu( - // context: context, - // title: context.translation.serviceType, - // initialValue: _serviceReport.serviceType, - // onSelect: (value) { - // _serviceReport.serviceType = value; - // }, - // ), - //Provider.of(context) - - 8.height, - AppTextFormField( - labelText: context.translation.travelingHours, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: _serviceReport?.travelingHours?.toString(), - textInputType: TextInputType.number, - // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), - onSaved: (value) { - _serviceReport?.travelingHours = double.tryParse(value) ?? 0.0; - }, - ), - 16.height, - context.translation.repairLocation.bodyText(context).custom(color: AppColor.black20, fontWeight: FontWeight.w500), - 8.height, - repairLocationWidget(context), - 16.height, - AppTextFormField( - labelText: context.translation.assignedEmployee, - backgroundColor: AppColor.neutral80, - initialValue: _serviceReport?.assignedEmployee?.name.toString(), - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - showShadow: false, - enable: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - AppTextFormField( - initialValue: _serviceReport?.comment, - labelText: context.translation.technicalComment, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - alignLabelWithHint: true, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport?.comment = value; - }, - ), + Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SingleItemDropDownMenu( + context: context, + height: 56.toScreenHeight, + title: context.translation.activityStatus, + showShadow: false, + backgroundColor: AppColor.neutral100, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, + onSelect: (status) { + requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, + formatDateWithTime: true, + 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, + ); + requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, + formatDateWithTime: true, + 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.activityMaintenanceHelperModel!.startTime != null && + selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + assignWorkingHours(requestDetailProvider: requestDetailProvider); + } + }); + }, + ).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: requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString(), + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + labelText: context.translation.travelingHours, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(), + textInputType: TextInputType.number, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = int.tryParse(value); + }, + // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as int?; + }, + ), + 16.height, + repairLocationWidget(context,requestDetailProvider), + 16.height, + AppTextFormField( + labelText: context.translation.assignedEmployee, + backgroundColor: AppColor.neutral80, + initialValue: _serviceReport?.assignedEmployee?.name.toString(), + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + enable: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + ), + ], + ), + ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), + const AssistantEmployeeCard().toShadowContainer(context, paddingValue: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), + 100.height, ], ), ), - ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), + FooterActionButton.footerContainer( + child: AppFilledButton( + label: context.translation.addInternalActivity, // Use the dynamic label + buttonColor: AppColor.primary10, + onPressed: () async { + // Handle button press + }, + ), + ), + ], + ), + ); + }); + } - FooterActionButton.footerContainer( - child: AppFilledButton( - label:context.translation.addInternalActivity, // Use the dynamic label - buttonColor: AppColor.primary10, - onPressed: () async { - // Handle button press + Widget repairLocationWidget(BuildContext context,RequestDetailProvider requestDetailProvider) { + return Consumer(builder: (cxt, snapshot, _) { + try { + requestDetailProvider.activityMaintenanceHelperModel?.repairLocation ??= snapshot.reasons?.first; + } catch (ex) { + print("snapshot.items:${snapshot.reasons?.length}"); + } - }, - ), - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + context.translation.repairLocation.bodyText(context).custom(color: AppColor.black20), + 8.height, + Wrap( + runSpacing: 8, + spacing: 8, + children: [ + for (var element in snapshot.reasons??[]) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: Colors.red, + fillColor: WidgetStateColor.resolveWith((states) { + if (states.contains(WidgetState.selected)) return AppColor.primary10; + return AppColor.neutral130; + }), + groupValue: requestDetailProvider.activityMaintenanceHelperModel?.repairLocation, + onChanged: (state) { + setState(() { + requestDetailProvider.activityMaintenanceHelperModel?.repairLocation = element; + }); + }), + ), + 8.width, + Text(element.name??'', style: AppTextStyles.tinyFont.copyWith(color:AppColor.neutral120)), + ], + ) + ], + ).toShimmer(isShow: snapshot.isLoading), ], - ), - ); + ); + }); } - Widget repairLocationWidget(BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - radioButtonWidget(label: context.translation.remotely, value: 1), - radioButtonWidget(label: context.translation.workshop, value: 2), - radioButtonWidget(label: context.translation.abroad, value: 3), - ], - ); + + int calculateWorkingHours(DateTime? startTime, DateTime? endTime) { + if (startTime != null && endTime != null) { + Duration difference = endTime.difference(startTime); + int hours = difference.inHours; + int minutes = difference.inMinutes % 60; + return hours; + } else { + return -1; + } } - Widget radioButtonWidget({required String label, required dynamic value}) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 20.toScreenWidth, - height: 40.toScreenHeight, - //TODO use the type required according data.. - child: Radio( - fillColor: WidgetStateProperty.resolveWith((states) { - // active - if (states.contains(WidgetState.selected)) { - return AppColor.primary10; - } - // inactive - return AppColor.neutral130; - }), - value: value, - groupValue: _selectedValue, - onChanged: (int ?value) { - setState(() { - _selectedValue = value!; - }); - }, - ), - ), - 8.width, - Text( - label, - style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120), - ), - 13.width, - ], - ); + assignWorkingHours({required RequestDetailProvider requestDetailProvider}) { + int hours = calculateWorkingHours(requestDetailProvider.activityMaintenanceHelperModel!.startTime, requestDetailProvider.activityMaintenanceHelperModel!.endTime); + if (hours != -1) { + _workingHoursController.text = hours.toString(); + requestDetailProvider.activityMaintenanceHelperModel!.workingHour = hours; + } } + Future validate({required ActivityMaintenanceHelperModel model }) async { + if (model.activityStatus == null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); + return false; + } else if (model.startTime == null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.startTime}"); + return false; + } else if (model.endTime == null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.endTime}"); + return false; + } else if (model.travelHours==null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.travelingHours}"); + return false; + }else if (model.repairLocation == null) { + Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.repairLocation}"); + return false; + } + //write all other missing conditions.. + + return true; + } + } diff --git a/lib/views/widgets/status/single_status_menu.dart b/lib/views/widgets/status/single_status_menu.dart index bd0d9300..52a6fbb8 100644 --- a/lib/views/widgets/status/single_status_menu.dart +++ b/lib/views/widgets/status/single_status_menu.dart @@ -48,9 +48,10 @@ class _SingleStatusMenuState extends State { @override void initState() { + print('status lenght is ${widget.statuses?.length}'); _selectedStatus = widget.statuses?.firstWhere( (element) => element == widget.initialStatus, - orElse: null); + orElse: () => Lookup()); if (widget.initialStatus != _selectedStatus) { widget.onSelect?.call(_selectedStatus); // Use null-aware operator diff --git a/pubspec.lock b/pubspec.lock index ba40d82b..91021d9f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692 + sha256: "5534e701a2c505fed1f0799e652dd6ae23bd4d2c4cf797220e5ced5764a7c1c2" url: "https://pub.dev" source: hosted - version: "1.3.42" + version: "1.3.44" another_flushbar: dependency: "direct main" description: @@ -225,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + expansion_tile_card: + dependency: "direct main" + description: + name: expansion_tile_card + sha256: "27ce4cb518f00e21d0f2309aaa6462b26b148e93cee2029a73088cecf42b1eb0" + url: "https://pub.dev" + source: hosted + version: "3.0.0" fake_async: dependency: transitive description: @@ -269,10 +277,10 @@ packages: dependency: transitive description: name: file_selector_macos - sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.9.4+1" file_selector_platform_interface: dependency: transitive description: @@ -285,58 +293,58 @@ packages: dependency: transitive description: name: file_selector_windows - sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4" url: "https://pub.dev" source: hosted - version: "0.9.3+2" + version: "0.9.3+3" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "40921de9795fbf5887ed5c0adfdf4972d5a8d7ae7e1b2bb98dea39bc02626a88" + sha256: "51dfe2fbf3a984787a2e7b8592f2f05c986bfedd6fdacea3f9e0a7beb334de96" url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "3.6.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315 + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "5.3.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25 + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 url: "https://pub.dev" source: hosted - version: "2.18.0" + version: "2.18.1" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: cc02c4afd6510cd84586020670140c4a23fbe52af16cd260ccf8ede101bb8d1b + sha256: eb6e28a3a35deda61fe8634967c84215efc19133ba58d8e0fc6c9a2af2cba05e url: "https://pub.dev" source: hosted - version: "15.1.1" + version: "15.1.3" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: d8a4984635f09213302243ea670fe5c42f3261d7d8c7c0a5f7dcd5d6c84be459 + sha256: b316c4ee10d93d32c033644207afc282d9b2b4372f3cf9c6022f3558b3873d2d url: "https://pub.dev" source: hosted - version: "4.5.44" + version: "4.5.46" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "258b9d637965db7855299b123533609ed95e52350746a723dfd1d8d6f3fac678" + sha256: d7f0147a1a9fe4313168e20154a01fd5cf332898de1527d3930ff77b8c7f5387 url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.2" fixnum: dependency: transitive description: @@ -450,10 +458,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: c500d5d9e7e553f06b61877ca6b9c8b92c570a4c8db371038702e8ce57f8a50f + sha256: "49eeef364fddb71515bc78d5a8c51435a68bccd6e4d68e25a942c5e47761ae71" url: "https://pub.dev" source: hosted - version: "17.2.2" + version: "17.2.3" flutter_local_notifications_linux: dependency: transitive description: @@ -849,18 +857,18 @@ packages: dependency: "direct main" description: name: open_file - sha256: de371f549b1320a48980952473fae1903d4927975506534c8ea4643642eb5f98 + sha256: a070625d8684aa35a35d6701b91d684592f1ea03f5a737ee0d39332526d09421 url: "https://pub.dev" source: hosted - version: "3.5.3" + version: "3.5.7" open_file_android: dependency: transitive description: name: open_file_android - sha256: b5e1a2e9c5ea8e256b015403e94299039627c7205c2a5e6bb426c33235b6ca9a + sha256: eaa52421c5e10ba42eb3958d2632be0fc8b4f7e53556296064339d363caa2233 url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" open_file_ios: dependency: transitive description: @@ -897,10 +905,10 @@ packages: dependency: transitive description: name: open_file_web - sha256: ba35c6f38c21c2bb4268a80927bb828353dda0edfce92e274e0b9639e4f31360 + sha256: cfc9d6091a844e305a3698c45f47f5cd88aabb143665dcfb0f5fd6f7524d357e url: "https://pub.dev" source: hosted - version: "0.0.2" + version: "0.0.3" open_file_windows: dependency: transitive description: @@ -1145,10 +1153,10 @@ packages: dependency: "direct main" description: name: rive - sha256: daa5394a7d064b4997b39e9afa02f6882c479c38b19fa0dd60f052b99c105400 + sha256: cd45b071b288e4bef05f25423e1001a9b3218b81745deae18c9b4d2a2952cc56 url: "https://pub.dev" source: hosted - version: "0.13.13" + version: "0.13.14" rive_common: dependency: transitive description: @@ -1294,18 +1302,18 @@ packages: dependency: transitive description: name: sqflite - sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + sha256: ff5a2436ef8ebdfda748fbfe957f9981524cb5ff11e7bafa8c42771840e8a788 url: "https://pub.dev" source: hosted - version: "2.3.3+1" + version: "2.3.3+2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" + sha256: "2d8e607db72e9cb7748c9c6e739e2c9618320a5517de693d5a24609c4671b1a4" url: "https://pub.dev" source: hosted - version: "2.5.4+2" + version: "2.5.4+4" stack_trace: dependency: transitive description: @@ -1350,10 +1358,10 @@ packages: dependency: transitive description: name: synchronized - sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.3.0+3" table_calendar: dependency: "direct main" description: @@ -1438,10 +1446,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_platform_interface: dependency: transitive description: @@ -1470,10 +1478,10 @@ packages: dependency: transitive description: name: uuid - sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -1518,10 +1526,10 @@ packages: dependency: transitive description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" win32: dependency: "direct overridden" description: diff --git a/pubspec.yaml b/pubspec.yaml index d9ec191f..64e83eb4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,7 @@ dependencies: permission_handler: ^11.3.1 rive: ^0.13.13 another_flushbar: + expansion_tile_card: ^3.0.0 pinput: audioplayers: ^6.1.0 flare_flutter: ^3.0.2