From 743bb28b1deca537238ed8df8b3be0bad1ffff10 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 12:03:47 +0300 Subject: [PATCH 01/11] Create New Work Order Done --- .../service_request/service_report.dart | 21 ++++++++++++++++--- lib/models/service_request/spare_parts.dart | 2 +- .../requests/service_request_details.dart | 2 +- .../work_order/create_service_report.dart | 13 +++++++----- .../work_order/work_orders_list_page.dart | 13 ++++++------ 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/models/service_request/service_report.dart b/lib/models/service_request/service_report.dart index 25ae4ccb..71966b8b 100644 --- a/lib/models/service_request/service_report.dart +++ b/lib/models/service_request/service_report.dart @@ -1,5 +1,8 @@ import 'dart:typed_data'; +import 'package:flutter/cupertino.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/spare_parts.dart'; import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart'; @@ -266,8 +269,8 @@ class ServiceReport { if (reason != null) { map['reason'] = reason.toJson(); } - map['startofWorkTime'] = startofWorkTime; - map['endofWorkTime'] = endofWorkTime; + map['startofWorkTime'] = "2023-10-30T10:14:07.032021"; + map['endofWorkTime'] = "2023-10-30T10:15:07.032021"; map['workingHours'] = workingHours; map['travelingHours'] = travelingHours; map['travelingExpenses'] = travelingExpenses; @@ -302,7 +305,19 @@ class ServiceReport { return map; } - Future validate() async { + Future validate(BuildContext context) async { + if (calllastSituation == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.callLastSituation}"); + return false; + } + if (sparePartsWorkOrders?.isEmpty ?? true) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNo}"); + return false; + } + if (reason == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.reason}"); + return false; + } return true; } } diff --git a/lib/models/service_request/spare_parts.dart b/lib/models/service_request/spare_parts.dart index cd981eb2..2f080f76 100644 --- a/lib/models/service_request/spare_parts.dart +++ b/lib/models/service_request/spare_parts.dart @@ -41,7 +41,7 @@ class SparePartsWorkOrders extends Base { if (sparePart != null) { map['sparePart'] = sparePart.toJson(); } - map['qty'] = qty; + map['qty'] = qty ?? 0; map['returnQty'] = returnQty; map['installQty'] = installQty; return map; diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart index 88afcebc..2e83457b 100644 --- a/lib/views/pages/user/requests/service_request_details.dart +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -209,7 +209,7 @@ class ServiceRequestDetailsPage extends StatelessWidget { padding: const EdgeInsets.all(16), child: informationCard(), ).expanded, - if (_userProvider.user.type != UsersTypes.engineer || (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3)) + if (_userProvider.user.type == UsersTypes.engineer || (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3)) (serviceRequest.firstAction == null ? AppFilledButton( label: context.translation.firstAction, diff --git a/lib/views/pages/user/requests/work_order/create_service_report.dart b/lib/views/pages/user/requests/work_order/create_service_report.dart index 84c9f652..0764b1c2 100644 --- a/lib/views/pages/user/requests/work_order/create_service_report.dart +++ b/lib/views/pages/user/requests/work_order/create_service_report.dart @@ -21,6 +21,7 @@ import 'package:test_sa/providers/work_order/reason_provider.dart'; import 'package:test_sa/providers/work_order/service_type_provider.dart'; import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; @@ -31,7 +32,6 @@ import '../../../../../new_views/common_widgets/default_app_bar.dart'; import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; import '../../../../widgets/date_and_time/date_picker.dart'; import '../../../../widgets/images/multi_image_picker.dart'; -import '../../../../widgets/status/report/service_report_assistant_employee_menu.dart'; /// todo : TBD (compare with the design) class CreateServiceReport extends StatefulWidget { @@ -84,7 +84,7 @@ class _CreateServiceReportState extends State with TickerPr setState(() {}); _serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id); await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); - // _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson()); + _serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee; _spareParts = await _partsProvider.getPartsList(assetId: widget.request.deviceId); _isLoading = false; setState(() {}); @@ -192,7 +192,7 @@ class _CreateServiceReportState extends State with TickerPr initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.sparePart : null, onSelect: (part) { _serviceReport.sparePartsWorkOrders.clear(); - _serviceReport.sparePartsWorkOrders.add(SparePartsWorkOrders(sparePart: part)); + _serviceReport.sparePartsWorkOrders.add(SparePartsWorkOrders(id: 0, sparePart: part, qty: 0)); setState(() {}); }, ), @@ -201,8 +201,11 @@ class _CreateServiceReportState extends State with TickerPr labelText: context.translation.quantity, textInputType: TextInputType.number, enable: _serviceReport.sparePartsWorkOrders.isNotEmpty, + initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.qty?.toString() : null, onSaved: (text) { - _serviceReport.sparePartsWorkOrders.first.qty = num.tryParse(text ?? ""); + if (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) { + _serviceReport.sparePartsWorkOrders.first.qty = num.tryParse(text ?? ""); + } }, ), 8.height, @@ -227,7 +230,7 @@ class _CreateServiceReportState extends State with TickerPr AppFilledButton( label: context.translation.submitRequest, onPressed: () async { - if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate()))) { + if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate(context)))) { setState(() {}); return; } diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index 2cac7c98..b12178c9 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -156,13 +156,14 @@ class WorkOrderListPage extends StatelessWidget { ); }, ).expanded, - if (_userProvider.user.type != UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)) + if (_userProvider.user.type == UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)) AppFilledButton( - label: context.translation.createWorkOrder, - maxWidth: true, - onPressed: () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }).paddingOnly(start: 16, end: 16, bottom: 16) + label: context.translation.createWorkOrder, + maxWidth: true, + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ).paddingOnly(start: 16, end: 16, bottom: 16) ], ); }, From 7a06f251be96a7aa5e132ed6890f1f715ff9a306 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 12:24:44 +0300 Subject: [PATCH 02/11] Create New Work Order Done --- lib/models/service_request/service_report.dart | 6 +++--- .../user/requests/work_order/create_service_report.dart | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/models/service_request/service_report.dart b/lib/models/service_request/service_report.dart index 71966b8b..cc59f679 100644 --- a/lib/models/service_request/service_report.dart +++ b/lib/models/service_request/service_report.dart @@ -269,8 +269,8 @@ class ServiceReport { if (reason != null) { map['reason'] = reason.toJson(); } - map['startofWorkTime'] = "2023-10-30T10:14:07.032021"; - map['endofWorkTime'] = "2023-10-30T10:15:07.032021"; + map['startofWorkTime'] = startofWorkTime; + map['endofWorkTime'] = endofWorkTime; map['workingHours'] = workingHours; map['travelingHours'] = travelingHours; map['travelingExpenses'] = travelingExpenses; @@ -283,7 +283,7 @@ class ServiceReport { map['reviewComment'] = reviewComment; map['comment'] = comment; if (attachmentsWorkOrder != null) { - map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => v.toJson()).toList(); + map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => {"name": v.name}).toList(); } if (equipmentStatus != null) { map['equipmentStatus'] = equipmentStatus.toJson(); diff --git a/lib/views/pages/user/requests/work_order/create_service_report.dart b/lib/views/pages/user/requests/work_order/create_service_report.dart index 0764b1c2..d1e5956d 100644 --- a/lib/views/pages/user/requests/work_order/create_service_report.dart +++ b/lib/views/pages/user/requests/work_order/create_service_report.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -180,8 +179,7 @@ class _CreateServiceReportState extends State with TickerPr assetId: _serviceReport.callRequest?.asset?.id, initialValue: (_serviceReport.assistantEmployees?.isNotEmpty ?? false) ? _serviceReport.assistantEmployees?.first : null, onSelect: (employee) { - log(employee.toJson().toString()); - _serviceReport.assistantEmployees = [employee]; + _serviceReport.assistantEmployees = [employee.copyWith(id: 0)]; }, ), 8.height, @@ -238,7 +236,7 @@ class _CreateServiceReportState extends State with TickerPr _serviceReport.attachmentsWorkOrder ??= []; if (_files.isEmpty) _serviceReport.attachmentsWorkOrder = []; for (var file in _files) { - _serviceReport.attachmentsWorkOrder.add(Attachment(name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}")); + _serviceReport.attachmentsWorkOrder.add(Attachment(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}")); } final user = Provider.of(context, listen: false).user; await _serviceRequestsProvider.createServiceReport(context, report: _serviceReport, request: widget.request, user: user); From 73d090cb9e2a56f19f7ac079bfd79c3db388ae4c Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 12:26:43 +0300 Subject: [PATCH 03/11] Edit wo only for eng --- .../pages/user/requests/work_order/work_orders_list_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index b12178c9..33cdde78 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -82,7 +82,7 @@ class WorkOrderListPage extends StatelessWidget { Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), ], ).expanded, - if (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) + if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) "edit".toSvgAsset(height: 48, width: 48).onPress(() { Navigator.of(context).push( MaterialPageRoute( From c281fba1ac128bd4bf2b973e9a515bbebdacb878 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 13:09:25 +0300 Subject: [PATCH 04/11] Enhancements --- lib/l10n/app_ar.arb | 2 + lib/l10n/app_en.arb | 3 +- lib/main.dart | 2 + .../work_order/work_order_details_page.dart | 98 +++++++++++++++++++ .../work_order/work_orders_list_page.dart | 38 +++---- 5 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 lib/views/pages/user/requests/work_order/work_order_details_page.dart diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index da3950b4..3a197653 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -208,6 +208,8 @@ "pickFromFiles" : "اختر من الملفات", "requiredFile" : "الملف مطلوب", "pickFile" : "اختر ملف", + "workOrder" : "طلب عمل", + "workOrders" : "طلبات عمل", "login" : "تسجيل الدخول", "enterCredsToLogin" : "أدخل بياناتك الخاصة لتسجيل الدخول", "forgotPassword" : "نسيت كلمة السر؟", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8ca93ef9..77f11ce2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -257,7 +257,8 @@ "filter" : "Filter", "pickAsset" : "Pick Asset", "firstAction" : "First Action", - "workOrder" : "Work Orders", + "workOrder" : "Work Order", + "workOrders" : "Work Orders", "viewWorkOrder" : "View All Work Order", "createWorkOrder" : "Create Work Order", "viewWorkOrder" : "View All Work Order", diff --git a/lib/main.dart b/lib/main.dart index be728ba2..3a361613 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -75,6 +75,7 @@ import 'package:test_sa/views/pages/user/report_issues_page.dart'; import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; import 'package:test_sa/views/pages/user/requests/requests_page.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; import 'package:test_sa/views/pages/user/visits/preventive_maintenance_visits_page.dart'; import 'package:test_sa/views/pages/user/visits/regular_visits_page.dart'; @@ -216,6 +217,7 @@ class MyApp extends StatelessWidget { AssetDetailPage.id: (_) => AssetDetailPage(), AssetSearchScreen.id: (_) => const AssetSearchScreen(), AssetFilterScreen.id: (_) => const AssetFilterScreen(), + WorkOrderDetailsPage.id: (_) => const WorkOrderDetailsPage(), }, ), ), diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart new file mode 100644 index 00000000..a9a4c9d8 --- /dev/null +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -0,0 +1,98 @@ +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/service_request/service_request.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/default_app_bar.dart'; + +import '../../../../../controllers/providers/api/user_provider.dart'; +import '../../../../../models/enums/user_types.dart'; +import '../../../../../models/service_request/search_work_order.dart'; +import '../../../../widgets/requests/request_status.dart'; + +class WorkOrderDetailsPage extends StatelessWidget { + static const String id = "/work_order_details_page"; + final SearchWorkOrder workOrder; + final ServiceRequest serviceRequest; + const WorkOrderDetailsPage({Key key, this.workOrder, this.serviceRequest}) : super(key: key); + + @override + Widget build(BuildContext context) { + UserProvider userProvider = Provider.of(context); + return Scaffold( + appBar: DefaultAppBar(title: context.translation.workOrder), + body: Column( + children: [ + SingleChildScrollView( + child: Container( + margin: const EdgeInsets.all(16), + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StatusLabel(label: workOrder.currentSituation.name, textColor: AppColor.orange60, backgroundColor: AppColor.orange40), + 8.height, + Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + 8.height, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text( + '${context.translation.status}: ${workOrder.currentSituation.name}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + ], + ).expanded, + Text(workOrder.visitDate?.toServiceRequestCardFormat ?? "", textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), + ], + ), + Text( + '${context.translation.orderWorkNumber}: ${workOrder.workOrderNo}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text( + '${context.translation.assignedEmployee}: ${workOrder.assignedEmployee?.name ?? ""}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text('${context.translation.assetSN}: ${workOrder.callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('${context.translation.assetNumber}: ${workOrder.callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('${context.translation.model}: ${workOrder.callRequest.asset.modelDefinition.modelName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('${context.translation.site}: ${workOrder.callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + Text('${"Call last Situation"}: ${workOrder.calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), + ], + ).paddingAll(16).onPress(() { + // onPressed(request); + }), + ), + ).expanded, + if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) + AppFilledButton( + onPressed: () { + /// todo zaid : push to update page + }, + label: context.translation.updateRequest, + ).paddingAll(16), + ], + ), + ); + } +} diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index 33cdde78..7fef1221 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -15,6 +15,7 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; class WorkOrderListPage extends StatelessWidget { @@ -36,14 +37,14 @@ class WorkOrderListPage extends StatelessWidget { } print("serviceRequest.statusValue:${serviceRequest.statusValue}"); return Scaffold( - appBar: DefaultAppBar(title: context.translation.workOrder), + appBar: DefaultAppBar(title: context.translation.workOrders), backgroundColor: const Color(0xfff8f9fb), body: SafeArea( child: FutureBuilder( future: serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), builder: (context, snap) { workOrders = snap.data as List; - if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); + if (snap.connectionState == ConnectionState.waiting) return const Center(child: CircularProgressIndicator()); return Column( children: [ @@ -104,33 +105,17 @@ class WorkOrderListPage extends StatelessWidget { children: [ Text( '${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), ), Text( '${context.translation.status}: ${workOrders[index].currentSituation.name}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), ), ], ).expanded, Text(workOrders[index].visitDate?.toServiceRequestCardFormat ?? "", textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), ], ), - Text( - '${context.translation.orderWorkNumber}: ${workOrders[index].workOrderNo}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - '${context.translation.assignedEmployee}: ${workOrders[index].assignedEmployee?.name ?? ""}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text('${context.translation.assetSN}: ${workOrders[index].callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), - Text('${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName ?? ""}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), - Text('${context.translation.assetNumber}: ${workOrders[index].callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), - Text('${context.translation.model}: ${workOrders[index].callRequest.asset.modelDefinition.modelName ?? ""}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), - Text('${context.translation.site}: ${workOrders[index].callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), - Text('${"Call last Situation"}: ${workOrders[index].calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), 16.height, Row( mainAxisSize: MainAxisSize.min, @@ -140,13 +125,14 @@ class WorkOrderListPage extends StatelessWidget { style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)), ), 4.width, - const Icon( - Icons.arrow_forward, - color: Color(0xFF4A8DB7), - size: 14, - ) + const Icon(Icons.arrow_forward, color: Color(0xFF4A8DB7), size: 14) ], - ), + ).onPress(() { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrders[index], serviceRequest: serviceRequest)), + ); + }), ], ).paddingAll(16).onPress(() { // onPressed(request); From 19845bd9d83a5ed925c242cfb04ef1542f6ebcb6 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 13:15:08 +0300 Subject: [PATCH 05/11] Enhancements --- lib/extensions/string_extensions.dart | 5 ++++ .../work_order/work_order_details_page.dart | 28 ++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 48d6e8b1..d0e7904f 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -5,4 +5,9 @@ extension StringExtensions on String { DateTime dateTime = DateTime.tryParse(this); return "${DateFormat('dd MMM, yyyy').format(dateTime)}\n${DateFormat('hh:mm a').format(dateTime)}"; } + + String get toServiceRequestDetailsFormat { + DateTime dateTime = DateTime.tryParse(this); + return "${DateFormat('dd MMM, yyyy').format(dateTime)} ${DateFormat('hh:mm a').format(dateTime)}"; + } } diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart index a9a4c9d8..c091422b 100644 --- a/lib/views/pages/user/requests/work_order/work_order_details_page.dart +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -31,6 +31,7 @@ class WorkOrderDetailsPage extends StatelessWidget { SingleChildScrollView( child: Container( margin: const EdgeInsets.all(16), + width: double.infinity, decoration: ShapeDecoration( color: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), @@ -44,25 +45,13 @@ class WorkOrderDetailsPage extends StatelessWidget { 8.height, Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), 8.height, - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName}', - style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), - ), - Text( - '${context.translation.status}: ${workOrder.currentSituation.name}', - style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), - ), - ], - ).expanded, - Text(workOrder.visitDate?.toServiceRequestCardFormat ?? "", textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), - ], + Text( + '${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), + ), + Text( + '${context.translation.status}: ${workOrder.currentSituation.name}', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), ), Text( '${context.translation.orderWorkNumber}: ${workOrder.workOrderNo}', @@ -72,6 +61,7 @@ class WorkOrderDetailsPage extends StatelessWidget { '${context.translation.assignedEmployee}: ${workOrder.assignedEmployee?.name ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)), ), + Text('${context.translation.visitDate}: ${workOrder.visitDate?.toServiceRequestDetailsFormat ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), Text('${context.translation.assetSN}: ${workOrder.callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), Text('${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), Text('${context.translation.assetNumber}: ${workOrder.callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))), From 477e6751aad8d4399e88345dfa6fd54b45eb8aeb Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Tue, 31 Oct 2023 13:16:31 +0300 Subject: [PATCH 06/11] Enhancements --- .../user/requests/work_order/work_order_details_page.dart | 5 ++++- .../user/requests/work_order/work_orders_list_page.dart | 6 +----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart index c091422b..efc0c920 100644 --- a/lib/views/pages/user/requests/work_order/work_order_details_page.dart +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -14,6 +14,7 @@ import '../../../../../controllers/providers/api/user_provider.dart'; import '../../../../../models/enums/user_types.dart'; import '../../../../../models/service_request/search_work_order.dart'; import '../../../../widgets/requests/request_status.dart'; +import 'future_service_report.dart'; class WorkOrderDetailsPage extends StatelessWidget { static const String id = "/work_order_details_page"; @@ -77,7 +78,9 @@ class WorkOrderDetailsPage extends StatelessWidget { if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) AppFilledButton( onPressed: () { - /// todo zaid : push to update page + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => FutureServiceReport(request: serviceRequest, workOrder: workOrder)), + ); }, label: context.translation.updateRequest, ).paddingAll(16), diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index 7fef1221..744e7a11 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -86,11 +86,7 @@ class WorkOrderListPage extends StatelessWidget { if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) "edit".toSvgAsset(height: 48, width: 48).onPress(() { Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, - workOrder: workOrders[index], - )), + MaterialPageRoute(builder: (_) => FutureServiceReport(request: serviceRequest, workOrder: workOrders[index])), ); }) ], From 18d0bdbd605ad62e748357d695d03579b368c49f Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Wed, 1 Nov 2023 10:07:58 +0300 Subject: [PATCH 07/11] Fix Service Details Design --- lib/main.dart | 2 + .../requests/service_request_details.dart | 65 +++++++++++-------- .../requests/update_service_request_page.dart | 20 ++++++ 3 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 lib/views/pages/user/requests/update_service_request_page.dart diff --git a/lib/main.dart b/lib/main.dart index 3a361613..c19c9bf6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -75,6 +75,7 @@ import 'package:test_sa/views/pages/user/report_issues_page.dart'; import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; import 'package:test_sa/views/pages/user/requests/requests_page.dart'; +import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; import 'package:test_sa/views/pages/user/visits/preventive_maintenance_visits_page.dart'; @@ -218,6 +219,7 @@ class MyApp extends StatelessWidget { AssetSearchScreen.id: (_) => const AssetSearchScreen(), AssetFilterScreen.id: (_) => const AssetFilterScreen(), WorkOrderDetailsPage.id: (_) => const WorkOrderDetailsPage(), + UpdateServiceRequestPage.id: (_) => const UpdateServiceRequestPage(), }, ), ), diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart index 2e83457b..20bdb790 100644 --- a/lib/views/pages/user/requests/service_request_details.dart +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -15,6 +15,7 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; @@ -54,45 +55,55 @@ class ServiceRequestDetailsPage extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - StatusLabel( - label: serviceRequest.priority.name, - id: serviceRequest.priority.id, - textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id), - backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)), - 8.width, - StatusLabel( - label: serviceRequest.statusLabel, - textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue), - backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)), - 1.width.expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + StatusLabel( + label: serviceRequest.priority.name, + id: serviceRequest.priority.id, + textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id), + backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)), + 8.width, + StatusLabel( + label: serviceRequest.statusLabel, + textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue), + backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)), + 1.width.expanded, + ], + ), + 8.height, + Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + 8.height, + Text( + '${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + 'Request Type: ${serviceRequest.type.name}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + 'Request No: ${serviceRequest.requestCode}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + ], + ).expanded, Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ if (_userProvider.user.type == UsersTypes.engineer) "edit".toSvgAsset(width: 48).onPress(() { - /// todo [zaid] : update service request + Navigator.push(context, MaterialPageRoute(builder: (context) => const UpdateServiceRequestPage())); }), if (_userProvider.user.type == UsersTypes.engineer) 16.height, Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), ], - ), + ) ], ), 8.height, - Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), - Text( - '${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - 'Request Type: ${serviceRequest.type.name}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - 'Request No: ${serviceRequest.requestCode}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - 8.height, const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), 8.height, Text( diff --git a/lib/views/pages/user/requests/update_service_request_page.dart b/lib/views/pages/user/requests/update_service_request_page.dart new file mode 100644 index 00000000..1e4b0cc3 --- /dev/null +++ b/lib/views/pages/user/requests/update_service_request_page.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; + +class UpdateServiceRequestPage extends StatelessWidget { + static const String id = "/update_service_request_page"; + const UpdateServiceRequestPage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DefaultAppBar(title: context.translation.updateServiceRequest), + body: SafeArea( + child: Column( + children: [], + ), + ), + ); + } +} From 8b7aa8235d2bef6c66984d2616b9ece338ba1f0b Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Wed, 1 Nov 2023 11:30:28 +0300 Subject: [PATCH 08/11] Update Service Request DONE --- .../api/service_requests_provider.dart | 1 + .../requests/create_service_request_page.dart | 4 + .../requests/first_action_bottom_sheet.dart | 2 +- .../requests/service_request_details.dart | 4 +- .../requests/update_service_request_page.dart | 163 +++++++++++++++++- lib/views/widgets/equipment/pick_asset.dart | 48 +++--- 6 files changed, 191 insertions(+), 31 deletions(-) diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index e3428ed3..6331eec6 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -233,6 +233,7 @@ class ServiceRequestsProvider extends ChangeNotifier { } Future updateRequest({ + @required BuildContext context, @required User user, @required ServiceRequest request, }) async { diff --git a/lib/views/pages/user/requests/create_service_request_page.dart b/lib/views/pages/user/requests/create_service_request_page.dart index c04d69d3..56d92c41 100644 --- a/lib/views/pages/user/requests/create_service_request_page.dart +++ b/lib/views/pages/user/requests/create_service_request_page.dart @@ -186,6 +186,10 @@ class CreateServiceRequestPageState extends State { controller: _commentController, labelText: context.translation.comments, suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), + initialValue: _serviceRequest.callComments, + onSaved: (text) { + _serviceRequest.callComments = text; + }, ), 8.height, RecordSound( diff --git a/lib/views/pages/user/requests/first_action_bottom_sheet.dart b/lib/views/pages/user/requests/first_action_bottom_sheet.dart index fcccef91..af0d539c 100644 --- a/lib/views/pages/user/requests/first_action_bottom_sheet.dart +++ b/lib/views/pages/user/requests/first_action_bottom_sheet.dart @@ -108,7 +108,7 @@ class _FirstActionBottomSheetState extends State { loading: snapshot.isLoading, onPressed: () async { _formKey.currentState.save(); - await snapshot.updateRequest(user: userProvider.user, request: _serviceRequest); + await snapshot.updateRequest(context: context, user: userProvider.user, request: _serviceRequest); Navigator.pop(context); }, ), diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart index 20bdb790..0ce5b97c 100644 --- a/lib/views/pages/user/requests/service_request_details.dart +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -93,9 +93,9 @@ class ServiceRequestDetailsPage extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - if (_userProvider.user.type == UsersTypes.engineer) + if (_userProvider.user.type == UsersTypes.normal_user) "edit".toSvgAsset(width: 48).onPress(() { - Navigator.push(context, MaterialPageRoute(builder: (context) => const UpdateServiceRequestPage())); + Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest))); }), if (_userProvider.user.type == UsersTypes.engineer) 16.height, Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), diff --git a/lib/views/pages/user/requests/update_service_request_page.dart b/lib/views/pages/user/requests/update_service_request_page.dart index 1e4b0cc3..d7fe80b5 100644 --- a/lib/views/pages/user/requests/update_service_request_page.dart +++ b/lib/views/pages/user/requests/update_service_request_page.dart @@ -1,20 +1,173 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; -class UpdateServiceRequestPage extends StatelessWidget { +import '../../../../models/lookup.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../providers/service_request_providers/equipment_status_provider.dart'; +import '../../../../providers/service_request_providers/priority_provider.dart'; +import '../../../../providers/service_request_providers/requested_through_provider.dart'; +import '../../../../providers/service_request_providers/type_of_request_provider.dart'; +import '../../../widgets/equipment/pick_asset.dart'; +import '../../../widgets/images/multi_image_picker.dart'; +import '../../../widgets/sound/record_sound.dart'; + +class UpdateServiceRequestPage extends StatefulWidget { static const String id = "/update_service_request_page"; - const UpdateServiceRequestPage({Key key}) : super(key: key); + final ServiceRequest serviceRequest; + const UpdateServiceRequestPage({Key key, this.serviceRequest}) : super(key: key); + + @override + State createState() => _UpdateServiceRequestPageState(); +} + +class _UpdateServiceRequestPageState extends State { + final GlobalKey _formKey = GlobalKey(); + TextEditingController _commentController; + List _deviceImages = []; + UserProvider _userProvider; + + @override + void initState() { + super.initState(); + _deviceImages = widget.serviceRequest.devicePhotos.map((e) => File(e)).toList(); + _commentController = TextEditingController(text: widget.serviceRequest.callComments ?? ""); + } + + @override + void dispose() { + _commentController.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { + _userProvider = Provider.of(context, listen: false); return Scaffold( appBar: DefaultAppBar(title: context.translation.updateServiceRequest), body: SafeArea( - child: Column( - children: [], - ), + child: Form( + key: _formKey, + child: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PickAsset( + editable: false, + device: widget.serviceRequest.device, + onPickAsset: (asset) { + widget.serviceRequest.device = asset; + setState(() {}); + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.priority, + initialValue: widget.serviceRequest?.priority, + onSelect: (value) { + widget.serviceRequest.priority = value; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.equipmentStatus, + initialValue: widget.serviceRequest?.defectType, + onSelect: (value) { + widget.serviceRequest.defectType = value; + }, + ), + 8.height, + Consumer(builder: (context, snapshot, _) { + return SingleItemDropDownMenu( + context: context, + enabled: false, + title: context.translation.requestedThrough, + initialValue: snapshot.items?.firstWhere((element) => element.value == 3, orElse: () => null), + ); + }), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.typeOfRequest, + initialValue: widget.serviceRequest?.type, + onSelect: (value) { + widget.serviceRequest.type = value; + }, + ), + 8.height, + MultiFilesPicker( + label: context.translation.attachImage, + onlyImages: true, + files: _deviceImages, + ), + ((widget.serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height, + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.callComments.heading5(context), + ), + 8.height, + AppTextFormField( + controller: _commentController, + labelText: context.translation.comments, + initialValue: widget.serviceRequest.callComments, + suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), + onSaved: (text) { + widget.serviceRequest.callComments = text; + }, + ), + 8.height, + RecordSound( + onRecord: (audio) { + widget.serviceRequest.audio = audio; + }, + enabled: widget.serviceRequest == null ? true : false, + ), + 16.height, + ], + ), + ).expanded, + AppFilledButton(onPressed: _submit, label: context.translation.submitRequest), + ], + ), + ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), ), ); } + + Future _submit() async { + widget.serviceRequest?.requestedThrough = Provider.of(context, listen: false).items?.firstWhere((element) => element.value == 3, orElse: () => null); + if (_formKey.currentState.validate() && await widget.serviceRequest.validateNewRequest(context)) { + _formKey.currentState.save(); + widget.serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); + if (widget.serviceRequest.audio != null) { + if (_isLocalUrl(widget.serviceRequest.audio)) { + final File file = File(widget.serviceRequest.audio); + widget.serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; + } + } + await Provider.of(context, listen: false).updateRequest(context: context, user: _userProvider.user, request: widget.serviceRequest); + } + } + + bool _isLocalUrl(String url) { + if (url?.isEmpty != false) return false; + return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); + } } diff --git a/lib/views/widgets/equipment/pick_asset.dart b/lib/views/widgets/equipment/pick_asset.dart index e3cddf2b..756deff6 100644 --- a/lib/views/widgets/equipment/pick_asset.dart +++ b/lib/views/widgets/equipment/pick_asset.dart @@ -12,36 +12,38 @@ import '../../../new_views/common_widgets/asset_info_card.dart'; class PickAsset extends StatelessWidget { final Function(Asset) onPickAsset; final Asset device; + final bool editable; - const PickAsset({Key key, this.device, this.onPickAsset}) : super(key: key); + const PickAsset({Key key, this.editable = true, this.device, this.onPickAsset}) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + if (editable) + Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + ], + ).onPress(() async { + Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset; + onPickAsset(device); + }).expanded, + "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70), + ], + ), ), - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), - context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), - ], - ).onPress(() async { - Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset; - onPickAsset(device); - }).expanded, - "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70), - ], - ), - ), if (device != null) AssetInfoCard(asset: device).paddingOnly(top: 8), ], ); From c3d6643ead4e9202a309e73991a10467e0063773 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Wed, 1 Nov 2023 11:46:54 +0300 Subject: [PATCH 09/11] Enhancements --- .../providers/api/service_requests_provider.dart | 6 +----- .../user/requests/create_service_request_page.dart | 6 +----- .../user/requests/first_action_bottom_sheet.dart | 2 +- .../user/requests/update_service_request_page.dart | 11 +++++------ 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 6331eec6..9c18b46d 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -232,11 +232,7 @@ class ServiceRequestsProvider extends ChangeNotifier { } } - Future updateRequest({ - @required BuildContext context, - @required User user, - @required ServiceRequest request, - }) async { + Future updateRequest({@required User user, @required ServiceRequest request}) async { isLoading = true; notifyListeners(); Map serviceRequest = await getServiceRequestById(requestId: request.id) ?? ""; diff --git a/lib/views/pages/user/requests/create_service_request_page.dart b/lib/views/pages/user/requests/create_service_request_page.dart index 56d92c41..fbad447e 100644 --- a/lib/views/pages/user/requests/create_service_request_page.dart +++ b/lib/views/pages/user/requests/create_service_request_page.dart @@ -171,11 +171,7 @@ class CreateServiceRequestPageState extends State { }, ), 8.height, - MultiFilesPicker( - label: context.translation.attachImage, - onlyImages: true, - files: _deviceImages, - ), + MultiFilesPicker(label: context.translation.attachImage, files: _deviceImages), ((_serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height, Align( alignment: AlignmentDirectional.centerStart, diff --git a/lib/views/pages/user/requests/first_action_bottom_sheet.dart b/lib/views/pages/user/requests/first_action_bottom_sheet.dart index af0d539c..fcccef91 100644 --- a/lib/views/pages/user/requests/first_action_bottom_sheet.dart +++ b/lib/views/pages/user/requests/first_action_bottom_sheet.dart @@ -108,7 +108,7 @@ class _FirstActionBottomSheetState extends State { loading: snapshot.isLoading, onPressed: () async { _formKey.currentState.save(); - await snapshot.updateRequest(context: context, user: userProvider.user, request: _serviceRequest); + await snapshot.updateRequest(user: userProvider.user, request: _serviceRequest); Navigator.pop(context); }, ), diff --git a/lib/views/pages/user/requests/update_service_request_page.dart b/lib/views/pages/user/requests/update_service_request_page.dart index d7fe80b5..9af6081f 100644 --- a/lib/views/pages/user/requests/update_service_request_page.dart +++ b/lib/views/pages/user/requests/update_service_request_page.dart @@ -15,6 +15,7 @@ import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import '../../../../models/lookup.dart'; import '../../../../new_views/app_style/app_color.dart'; import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_lazy_loading.dart'; import '../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; import '../../../../providers/service_request_providers/equipment_status_provider.dart'; @@ -112,11 +113,7 @@ class _UpdateServiceRequestPageState extends State { }, ), 8.height, - MultiFilesPicker( - label: context.translation.attachImage, - onlyImages: true, - files: _deviceImages, - ), + MultiFilesPicker(label: context.translation.attachImage, files: _deviceImages), ((widget.serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height, Align( alignment: AlignmentDirectional.centerStart, @@ -162,7 +159,9 @@ class _UpdateServiceRequestPageState extends State { widget.serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; } } - await Provider.of(context, listen: false).updateRequest(context: context, user: _userProvider.user, request: widget.serviceRequest); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + await Provider.of(context, listen: false).updateRequest(user: _userProvider.user, request: widget.serviceRequest); + Navigator.of(context).pop(); } } From daa427bac2a514050ca53b9e8d9f210b1864fc68 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Wed, 1 Nov 2023 14:36:18 +0300 Subject: [PATCH 10/11] Update Work Order Screen DONE --- .../api/service_requests_provider.dart | 70 +- lib/l10n/app_ar.arb | 3 +- lib/l10n/app_en.arb | 3 +- .../requests/update_service_request_page.dart | 2 +- .../work_order/create_service_report.dart | 1 + .../work_order/edit_service_report.dart | 1166 +++-------------- ...report.dart => update_service_report.dart} | 27 +- .../work_order/work_order_details_page.dart | 4 +- .../work_order/work_orders_list_page.dart | 4 +- .../widgets/e_signature/e_signature.dart | 18 +- 10 files changed, 209 insertions(+), 1089 deletions(-) rename lib/views/pages/user/requests/work_order/{future_service_report.dart => update_service_report.dart} (53%) diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 9c18b46d..41c75d37 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -461,42 +461,28 @@ class ServiceRequestsProvider extends ChangeNotifier { } } - Future updateServiceReport({ - @required ServiceReport report, - String host, - User user, - ServiceRequest request, - }) async { + Future updateServiceReport(BuildContext context, {@required ServiceReport report}) async { Response response; - //Map body = report.toMap(request); - // body["uid"] = user.id; - // body["token"] = user.token; - // body["job_id"] = request.id; - // body["report_id"] = request.reportID; - // try { + report.callRequest = CallRequest(id: report.callRequest.id); Map body = report.toJson(); - - /// todo [zaid] : don't forget to add [request] data to [body] - // Map body = report.toMap(request); - // body["uid"] = user.id; - // body["token"] = user.token; - response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); - // response = await post( - // Uri.parse( - // host+URLs.updateServiceReport), - // body: body, - // ); - // stateCode = response.statusCode; - - if (response.statusCode >= 200 && response.statusCode < 300) { - reset(); - notifyListeners(); + try { + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); + if (response.statusCode >= 200 && response.statusCode < 300) { + reset(); + notifyListeners(); + Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); + Navigator.of(context).pop(); + } else { + Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest}"); + } + Navigator.of(context).pop(); + return response.statusCode; + } catch (e) { + print(e); + Navigator.of(context).pop(); + return -1; } - return response.statusCode; - // } catch (error) { - // print(error); - // return -1; - // } } Future updateWorkOrderDetails({@required SearchWorkOrder workOrder}) async { @@ -560,28 +546,20 @@ class ServiceRequestsProvider extends ChangeNotifier { } } - Future getSingleServiceReport({ - @required int reportId, - @required String host, - @required User user, - @required AppLocalizations subtitle, - }) async { + Future getSingleServiceReport(BuildContext context, {@required int reportId}) async { Response response; try { - response = await ApiManager.instance.get( - URLs.getServiceReport + "?workOrderId=$reportId", - ); + response = await ApiManager.instance.get(URLs.getServiceReport + "?workOrderId=$reportId"); } catch (error) { - throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle)); + throw (context.translation.failedToCompleteRequest); } // If the call to the server was successful, parse the JSON. if (response.statusCode >= 200 && response.statusCode < 300) { // If the call to the server was successful, parse the JSON. - /// todo [zaid]: check [reportId] below - return ServiceReport.fromJson(json.decode(response.body)["data"] /*, reportId*/); + return ServiceReport.fromJson(json.decode(response.body)["data"]); } else { - throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle)); + throw (("${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}")); } } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 3a197653..20102d21 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -295,5 +295,6 @@ "assistantEmployee" : "موظف مساعد", "assignAssistant" : "تعيين مساعد", "partNo" : "الجزء رقم", - "engSign" : "توقيع المهندس" + "engSign" : "توقيع المهندس", + "updateWorkOrder" : "تعديل طلب العمل" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 77f11ce2..5233fb33 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -299,5 +299,6 @@ "assistantEmployee" : "Assistant Employee", "assignAssistant" : "Assign Assistant", "partNo" : "Part No.", - "engSign" : "Engineer Signature" + "engSign" : "Engineer Signature", + "updateWorkOrder" : "Update Work Order" } \ No newline at end of file diff --git a/lib/views/pages/user/requests/update_service_request_page.dart b/lib/views/pages/user/requests/update_service_request_page.dart index 9af6081f..d7e7a395 100644 --- a/lib/views/pages/user/requests/update_service_request_page.dart +++ b/lib/views/pages/user/requests/update_service_request_page.dart @@ -140,7 +140,7 @@ class _UpdateServiceRequestPageState extends State { ], ), ).expanded, - AppFilledButton(onPressed: _submit, label: context.translation.submitRequest), + AppFilledButton(onPressed: _submit, label: context.translation.updateRequest), ], ), ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), diff --git a/lib/views/pages/user/requests/work_order/create_service_report.dart b/lib/views/pages/user/requests/work_order/create_service_report.dart index d1e5956d..4383e6ff 100644 --- a/lib/views/pages/user/requests/work_order/create_service_report.dart +++ b/lib/views/pages/user/requests/work_order/create_service_report.dart @@ -208,6 +208,7 @@ class _CreateServiceReportState extends State with TickerPr ), 8.height, MultiFilesPicker(label: context.translation.attachImage, files: _files), + 8.height, ESignature( title: context.translation.engSign, oldSignature: _serviceReport.engSignature, diff --git a/lib/views/pages/user/requests/work_order/edit_service_report.dart b/lib/views/pages/user/requests/work_order/edit_service_report.dart index 8915d49e..34d2c562 100644 --- a/lib/views/pages/user/requests/work_order/edit_service_report.dart +++ b/lib/views/pages/user/requests/work_order/edit_service_report.dart @@ -1,33 +1,36 @@ +import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/api_routes/http_status_manger.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_last_calls_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_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/controllers/validator/validator.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.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/views/app_style/colors.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.dart'; -import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; -import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_equipment_status.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_fault_description.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; -import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../../../../../attachment.dart'; +import '../../../../../models/lookup.dart'; +import '../../../../../models/service_request/spare_parts.dart'; import '../../../../../models/service_request/wo_call_request.dart'; +import '../../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../../providers/loading_list_notifier.dart'; +import '../../../../../providers/work_order/reason_provider.dart'; +import '../../../../../providers/work_order/service_type_provider.dart'; +import '../../../../widgets/date_and_time/date_picker.dart'; +import '../../../../widgets/e_signature/e_signature.dart'; import '../../../../widgets/images/multi_image_picker.dart'; +import '../../../../widgets/status/report/service_report_assistant_employee_menu.dart'; class EditServiceReport extends StatefulWidget { static final String id = "/edit-service-report"; @@ -44,35 +47,31 @@ class _EditServiceReportState extends State with TickerProvid UserProvider _userProvider; SettingProvider _settingProvider; ServiceRequestsProvider _serviceRequestsProvider; - - bool _validate = false; + List _spareParts = []; ServiceReport _serviceReport; bool _isLoading = false; - bool _showCommentField = false; - - List _images = []; + List _files = []; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); - TextEditingController _faultController = TextEditingController(); - TextEditingController _workPreformedController = TextEditingController(); - + final TextEditingController _faultController = TextEditingController(); + final TextEditingController _workPreformedController = TextEditingController(); ServiceStatusProvider _assetTypeProvider; - CallRequest _callRequestForWorkOrder; @override void initState() { _serviceReport = widget.report; - // _images = widget.report?.files?.map((e) => File(e))?.toList(); + _files = widget.report?.attachmentsWorkOrder?.map((e) => File(e.name))?.toList(); + _spareParts = _serviceReport.sparePartsWorkOrders.map((e) => e.sparePart).toList(); super.initState(); } void getRequestForWorkOrder() async { _isLoading = true; setState(() {}); - _callRequestForWorkOrder = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id); - // _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson()); - await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _callRequestForWorkOrder = await _serviceRequestsProvider?.getCallRequestForWorkOrder(callId: widget.request.id); + _serviceReport.assignedEmployee = _callRequestForWorkOrder?.assignedEmployee; + await _assetTypeProvider?.getTypes(user: _userProvider.user, host: _settingProvider.host); _isLoading = false; setState(() {}); } @@ -89,18 +88,14 @@ class _EditServiceReportState extends State with TickerProvid _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _serviceRequestsProvider = Provider.of(context); - _assetTypeProvider = Provider.of(context); if (_callRequestForWorkOrder == null) { getRequestForWorkOrder(); } - _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( - (element) => element.value == _callRequestForWorkOrder?.assetType, - orElse: () => null, - ); - + _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere((element) => element.value == _callRequestForWorkOrder?.assetType, orElse: () => null); return Scaffold( key: _scaffoldKey, + appBar: DefaultAppBar(title: context.translation.updateWorkOrder), body: SafeArea( child: LoadingManager( isLoading: _isLoading, @@ -109,990 +104,143 @@ class _EditServiceReportState extends State with TickerProvid onRefresh: () async {}, child: Form( key: _formKey, - child: Stack( + child: Column( children: [ - ListView( - padding: const EdgeInsets.all(16), - children: [ - const SizedBox(height: 16), - Center( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - context.translation.editServiceReport, - style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold), - ), + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + widget.request.hospitalName.heading5(context), + 8.height, + "${context.translation.assetNo}: ${widget.request.deviceNumber}".bodyText(context), + "${context.translation.callId}: ${widget.request.requestCode}".bodyText(context), + ], + ).paddingAll(16), ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle("Caller Info"), - const SizedBox(height: 8), - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - margin: const EdgeInsets.symmetric(vertical: 16), - decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ - BoxShadow( - color: AColors.grey, - offset: Offset(0, -1), - ) - ]), - child: Wrap( - direction: Axis.vertical, - spacing: 10, - children: [ - ASubTitle( - "${context.translation.callId}: ${widget.request.requestCode}", - font: 14, - ), - ASubTitle( - "${context.translation.assetNumber}: ${widget.request.deviceNumber}", - font: 14, - ), - widget.request.deviceSerialNumber == null - ? const SizedBox() - : ASubTitle( - "${context.translation.deviceSN}: ${widget.request.deviceSerialNumber}", - font: 14, - ), - Text( - "${context.translation.customer}: ${widget.request.hospitalName}", - style: Theme.of(context).textTheme.subtitle1.copyWith( - fontWeight: FontWeight.bold, - fontSize: 12, - ), - textScaleFactor: AppStyle.getScaleFactor(context), - ) - ], - ), - ), - const SizedBox(height: 8), - ASubTitle("Work Order Details"), - const SizedBox(height: 8), - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - margin: const EdgeInsets.symmetric(vertical: 16), - decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ - BoxShadow( - color: AColors.grey, - offset: Offset(0, -1), - ) - ]), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Report type and Reasons - // Row( - // children: [ - // // Report Status - // // Expanded( - // // child: Column( - // // crossAxisAlignment: CrossAxisAlignment.start, - // // children: [ - // // ASubTitle(context.translation.reportType), - // // _validate && _serviceReport.type == null - // // ? ASubTitle( - // // context.translation.requiredWord, - // // color: Colors.red, - // // ) - // // : const SizedBox.shrink(), - // // const SizedBox( - // // height: 4, - // // ), - // // ServiceReportTypeMenu( - // // initialValue: _serviceReport.type, - // // onSelect: (status) { - // // _serviceReport.type = status; - // // }, - // // ), - // // ], - // // ), - // // ), - // // const SizedBox( - // // width: 8, - // // ), - // // visit date - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.visitDate), - // _validate && _serviceReport.visitDate == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // Row( - // children: [ - // Expanded( - // child: ADatePicker( - // date: _serviceReport.visitDate, - // from: DateTime.now().subtract(const Duration(days: 365)), - // to: DateTime.now().add(const Duration(days: 365)), - // onDatePicker: (date) { - // _serviceReport.visitDate = date; - // setState(() {}); - // }, - // ), - // ), - // ], - // ), - // ], - // ), - // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // device sn - // Visibility( - // visible: widget.request.deviceSerialNumber == null, - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.deviceSN), - // _validate && _serviceReport.device?.id == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // AutoCompleteDeviceField( - // hospitalId: widget.request.hospitalId, - // initialValue: _serviceReport.device, - // onPick: (id) { - // _serviceReport.device.id = id; - // }, - // ), - // const SizedBox(height: 8), - // ], - // ), - // ), - const SizedBox(height: 8), - ASubTitle(context.translation.assetType), - _validate && _serviceReport.assetType == null - ? ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - LoadingManager( - isLoading: _assetTypeProvider.isLoading, - isFailedLoading: _assetTypeProvider.statuses == null, - stateCode: _assetTypeProvider.stateCode, - onRefresh: () async { - _assetTypeProvider.reset(); - await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); - _serviceReport?.assetType = _assetTypeProvider.statuses?.firstWhere( - (element) => element.value == _callRequestForWorkOrder.assetType, - orElse: () => null, - ); - }, - child: ATextFormField( - initialValue: _serviceReport?.assetType?.name ?? "NULL", - textAlign: TextAlign.center, - enable: false, - style: Theme.of(context).textTheme.titleMedium, - ), - ), - // ServiceAssetTypeMenu( - // initialValue: _serviceReport.assetType, - // onSelect: (status) { - // _serviceReport.assetType = status; - // }, - // ), - const SizedBox( - height: 8, - ), - Row( - children: [ - // report status - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // ASubTitle(context.translation.reportStatus), - ASubTitle("Equipment Status"), - _validate && _serviceReport.equipmentStatus == null - ? ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox( - height: 4, - ), - // ServiceReportStatusMenu( - // report: _serviceReport, - // request: widget.request, - // onSelect: (status) { - // _serviceReport.status = status; - // }, - // ), - ServiceReportEquipmentStatusMenu( - report: _serviceReport, - request: widget.request, - onSelect: (status) { - _serviceReport.equipmentStatus = status; - }, - ) - ], - ), - ), - const SizedBox( - width: 8, - ), - // Provider.of(context).isLoading == null - // ? const SizedBox.shrink(): - // Call's last Situation - Consumer( - builder: (_, provider, __) { - if (provider.isLoading == null) return const SizedBox.shrink(); - return Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(context.translation.callLastSituation), - _validate && _serviceReport.calllastSituation == null - ? ASubTitle( - context.translation.requiredWord, - color: Colors.red, - ) - : const SizedBox.shrink(), - const SizedBox(height: 4), - ServiceReportLastCallsMenu( - report: _serviceReport, - onSelect: (status) { - if (status?.value == 12 || _serviceReport.calllastSituation?.value == 12) { - _serviceReport.calllastSituation = status; - setState(() {}); - } else { - _serviceReport.calllastSituation = status; - setState(() {}); - } - }, - ), - ], - ), - ); - }, - ), - ], - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Return to Service"), - // Row( - // children: [ - // Expanded( - // child: ADatePicker( - // date: _serviceReport.returnToService, - // from: DateTime.now().subtract(const Duration(days: 365)), - // to: DateTime.now().add(const Duration(days: 365)), - // onDatePicker: (date) { - // _serviceReport.returnToService = date; - // setState(() {}); - // }, - // ), - // ), - // ], - // ), - if (_serviceReport?.calllastSituation?.value == 2) - Column( - children: [ - const SizedBox( - height: 8, - ), - ATextFormField( - initialValue: _serviceReport?.reviewComment, - hintText: "Vendor Name", - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport.reviewComment = value; - }, - ), - const SizedBox( - height: 8, - ), - ATextFormField( - initialValue: _serviceReport?.reviewComment, - hintText: "Vendor Engineer", - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport.reviewComment = value; - }, - ), - ], - ), - if (_showCommentField) - const SizedBox( - height: 8, - ), - if (_showCommentField) - ATextFormField( - initialValue: _serviceReport?.reviewComment, - hintText: "Review Comment", - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport.reviewComment = value; - }, - ), - - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - // const ASubTitle("Assign Employee"), - // const SizedBox( - // height: 8, - // ), - // _validate && _serviceReport.engineer == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // const SizedBox( - // height: 4, - // ), - // EngineersMenu( - // initialValue: _serviceReport.engineer, - // onSelect: (engineer) { - // _serviceReport.engineer = engineer; - // }, - // ), - // const SizedBox( - // height: 8, - // ), - // Report status and Service Type - // Row( - // children: [ - // // report status - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.reportStatus), - // _validate && _serviceReport.equipmentStatus == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // const SizedBox( - // height: 4, - // ), - // ServiceReportStatusMenu( - // report: _serviceReport, - // request: widget.request, - // onSelect: (status) { - // _serviceReport.equipmentStatus = status; - // }, - // ), - // ], - // ), - // ), - // const SizedBox( - // width: 8, - // ), - // Consumer( - // builder: (_, provider, __) { - // if (provider.isLoading == null) return const SizedBox.shrink(); - // return Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.callLastSituation), - // _validate && _serviceReport.callLastSituation == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // const SizedBox( - // height: 4, - // ), - // ServiceReportLastCallsMenu( - // report: _serviceReport, - // onSelect: (status) { - // if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { - // _serviceReport.callLastSituation = status; - // setState(() {}); - // } else { - // _serviceReport.callLastSituation = status; - // } - // }, - // ), - // ], - // ), - // ); - // }, - // ), - // ], - // ), - const SizedBox( - height: 8, - ), - // invoice number & code - _serviceReport.calllastSituation?.value != 12 - ? const SizedBox.shrink() - : Row( - children: [ - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.invoiceNumber), - // const SizedBox( - // height: 8, - // ), - // ATextFormField( - // initialValue: _serviceReport?.invoiceNumber, - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value) { - // _serviceReport.invoiceNumber = value; - // }, - // ), - // ], - // ), - // ), - const SizedBox( - width: 8, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(context.translation.invoiceCode), - const SizedBox( - height: 4, - ), - // ATextFormField( - // initialValue: _serviceReport?.invoiceCode, - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredWord, - // textInputType: TextInputType.text, - // onSaved: (value) { - // _serviceReport.invoiceCode = value; - // }, - // ), - ], - ), - ), - ], - ), - - // const SizedBox(height: 8,), - // Row( - // children: [ - // ASubTitle(context.translation.faultDescription), - // Expanded( - // child: SizedBox( - // height: 32 * AppStyle.getScaleFactor(context), - // child: SpeechToTextButton( - // controller: _faultController, - // mini: true, - // ), - // ), - // ), - // ], - // ), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.faultDescriptionId, - // textAlign: TextAlign.center, - // controller: _faultController, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.hasValue(value) - // ? null : context.translation.requiredWord, - // textInputType: TextInputType.multiline, - // onSaved: (value){ - // _serviceReport.faultDescriptionId = value; - // }, - // ), - // const SizedBox(height: 8,), - // Row( - // children: [ - // ASubTitle(context.translation.workPreformed), - // Expanded( - // child: SizedBox( - // height: 32 * AppStyle.getScaleFactor(context), - // child: SpeechToTextButton( - // controller: _workPreformedController, - // mini: true, - // ), - // ), - // ), - // ], - // ), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.workPreformed, - // textAlign: TextAlign.center, - // controller: _workPreformedController, - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.hasValue(value) - // ? null : context.translation.requiredWord, - // textInputType: TextInputType.multiline, - // onSaved: (value){ - // _serviceReport.workPreformed = value; - // }, - // ), - // const SizedBox(height: 8,), - const SizedBox(height: 8), - ASubTitle(context.translation.workingHours), - const SizedBox(height: 8), - // Row( - // children: [ - // Expanded( - // child: AppTimer( - // timer: _serviceReport.timer, - // enabled: false, - // // onChange: (timer) async { - // // _serviceReport.timer = timer; - // // _serviceReport.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); - // // return true; - // // }, - // ), - // ), - // ], - // ), - const SizedBox(height: 16), - if (_showCommentField) - const SizedBox( - height: 8, - ), - if (_showCommentField) - ATextFormField( - initialValue: _serviceReport?.reviewComment, - hintText: "Review Comment", - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport.reviewComment = value; - }, - ), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - const SizedBox(height: 8), - ASubTitle(context.translation.faultDescription), - const SizedBox( - height: 4, - ), - ServiceReportFaultDescription( - requestId: widget.request?.id, - initialValue: _serviceReport.faultDescription, - onSelect: (status) { - _serviceReport.faultDescription = status; - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - if (mounted) setState(() {}); - }); - }, - ), - const SizedBox(height: 8), - const ASubTitle("Solutions"), - const SizedBox(height: 4), - ATextFormField( - initialValue: "_serviceReport?.workPreformed", - textAlign: TextAlign.center, - enable: false, - hintText: _serviceReport.faultDescription?.workPerformed ?? "", - controller: _workPreformedController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredWord, - textInputType: TextInputType.multiline, - onSaved: (value) { - // _serviceReport.workPreformed = value; - }, - ), - const SizedBox(height: 4), - ASubTitle("Failure Reason"), - const SizedBox( - height: 4, - ), - ServiceReportReasonsMenu( - initialValue: _serviceReport.reason, - onSelect: (status) { - _serviceReport.reason = status; - }, - ), - const SizedBox( - height: 8, - ), - ASubTitle(context.translation.attachImage), - const SizedBox( - height: 4, - ), - MultiFilesPicker( - label: "", - files: _images, - ), - // AMiniOneImagePicker( - // //error: _validate && _serviceReport.image == null, - // image: _image, - // onPick: (image) { - // _image = image; - // _serviceReport.image = base64Encode(image.readAsBytesSync()); - // }, - // ), - const SizedBox( - height: 8, - ), - const SizedBox(height: 8), - ASubTitle(context.translation.repairLocation), - const SizedBox(height: 4), - ServiceReportRepairLocation( - initialValue: _serviceReport.repairLocation, - onSelect: (status) { - _serviceReport.repairLocation = status; - }, - ), - const SizedBox(height: 16), - ASubTitle("Travel Expenses"), - const SizedBox( - height: 4, - ), - ATextFormField( - initialValue: " _serviceReport?.travelingExpense?.toString()", - hintText: context.translation.travelingExpense, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.number, - onSaved: (value) { - // if (value != null && value.isEmpty) { - // _serviceReport.travelingExpense = num.tryParse(_serviceReport?.travelingExpense?.toString() ?? "") ?? 0; - // } else - // _serviceReport.travelingExpense = num.tryParse(value) ?? 0; - }, - ), - - const SizedBox(height: 8), - ASubTitle(context.translation.travelingHours), - const SizedBox(height: 4), - ATextFormField( - initialValue: _serviceReport?.travelingHours?.toString(), - textAlign: TextAlign.center, - hintText: "i.e 3, 3.5, 4", - style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : context.translation.requiredWord, - textInputType: TextInputType.number, - onSaved: (value) { - _serviceReport.travelingHours = double.tryParse(value) ?? 0.0; - }, - ), - // Traveling Hours & Working Hours - // Row( - // children: [ - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.workingHours), - // const SizedBox( - // height: 8, - // ), - // Row( - // children: [ - // Expanded( - // child: AppTimer( - // timer: _serviceReport.timer, - // onChange: (timer) async { - // _serviceReport.timer = timer; - // return true; - // }, - // ), - // ), - // ], - // ), - // // ATextFormField( - // // initialValue: _serviceReport?.workHours, - // // textAlign: TextAlign.center, - // // hintText: "i.e 3, 3.5, 4", - // // style: Theme.of(context).textTheme.subtitle1, - // // validator: (value) => - // // Validator.isNumeric(value) - // // ? null : context.translation.requiredWord, - // // textInputType: TextInputType.number, - // // onSaved: (value){ - // // _serviceReport.workHours = value; - // // }, - // // ), - // ], - // ), - // ), - // // const SizedBox(width: 8,), - // // Expanded( - // // child: Column( - // // crossAxisAlignment: CrossAxisAlignment.start, - // // children: [ - // // ASubTitle(context.translation.travelingHours), - // // const SizedBox(height: 4,), - // // ATextFormField( - // // initialValue: _serviceReport?.travelingHours, - // // textAlign: TextAlign.center, - // // hintText: "i.e 3, 3.5, 4", - // // style: Theme.of(context).textTheme.subtitle1, - // // validator: (value) => - // // Validator.isNumeric(value) - // // ? null : context.translation.requiredWord, - // // textInputType: TextInputType.number, - // // onSaved: (value){ - // // _serviceReport.travelingHours = value; - // // }, - // // ), - // // ], - // // ), - // // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // Operating Hours and Job Sheet Number - // Row( - // children: [ - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.operatingHours), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.operatingHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : context.translation.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.operatingHours = value; - // }, - // ), - // ], - // ), - // ), - // const SizedBox(width: 8,), - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.jobSheetNumber), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.jobSheetNumber, - // textAlign: TextAlign.center, - // style: Theme.of(context).textTheme.subtitle1, - // textInputType: TextInputType.name, - // onSaved: (value){ - // _serviceReport.jobSheetNumber = value; - // }, - // ), - // ], - // ), - // ), - // ], - // ), - //const SizedBox(height: 8,), - - const SizedBox(height: 8), - const ASubTitle("Technical comment"), - const SizedBox(height: 4), - ATextFormField( - initialValue: _serviceReport?.comment, - hintText: "Technical Comment", - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceReport.comment = value; - }, - ), - const SizedBox(height: 8), - const ASubTitle("Nurse Signature"), - // ESignature( - // oldSignature: _serviceReport.signatureNurse, - // newSignature: _serviceReport.localNurseSignature, - // onSaved: (signature) { - // if (signature == null || signature.isEmpty) { - // return; - // } - // _serviceReport.localNurseSignature = signature; - // _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - // }, - // ), - // const SizedBox( - // height: 8, - // ), - // const ASubTitle("Engineer Signature"), - // ESignature( - // oldSignature: _serviceReport.signatureEngineer, - // newSignature: _serviceReport.localNurseSignature, - // onSaved: (signature) { - // if (signature == null || signature.isEmpty) { - // return; - // } - // _serviceReport.localNurseSignature = signature; - // _serviceReport.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - // }, - // ), - const SizedBox( - height: 8, - ), - // Part Number and Quantity - ], - ), - ), - ], - ), - ASubTitle("Spare Parts"), - Container( - width: double.infinity, - padding: const EdgeInsets.all(16), - margin: const EdgeInsets.symmetric(vertical: 16), - decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ - BoxShadow( - color: AColors.grey, - offset: Offset(0, -1), - ) - ]), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Row( - // children: [ - // Expanded( - // flex: 3, - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(context.translation.partNumberName), - // _validate && _serviceReport.parts == null - // ? ASubTitle( - // context.translation.requiredWord, - // color: Colors.red, - // ) - // : const SizedBox.shrink(), - // const SizedBox( - // height: 4, - // ), - // AutoCompletePartsField( - // assetId: _serviceReport?.device?.id, - // onPick: (part) { - // _serviceReport.parts.add(part); - // setState(() {}); - // }, - // ), - // ], - // ), - // ), - // ], - // ), - SizedBox( - height: 8 * AppStyle.getScaleFactor(context), - ), - Row( - children: [ - Expanded(flex: 3, child: Text(context.translation.number)), - Expanded(flex: 1, child: Text(context.translation.quantity)), - ], - ), - // Column( - // children: List.generate(_serviceReport.parts.length, (index) { - // Part _part = _serviceReport.parts[index]; - // return PartItem( - // part: _part, - // onDelete: (part) { - // _serviceReport.parts.remove(part); - // setState(() {}); - // }, - // ); - // }), - // ), - const SizedBox( - height: 16, - ), - ], + 8.height, + ADatePicker( + label: context.translation.visitDate, + date: DateTime.tryParse(_serviceReport.visitDate ?? ""), + onDatePicker: (date) { + _serviceReport.visitDate = date?.toIso8601String(); + // setState(() {}); + }, ), - ), - AButton( - text: context.translation.update, - onPressed: () async { - if (_serviceReport?.workingHours == null) { - await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started"); - return; - } - _validate = true; - // if (!_formKey.currentState.validate()) { - // setState(() {}); - // return; - // } - // print("jere124"); - // if (!_serviceReport.validate()) { - // setState(() {}); - // return; - // } - // print("jere14"); - _formKey.currentState.save(); - - _isLoading = true; - setState(() {}); - // _serviceReport.files = _images.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); - int status = await _serviceRequestsProvider.updateServiceReport(user: _userProvider.user, host: _settingProvider.host, report: _serviceReport, request: widget.request); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: context.translation.successfulRequestMessage, - ); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - }, - ), - ], + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + textInputType: TextInputType.number, + initialValue: _serviceReport.workingHours?.toString(), + onSaved: (text) { + _serviceReport.workingHours = num.tryParse(text ?? ""); + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.reason, + initialValue: _serviceReport.reason, + onSelect: (value) { + _serviceReport.reason = value; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.serviceType, + onSelect: (value) {}, + ), + 8.height, + ServiceReportLastCallsMenu( + report: _serviceReport, + title: context.translation.callLastSituation, + parentId: widget.request.id, + onSelect: (status) { + _serviceReport.calllastSituation = status; + }, + ), + 8.height, + ServiceReportAssistantEmployeeMenu( + title: context.translation.assignAssistant, + assetId: _serviceReport.callRequest?.asset?.id, + initialValue: (_serviceReport.assistantEmployees?.isNotEmpty ?? false) ? _serviceReport.assistantEmployees?.first : null, + onSelect: (employee) { + _serviceReport.assistantEmployees = [employee.copyWith(id: 0)]; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.partNo, + staticData: _spareParts, + initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.sparePart : null, + onSelect: (part) { + _serviceReport.sparePartsWorkOrders.clear(); + _serviceReport.sparePartsWorkOrders.add(SparePartsWorkOrders(id: 0, sparePart: part, qty: 0)); + // setState(() {}); + }, + ), + 8.height, + AppTextFormField( + labelText: context.translation.quantity, + textInputType: TextInputType.number, + enable: _serviceReport.sparePartsWorkOrders.isNotEmpty, + initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.qty?.toString() : null, + onSaved: (text) { + if (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) { + _serviceReport.sparePartsWorkOrders.first.qty = num.tryParse(text ?? ""); + } + }, + ), + 8.height, + MultiFilesPicker(label: context.translation.attachImage, files: _files), + 8.height, + ESignature( + title: context.translation.engSign, + oldSignature: _serviceReport.engSignature, + newSignature: _serviceReport.localEngSignature, + onSaved: (signature) { + // if (signature == null || signature.isEmpty) { + // setState(() {}); + // return; + // } + _serviceReport.localEngSignature = signature; + _serviceReport.engSignature = signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" : null; + }, + ), + 24.height, + ], + ), + ).expanded, + AppFilledButton( + label: context.translation.updateRequest, + onPressed: () async { + if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate(context)))) { + setState(() {}); + return; + } + _formKey.currentState.save(); + _serviceReport.attachmentsWorkOrder ??= []; + if (_files.isEmpty) _serviceReport.attachmentsWorkOrder = []; + try { + for (var file in _files) { + _serviceReport.attachmentsWorkOrder.add(Attachment(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}")); + } + } catch (error) { + print(error); + } + await _serviceRequestsProvider.updateServiceReport(context, report: _serviceReport); + }, ), - const ABackButton(), ], - ), + ).paddingAll(16), ), ), ), ); } - - bool _isLocalUrl(String url) { - if (url?.isEmpty != false) return false; - return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); - } } diff --git a/lib/views/pages/user/requests/work_order/future_service_report.dart b/lib/views/pages/user/requests/work_order/update_service_report.dart similarity index 53% rename from lib/views/pages/user/requests/work_order/future_service_report.dart rename to lib/views/pages/user/requests/work_order/update_service_report.dart index 937262b4..fb8bcee7 100644 --- a/lib/views/pages/user/requests/work_order/future_service_report.dart +++ b/lib/views/pages/user/requests/work_order/update_service_report.dart @@ -1,9 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_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/models/service_request/search_work_order.dart'; import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; @@ -12,29 +8,23 @@ import 'package:test_sa/views/widgets/loaders/failed_loading.dart'; import 'edit_service_report.dart'; -class FutureServiceReport extends StatefulWidget { +class UpdateServiceReport extends StatefulWidget { final ServiceRequest request; final SearchWorkOrder workOrder; - const FutureServiceReport({Key key, this.request, this.workOrder}) : super(key: key); + const UpdateServiceReport({Key key, this.request, this.workOrder}) : super(key: key); @override - _FutureServiceReportState createState() => _FutureServiceReportState(); + _UpdateServiceReportState createState() => _UpdateServiceReportState(); } -class _FutureServiceReportState extends State { - UserProvider _userProvider; - SettingProvider _settingProvider; - +class _UpdateServiceReportState extends State { @override Widget build(BuildContext context) { - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); - - ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: context.translation); + ServiceRequestsProvider().getSingleServiceReport(context, reportId: widget.workOrder.id); return Scaffold( body: FutureBuilder( - future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: context.translation), + future: ServiceRequestsProvider().getSingleServiceReport(context, reportId: widget.workOrder.id), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return FailedLoading( @@ -45,10 +35,7 @@ class _FutureServiceReportState extends State { ); } if (snapshot.connectionState == ConnectionState.done) { - return EditServiceReport( - report: snapshot.data, - request: widget.request, - ); + return EditServiceReport(report: snapshot.data, request: widget.request); } return const Center(child: ALoading()); }, diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart index efc0c920..cd9d9ab1 100644 --- a/lib/views/pages/user/requests/work_order/work_order_details_page.dart +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -14,7 +14,7 @@ import '../../../../../controllers/providers/api/user_provider.dart'; import '../../../../../models/enums/user_types.dart'; import '../../../../../models/service_request/search_work_order.dart'; import '../../../../widgets/requests/request_status.dart'; -import 'future_service_report.dart'; +import 'update_service_report.dart'; class WorkOrderDetailsPage extends StatelessWidget { static const String id = "/work_order_details_page"; @@ -79,7 +79,7 @@ class WorkOrderDetailsPage extends StatelessWidget { AppFilledButton( onPressed: () { Navigator.of(context).push( - MaterialPageRoute(builder: (_) => FutureServiceReport(request: serviceRequest, workOrder: workOrder)), + MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrder)), ); }, label: context.translation.updateRequest, diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index 744e7a11..2f7ea3e6 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -14,7 +14,7 @@ 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/default_app_bar.dart'; import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; -import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/update_service_report.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; @@ -86,7 +86,7 @@ class WorkOrderListPage extends StatelessWidget { if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) "edit".toSvgAsset(height: 48, width: 48).onPress(() { Navigator.of(context).push( - MaterialPageRoute(builder: (_) => FutureServiceReport(request: serviceRequest, workOrder: workOrders[index])), + MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrders[index])), ); }) ], diff --git a/lib/views/widgets/e_signature/e_signature.dart b/lib/views/widgets/e_signature/e_signature.dart index 3ed11050..2fbf9e6a 100644 --- a/lib/views/widgets/e_signature/e_signature.dart +++ b/lib/views/widgets/e_signature/e_signature.dart @@ -6,6 +6,9 @@ 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 '../../app_style/sizing.dart'; +import '../loaders/image_loader.dart'; + class ESignature extends StatefulWidget { final String oldSignature; final Uint8List newSignature; @@ -35,7 +38,7 @@ class _ESignatureState extends State { if (widget.newSignature != null) { signature = widget.newSignature; } else if (widget.oldSignature != null || signature != null) { - signature = widget.oldSignature.codeUnits; + signature = Uint8List.fromList(widget.oldSignature.codeUnits); } super.initState(); } @@ -50,12 +53,13 @@ class _ESignatureState extends State { Widget build(BuildContext context) { return Column( children: [ - // if (widget.oldSignature != null || signature != null) - // Container( - // width: MediaQuery.of(context).size.width, - // padding: const EdgeInsets.only(bottom: 8), - // height: 90 * AppStyle.getScaleFactor(context), - // child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: widget.oldSignature)), + if (widget.oldSignature != null || signature != null) + Container( + width: MediaQuery.of(context).size.width, + padding: const EdgeInsets.only(bottom: 8), + height: 90 * AppStyle.getScaleFactor(context), + child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: widget.oldSignature), + ), FormField(onSaved: (_) async { widget.onSaved(signature); }, builder: (FormFieldState state) { From 8b63cee7c58f803e38272b38835963c200f7d7dc Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Wed, 1 Nov 2023 14:40:46 +0300 Subject: [PATCH 11/11] Update Work Order Screen DONE --- lib/views/widgets/e_signature/e_signature.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/views/widgets/e_signature/e_signature.dart b/lib/views/widgets/e_signature/e_signature.dart index 2fbf9e6a..e21a51a0 100644 --- a/lib/views/widgets/e_signature/e_signature.dart +++ b/lib/views/widgets/e_signature/e_signature.dart @@ -37,8 +37,6 @@ class _ESignatureState extends State { void initState() { if (widget.newSignature != null) { signature = widget.newSignature; - } else if (widget.oldSignature != null || signature != null) { - signature = Uint8List.fromList(widget.oldSignature.codeUnits); } super.initState(); }