From ed1337e16db7d1578178b9e64ffc93f3c39fbb86 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 30 Jan 2025 10:25:24 +0300 Subject: [PATCH 1/5] recurrent task ui complete --- lib/l10n/app_ar.arb | 3 +- lib/l10n/app_en.arb | 3 +- .../views/nurse/create_new_request_view.dart | 2 - .../pages/user/ppm/ppm_details_page.dart | 4 +- .../components/asset_info_widget.dart | 22 ++- .../recurrent_wo/components/dummy_data.dart | 184 ++++++++++++++++++ .../components/room_inspection_card.dart | 81 ++++++++ .../components/room_tabs_widget.dart | 88 +++++++++ .../recurrent_work_order_view.dart | 86 +++++--- 9 files changed, 436 insertions(+), 37 deletions(-) create mode 100644 lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart create mode 100644 lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart create mode 100644 lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 881d3054..51742453 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -531,5 +531,6 @@ "recurrentWo": "أمر العمل المتكرر", "taskNo": "رقم المهمة", "assignEngineer": "تعيين مهندس", - "scheduledDate": "التاريخ المجدول" + "scheduledDate": "التاريخ المجدول", + "complete": "اكتمل" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7d89a8ba..fcee617c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -535,5 +535,6 @@ "recurrentWo": "Recurrent WO", "taskNo": "Task No", "assignEngineer": "Assign Engineer", - "scheduledDate": "Scheduled Date" + "scheduledDate": "Scheduled Date", + "complete": "Complete" } \ No newline at end of file diff --git a/lib/service_request_latest/views/nurse/create_new_request_view.dart b/lib/service_request_latest/views/nurse/create_new_request_view.dart index 58e06fe1..1015199d 100644 --- a/lib/service_request_latest/views/nurse/create_new_request_view.dart +++ b/lib/service_request_latest/views/nurse/create_new_request_view.dart @@ -329,8 +329,6 @@ class _CreateNewRequestState extends State with TickerProvider _serviceRequest.requestedThrough = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 3, orElse: null); _serviceRequest.type = Provider.of(context, listen: false).items.firstWhere((element) => element.value == 1, orElse: null); - - print('comments value is ${_serviceRequest.callComments}'); if (_formKey.currentState!.validate() && await _serviceRequest.validateNewRequest(context)) { _formKey.currentState!.save(); diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index 9ac652d9..9496b7bc 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -110,8 +110,8 @@ class _PpmDetailsPageState extends State { AppFilledButton( onPressed: () async { //TODO remove after testing.. - // await Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView( request: widget.request))); - await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: ppm, details: widget.request))); + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView( request: widget.request))); + // await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: ppm, details: widget.request))); setState(() {}); }, label: context.translation.updateRequest, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart index 4ab4aa28..a50c8b81 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart @@ -12,14 +12,18 @@ import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; class AssetInfoWidget extends StatelessWidget { - DummyModel ?model; - AssetInfoWidget({super.key,DummyModel ?model}); + + final DummyModel? model; // Use `final` since it's a StatelessWidget + + AssetInfoWidget({super.key, required this.model}); @override Widget build(BuildContext context) { return Column( + mainAxisSize: MainAxisSize.min, children: [ Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ if (model?.request?.priority != null) @@ -30,16 +34,17 @@ class AssetInfoWidget extends StatelessWidget { ), 8.height, - model!.ppm!.assetName!.heading5(context), - 8.height, - '${context.translation.taskNo}: ${model!.ppm!.assetName}'.bodyText(context), - '${context.translation.site}: ${model!.ppm!.siteName!.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.assignEngineer}: ${model!.ppm!.assignedEmployeeName ?? ""}'.bodyText(context), - '${context.translation.scheduledDate}: ${'July 7, 2024' ?? ""}'.bodyText(context), + model!.ppm!.assetName!.bodyText(context).custom(color:AppColor.black10 ), + 2.height, + '${context.translation.taskNo}: ${model!.ppm!.assetName}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.site}: ${model!.ppm!.siteName!.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${model!.ppm!.assignedEmployeeName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.scheduledDate}: ${'July 7, 2024' ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), ], ).toShadowContainer(context), 12.height, Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ buildingInfoWidget(label: context.translation.department, value: model!.ppm!.departmentName!.cleanupWhitespace.capitalizeFirstOfEach,context: context), @@ -91,6 +96,7 @@ class AssetInfoWidget extends StatelessWidget { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ Text( label, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart new file mode 100644 index 00000000..51b3e6bb --- /dev/null +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart @@ -0,0 +1,184 @@ +class DummyData { + static List> roomData = [ + { + "name": "Room 1", + "cards": [ + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": true + }, + { + "label": "Room Humidity <35%", + "value": true + }, + { + "label": "Valve value", + "value": false + }, + { + "label": "Alarm Check", + "value": true + }, + { + "label": "Overall Result", + "value": true + } + ] + }, + { + "title": "Manifold", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": true + }, + { + "label": "Room Humidity <35%", + "value": true + }, + { + "label": "Valve value", + "value": false + }, + { + "label": "Alarm Check", + "value": true + } + ] + } + ] + }, + { + "name": "Room 2", + "cards": [ + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": true + }, + { + "label": "Room Humidity <35%", + "value": true + }, + { + "label": "Valve value", + "value": true + }, + { + "label": "Alarm Check", + "value": true + }, + { + "label": "Overall Result", + "value": true + } + ] + } + ] + }, + { + "name": "Room 3", + "cards": [ + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": false + }, + { + "label": "Room Humidity <35%", + "value": false + }, + { + "label": "Valve value", + "value": true + }, + { + "label": "Alarm Check", + "value": true + }, + { + "label": "Overall Result", + "value": false + } + ] + } + ] + }, + { + "name": "Room 4", + "cards": [ + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": false + }, + { + "label": "Room Humidity <35%", + "value": false + }, + { + "label": "Valve value", + "value": true + }, + { + "label": "Alarm Check", + "value": true + }, + { + "label": "Overall Result", + "value": false + } + ] + }, + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": false + }, + { + "label": "Room Humidity <35%", + "value": false + }, + { + "label": "Valve value", + "value": true + }, + { + "label": "Alarm Check", + "value": true + }, + ] + }, + { + "title": "General Inspection", + "info": [ + { + "label": "Room Temperature (15-35 C)", + "value": false + }, + { + "label": "Room Humidity <35%", + "value": false + }, + { + "label": "Valve value", + "value": true + }, + ] + } + + ] + } + ]; +} diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart new file mode 100644 index 00000000..855021d9 --- /dev/null +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -0,0 +1,81 @@ +import 'package:flutter/cupertino.dart'; +import 'package:test_sa/dashboard_latest/dashboard_view.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + +class RoomInspectionCard extends StatefulWidget { + final Map? inspectionModel; + + RoomInspectionCard({super.key, required this.inspectionModel}); + + @override + State createState() => _RoomInspectionCardState(); +} + +class _RoomInspectionCardState extends State { + late List inspectionValues; // Add a list to store the state of switches + + @override + void initState() { + super.initState(); + inspectionValues = widget.inspectionModel?['info'] + ?.map((inspectionType) => inspectionType['value'] as bool) + .toList() ?? + []; + } + + @override + Widget build(BuildContext context) { + return Column( + children: widget.inspectionModel?['info'] + ?.asMap() + .entries + .map((entry) => inspectionStatusRadioWidget( + index: entry.key, + label: entry.value['label'], + context: context, + )) + .toList() ?? + [], + ).toShadowContainer(context).paddingOnly(top: 12); + } + + Widget inspectionStatusRadioWidget({ + required int index, + required String label, + required BuildContext context, + }) { + String status = inspectionValues[index] ? 'Pass' : 'Fail'; + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + label + .bodyText2(context) + .custom(color: AppColor.white936, fontWeight: FontWeight.w500), + status + .bodyText2(context) + .custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), + ], + ), + CupertinoSwitch( + thumbColor: + inspectionValues[index] ? AppColor.green50 : AppColor.red30, + activeColor: inspectionValues[index] + ? AppColor.green50.withOpacity(0.25) + : AppColor.red30.withOpacity(0.25), + value: inspectionValues[index], + onChanged: (state) { + setState(() { + inspectionValues[index] = state; + }); + }, + ), + ], + ).paddingOnly(bottom: 12); + } +} + diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart new file mode 100644 index 00000000..b8cb080f --- /dev/null +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.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/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; +import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; + +class RoomTabsWidget extends StatefulWidget { + const RoomTabsWidget({Key? key}) : super(key: key); + + @override + State createState() => _RoomTabsWidgetState(); +} + +class _RoomTabsWidgetState extends State { + int selectedIndex = 0; + bool isLoading = false; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.all(12.toScreenHeight), + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral50 : AppColor.white10, + borderRadius: BorderRadius.circular(10), + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: DummyData.roomData.asMap().entries.map((entry) { + final int index = entry.key; + final String label = entry.value['name']; + return GestureDetector( + onTap: () { + setState(() { + isLoading = true; + selectedIndex = index; + //TODO replace with api response delay... + Future.delayed(const Duration(seconds: 1)).whenComplete(() { + setState(() { + isLoading = false; + }); + }); + }); + }, + child: Container( + margin: EdgeInsets.only(right: 8.toScreenWidth), + padding: EdgeInsets.symmetric( + vertical: 20.toScreenHeight, + horizontal: 30.toScreenWidth, + ), + alignment: Alignment.center, + decoration: BoxDecoration( + color: selectedIndex == index ? (context.isDark ? AppColor.neutral60 : AppColor.neutral110) : Colors.transparent, + borderRadius: BorderRadius.circular(7), + ), + child: label.bodyText(context).custom( + color: selectedIndex == index ? (context.isDark ? AppColor.white10 : AppColor.black20) : (context.isDark ? AppColor.neutral30 : AppColor.black20), + fontWeight: FontWeight.w600, + ), + ), + ); + }).toList(), + ), + ), + ), + 12.height, + // Display the Selected Tab Content + isLoading + ? SizedBox(height: 120.toScreenHeight, child: const ALoading().center) + : ListView( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + children: DummyData.roomData[selectedIndex]['cards'].map((card) { + return RoomInspectionCard(inspectionModel: card); + }).toList(), + ), + ], + ); + } +} diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index ca2cfb05..81266b08 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; @@ -7,17 +8,19 @@ 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/all_requests_and_count_model.dart'; -import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; -import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart'; +import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; -import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:test_sa/views/widgets/timer/app_timer.dart'; + +import 'components/room_inspection_card.dart'; +import 'components/room_tabs_widget.dart'; class RecurrentWorkOrderView extends StatefulWidget { static const String id = "/visit-details"; @@ -54,48 +57,85 @@ class _RecurrentWorkOrderViewState extends State { userProvider ??= Provider.of(context, listen: false); ppmProvider ??= Provider.of(context, listen: false); + RoomTabs.getRoomTabs(); return Scaffold( appBar: DefaultAppBar(title: context.translation.recurrentWo), - body: SafeArea( - child: FutureBuilder( + //TODO refactor this after getting api... + body: Stack( + children: [ + FutureBuilder( future: ppmProvider!.getPpmById(widget.request.id!), builder: (context, snap) { if (snap.connectionState == ConnectionState.waiting) { return const ALoading(); } else if (snap.hasData) { Ppm ppm = snap.data as Ppm; - return Column(children: [ - AssetInfoWidget(model: DummyModel(widget.request, ppm, timerModel, totalWorkingHours)), - ]).paddingAll(12); + DummyModel testModel = DummyModel(widget.request, ppm, timerModel, totalWorkingHours); + return SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AssetInfoWidget(model: testModel), + 16.height, + const RoomTabsWidget(), + ], + ).paddingAll(12), + ); } return NoDataFound(message: context.translation.noDataFound); - }), + }, + ).paddingOnly(bottom: 85), + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () async { + print('save clicked...'); + }, + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () async { + print('complete clicked...'); + }, + ).expanded, + ], + ), + ), + ], ), ); + } +} + + + + + -} class RoomTabs { String label; int tag; - int id; -// RoomTabs({ required this.label, required this.tag, - required this.id, }); - static List getTabs({required UsersTypes userType, required BuildContext context}) { - List tabs = []; - - tabs.add(RoomTabs(label: 'Upcoming', tag: 0, id: 0)); - tabs.add(RoomTabs(label: 'UnAssigned Open', tag: 1, id: 1)); - tabs.add(RoomTabs(label: 'Assigned Open', tag: 1, id: 2)); - tabs.add(RoomTabs(label: 'In Progress', tag: 2, id: 3)); - tabs.add(RoomTabs(label: 'Completed', tag: 3, id: 4)); - return tabs; + static List getRoomTabs() { + List roomTabs = []; + for(int i =0;i Date: Sun, 2 Feb 2025 11:50:29 +0300 Subject: [PATCH 2/5] Gas refill and Asset Transfer attributes addition done --- .../providers/api/gas_refill_provider.dart | 1 + lib/l10n/app_ar.arb | 6 +++- lib/l10n/app_en.arb | 6 +++- lib/models/device/asset_transfer.dart | 28 +++++++++++++++++++ lib/models/new_models/gas_refill_model.dart | 26 ++++++++++++++++- .../widgets/request_item_view_list.dart | 1 + .../device_transfer_details.dart | 14 ++++++++++ .../user/gas_refill/gas_refill_details.dart | 17 +++++++++++ .../user/gas_refill/request_gas_refill.dart | 1 + 9 files changed, 97 insertions(+), 3 deletions(-) diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index a551ebb2..a5d59016 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -47,6 +47,7 @@ class GasRefillProvider extends ChangeNotifier { Future getGasRefillObjectById(num id) async { try { Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gazRefillId=$id"); + if (response.statusCode >= 200 && response.statusCode < 300) { return GasRefillModel.fromJson(json.decode(response.body)["data"]); } else { diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 8ce8856c..331191a3 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -526,5 +526,9 @@ "userName": "اسم المستخدم", "siteName": "اسم الموقع", "pointName": "اسم النقطة", - "checkIn": "تسجيل الدخول" + "checkIn": "تسجيل الدخول", + "createdDate": "تاريخ الإنشاء", + "employeeId": "رقم الموظف", + "extensionNo": "رقم التمديد", + "recurrentWo": "أمر العمل المتكرر" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 74f488b9..c4aa20e2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -530,5 +530,9 @@ "userName": "User Name", "siteName": "Site Name", "pointName": "Point Name", - "checkIn": "Check in" + "checkIn": "Check in", + "createdDate": "Created Date", + "employeeId": "Employee ID", + "extensionNo": "Extension No", + "recurrentWo": "Recurrent WO" } \ No newline at end of file diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index 26116478..40ae2302 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -52,6 +52,10 @@ class AssetTransfer { this.destDepartmentName, this.destBuildingName, this.applied, + this.extensionNo, + this.name, + this.employeeId, + this.createdDate, this.createdOn, this.destFloorName, this.destSiteName, @@ -155,6 +159,10 @@ class AssetTransfer { destDepartmentName = json['destDepartmentName']; destBuildingName = json['destBuildingName']; applied = json['applied']; + extensionNo = json['extensionNo']; + employeeId = json['employeeId']; + name = json['name']; + createdDate = json['createdDate']; createdOn = json['createdOn']; destFloorName = json['destFloorName']; destSiteName = json['destSiteName']; @@ -234,6 +242,10 @@ class AssetTransfer { String? receiverMachineStatusName; String? receiverEngSignatureUrl; bool? applied; + dynamic extensionNo; + String? employeeId; + String? name; + String? createdDate; String? createdOn; String? modifiedOn; List? senderVisitTimers; @@ -293,6 +305,10 @@ class AssetTransfer { String? receiverMachineStatusName, String? receiverEngSignatureUrl, bool? applied, + dynamic extensionNo, + String? employeeId, + String? name, + String? createdDate, String? createdOn, String? modifiedOn, String? assetSerialNo, @@ -359,6 +375,10 @@ class AssetTransfer { receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName, receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl, applied: applied ?? this.applied, + extensionNo: extensionNo??this.extensionNo, + employeeId: employeeId??this.employeeId, + name: name??this.name, + createdDate: createdDate??this.createdDate, createdOn: createdOn ?? this.createdOn, modifiedOn: modifiedOn ?? this.modifiedOn, assetSerialNo: assetSerialNo ?? this.assetSerialNo, @@ -436,6 +456,10 @@ class AssetTransfer { map["receiverMachineStatusName"] = receiverMachineStatusName; map["receiverEngSignatureUrl"] = receiverEngSignatureUrl; map["applied"] = applied; + map["extensionNo"] = extensionNo; + map["employeeId"] = employeeId; + map["name"] = name; + map["createdDate"] = createdDate; map["createdOn"] = createdOn; map["modifiedOn"] = modifiedOn; map["assetSerialNo"] = assetSerialNo; @@ -552,6 +576,10 @@ class AssetTransfer { receiverMachineStatusName = assetTransfer.receiverMachineStatusName; receiverEngSignatureUrl = assetTransfer.receiverEngSignatureUrl; applied = assetTransfer.applied; + extensionNo = assetTransfer.extensionNo; + employeeId = assetTransfer.employeeId; + name = assetTransfer.name; + createdDate = assetTransfer.createdDate; createdOn = assetTransfer.createdOn; modifiedOn = assetTransfer.modifiedOn; assetSerialNo = assetTransfer.assetSerialNo; diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index eb944aa4..938d94e4 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -24,6 +24,10 @@ class GasRefillModel { this.engSignature, this.nurseSignature, this.workingHours, + this.extensionNo, + this.employeeId, + this.name, + this.createdDate, this.site, this.building, this.floor, @@ -47,6 +51,10 @@ class GasRefillModel { endTime = json['endTime']; comment = json['comment']; workingHours = json['workingHours']; + extensionNo = json['extensionNo']; + employeeId = json['employeeId']; + name = json['name']; + createdDate = json['createdDate']; try { final DateTime? sd = DateTime.tryParse(startDate ?? ""); final DateTime? st = DateTime.tryParse(startTime ?? ""); @@ -90,7 +98,11 @@ class GasRefillModel { String? endTime; // Now nullable String? engSignature; // Now nullable String? nurseSignature; // Now nullable - num? workingHours; // Now nullable + num? workingHours; + dynamic extensionNo; + String? employeeId; + String? name; + String? createdDate; Site? site; // Now nullable Building? building; // Now nullable Floor? floor; // Now nullable @@ -115,6 +127,10 @@ class GasRefillModel { String? engSignature, String? nurseSignature, num? workingHours, + num? extensionNo, + num? employeeId, + String? name, + String? createdDate, Site? site, Building? building, Floor? floor, @@ -161,6 +177,10 @@ class GasRefillModel { map['engSignature'] = engSignature; map['nurseSignature'] = nurseSignature; map['workingHours'] = workingHours; + map['extensionNo'] = extensionNo; + map['employeeId'] = employeeId; + map['name'] = name; + map['createdDate'] = createdDate; map['comment'] = comment; if (site != null) { map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety @@ -223,6 +243,10 @@ class GasRefillModel { engSignature = model.engSignature; nurseSignature = model.nurseSignature; workingHours = model.workingHours; + extensionNo = model.extensionNo; + employeeId = model.employeeId; + name = model.name; + createdDate = model.createdDate; } } diff --git a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart index 783671aa..ab2fb9ce 100644 --- a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart +++ b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart @@ -25,6 +25,7 @@ class RequestItemViewList extends StatelessWidget { shrinkWrap: true, itemBuilder: (cxt, index) { if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading); + bool isServiceRequest = list[index].transactionType == 1; bool isGasRefill = list[index].transactionType == 2; bool isAssetTransfer = list[index].transactionType == 3; diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index 6e1e6481..1815d04c 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -79,6 +79,11 @@ class _DeviceTransferDetailsState extends State { _buildTextWidget('${context.translation.sn} : ${_model?.assetSerialNo ?? ""}'), if (_model?.receiverEndUserName != null) _buildTextWidget('${context.translation.receiverName} : ${_model?.receiverEndUserName ?? ""}'), _buildTextWidget('${context.translation.requestNo} : ${_model?.transferCode ?? ""}'), + //TODO need to confirm where to display this new data... + infoText(label:context.translation.gasRequest ,value:_model?.extensionNo ), + infoText(label:context.translation.employeeId ,value:_model?.employeeId ), + infoText(label:context.translation.name ,value:_model?.name ), + infoText(label:context.translation.createdDate ,value:_model?.createdDate?.toInitialVisitCardFormat), if ((_model?.comment ?? "").isNotEmpty) ...[ 8.height, const Divider().defaultStyle(context), @@ -223,4 +228,13 @@ class _DeviceTransferDetailsState extends State { ], ).toShadowContainer(context); } + Widget infoText({String ?label,String ?value,}){ + if(value==null||value.isEmpty){ + return const SizedBox(); + } + else { + return '$label: $value'.bodyText(context); + } + + } } diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index 036182f4..b341c310 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -108,12 +108,19 @@ class _GasRefillDetailsPageState extends State { 8.height, context.translation.gasRefillRequest.heading5(context), 8.height, + '${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails![0].gasType?.name}'.bodyText(context), '${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails![0].cylinderType?.name}'.bodyText(context), '${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails![0].cylinderSize?.name}'.bodyText(context), '${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.requestNo}: ${gasRefillModel.gazRefillNo}'.bodyText(context), + //TODO need to confirm where to display this new data... + infoText(label:context.translation.gasRequest ,value:gasRefillModel.extensionNo ), + infoText(label:context.translation.employeeId ,value:gasRefillModel.employeeId ), + infoText(label:context.translation.name ,value:gasRefillModel.name ), + infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), + const Divider().defaultStyle(context), '${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), @@ -221,4 +228,14 @@ class _GasRefillDetailsPageState extends State { ], ).toShadowContainer(context, padding: 0); } + + Widget infoText({String ?label,String ?value,}){ + if(value==null||value.isEmpty){ + return const SizedBox(); + } + else { + return '$label: $value'.bodyText(context); + } + + } } diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index c5aa13df..462e30c7 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -176,6 +176,7 @@ class _RequestGasRefillState extends State { @override Widget build(BuildContext context) { + _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _gasRefillProvider ??= Provider.of(context, listen: false); From 99bcae1dc2c34d94f9e6c0308c3809b57c2f7ac7 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Sun, 2 Feb 2025 17:01:02 +0300 Subject: [PATCH 3/5] recurrent task api integrated --- lib/controllers/api_routes/urls.dart | 3 + .../providers/api/all_requests_provider.dart | 21 +- lib/extensions/string_extensions.dart | 9 + lib/l10n/app_ar.arb | 3 +- lib/l10n/app_en.arb | 3 +- lib/models/ppm/recurrent_wo.dart | 346 ++++++++++++++++++ .../my_request/my_requests_page.dart | 1 + .../requests/recurrent_wo_item_view.dart | 79 ++++ .../widgets/request_item_view_list.dart | 54 ++- .../pages/user/ppm/ppm_details_page.dart | 4 +- .../components/asset_info_widget.dart | 41 ++- .../components/room_inspection_card.dart | 40 +- .../components/room_tabs_widget.dart | 11 +- .../recurrent_work_order_view.dart | 103 +++--- 14 files changed, 598 insertions(+), 120 deletions(-) create mode 100644 lib/models/ppm/recurrent_wo.dart create mode 100644 lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 137d2f3a..b1959cfc 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -80,6 +80,9 @@ class URLs { static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction'; static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; + static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; + //Recurrent plan Api... + //service request..... static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index a4b82bd8..88cf8f95 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -4,8 +4,10 @@ import 'package:flutter/widgets.dart'; import 'package:http/http.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/enums/user_types.dart'; +import 'package:test_sa/models/ppm/recurrent_wo.dart'; import '../../../models/search_all_requests_model.dart'; @@ -128,7 +130,7 @@ class AllRequestsProvider extends ChangeNotifier { } final type = typeTransaction == null ? search?.typeTransaction == null || (search?.typeTransaction?.isEmpty ?? false) - ? [1, 2, 3, 4] + ? [1, 2, 3, 4,5]//added 5 to get recurrent wo ... : search!.typeTransaction : [typeTransaction]; List status = (search?.statuses == null || (search?.statuses?.isEmpty ?? false)) ? (((search?.isArchived ?? false) ? [3] : [1, 2, 4])) : search!.statuses!; @@ -177,6 +179,23 @@ class AllRequestsProvider extends ChangeNotifier { } } + Future getRecurrentWoById(BuildContext context, {required int id}) async { + Response response; + try { + response = await ApiManager.instance.get(URLs.getRecurrentPlanByIdUrl + "?planRecurrentTaskId=$id"); + + } catch (error) { + throw (context.translation.failedToCompleteRequest); + } + if (response.statusCode >= 200 && response.statusCode < 300) { + RecurrentWo recurrentWo = RecurrentWo.fromJson(json.decode(response.body)); + return recurrentWo; + + } else { + throw (("${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}")); + } + } + Future getCalendarRequests({required DateTime from, DateTime? to}) async { if (isCalendarLoading == true) return -2; isCalendarLoading = true; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 80a0f88d..6a024697 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -38,6 +38,15 @@ extension StringExtensions on String { return ""; } } + String get toMonthYearFormat { + try { + DateTime dateTime = DateTime.parse(this); + String formattedDate = DateFormat('MMMM d, y').format(dateTime); + return formattedDate; + } catch (e) { + return ""; + } + } String get toAssetDetailsFormat { try { diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 51742453..a15a9b45 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -532,5 +532,6 @@ "taskNo": "رقم المهمة", "assignEngineer": "تعيين مهندس", "scheduledDate": "التاريخ المجدول", - "complete": "اكتمل" + "complete": "اكتمل", + "recurrentWo": "أمر العمل المتكرر" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fcee617c..7d5a1c18 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -536,5 +536,6 @@ "taskNo": "Task No", "assignEngineer": "Assign Engineer", "scheduledDate": "Scheduled Date", - "complete": "Complete" + "complete": "Complete", + "recurrentWo": "Recurrent WO" } \ No newline at end of file diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart new file mode 100644 index 00000000..19d5d233 --- /dev/null +++ b/lib/models/ppm/recurrent_wo.dart @@ -0,0 +1,346 @@ +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/timer_model.dart'; + +class RecurrentWo { + RecurrentWoData? recurrentWoData; + String? message; + String? title; + String? innerMessage; + int? responseCode; + bool? isSuccess; + + RecurrentWo( + {this.recurrentWoData, + this.message, + this.title, + this.innerMessage, + this.responseCode, + this.isSuccess}); + + RecurrentWo.fromJson(Map json) { + recurrentWoData = json['data'] != null ? RecurrentWoData.fromJson(json['data']) : null; + message = json['message']; + title = json['title']; + innerMessage = json['innerMessage']; + responseCode = json['responseCode']; + isSuccess = json['isSuccess']; + } + + Map toJson() { + final Map data = {}; + if (recurrentWoData != null) { + data['data'] = recurrentWoData!.toJson(); + } + data['message'] = message; + data['title'] = title; + data['innerMessage'] = innerMessage; + data['responseCode'] = responseCode; + data['isSuccess'] = isSuccess; + return data; + } +} + +class RecurrentWoData { + int? id; + Engineer? engineer; + String? scheduleDate; + Status? status; + Site? site; + Lookup? building; + Lookup? floor; + Lookup? department; + Lookup? room; + List? planRecurrentMedicalTaskRooms; + List? planRecurrentTaskTimers; + TimerModel? recurrentWoTimerModel = TimerModel(); + + RecurrentWoData( + {this.id, + this.engineer, + this.scheduleDate, + this.status, + this.site, + this.building, + this.recurrentWoTimerModel, + this.floor, + this.department, + this.room, + this.planRecurrentMedicalTaskRooms, + this.planRecurrentTaskTimers}); + + RecurrentWoData.fromJson(Map json) { + id = json['id']; + engineer = json['engineer'] != null + ? new Engineer.fromJson(json['engineer']) + : null; + scheduleDate = json['scheduleDate']; + status = + json['status'] != null ? Status.fromJson(json['status']) : null; + site = json['site'] != null ? Site.fromJson(json['site']) : null; + building= json["building"] == null ? null : Lookup.fromJson(json["building"]); + floor= json["floor"] == null ? null : Lookup.fromJson(json["floor"]); + department= json["department"] == null ? null : Lookup.fromJson(json["department"]); + room= json["room"] == null ? null : Lookup.fromJson(json["room"]); + if (json['planRecurrentMedicalTaskRooms'] != null) { + planRecurrentMedicalTaskRooms = []; + json['planRecurrentMedicalTaskRooms'].forEach((v) { + planRecurrentMedicalTaskRooms! + .add(PlanRecurrentMedicalTaskRooms.fromJson(v)); + }); + } + if (json['planRecurrentTaskTimers'] != null) { + //TODO match with exact data and replace... + // planRecurrentTaskTimers = []; + // json['planRecurrentTaskTimers'].forEach((v) { + // planRecurrentTaskTimers!.add(new Null.fromJson(v)); + // }); + } + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + if (engineer != null) { + data['engineer'] = engineer!.toJson(); + } + data['scheduleDate'] = scheduleDate; + if (status != null) { + data['status'] = status!.toJson(); + } + if (site != null) { + data['site'] = site!.toJson(); + } + + if (planRecurrentMedicalTaskRooms != null) { + data['planRecurrentMedicalTaskRooms'] = + planRecurrentMedicalTaskRooms!.map((v) => v.toJson()).toList(); + } + if (planRecurrentTaskTimers != null) { + //TODO match with exact data and replace... + // data['planRecurrentTaskTimers'] = + // this.planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Engineer { + String? userId; + String? userName; + String? email; + String? employeeId; + int? languageId; + + Engineer( + {this.userId, + this.userName, + this.email, + this.employeeId, + this.languageId}); + + Engineer.fromJson(Map json) { + userId = json['userId']; + userName = json['userName']; + email = json['email']; + employeeId = json['employeeId']; + languageId = json['languageId']; + } + + Map toJson() { + final Map data = new Map(); + data['userId'] = this.userId; + data['userName'] = this.userName; + data['email'] = this.email; + data['employeeId'] = this.employeeId; + data['languageId'] = this.languageId; + return data; + } +} + +class Status { + int? id; + String? name; + int? value; + + Status({this.id, this.name, this.value}); + + Status.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['value'] = this.value; + return data; + } +} + +class Site { + int? id; + String? siteName; + + Site({this.id, this.siteName}); + + Site.fromJson(Map json) { + id = json['id']; + siteName = json['siteName']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['siteName'] = this.siteName; + return data; + } +} + +class PlanRecurrentMedicalTaskRooms { + int? id; + Room? room; + List? planRecurrentMedicalTaskRoomTabs; + + PlanRecurrentMedicalTaskRooms( + {this.id, this.room, this.planRecurrentMedicalTaskRoomTabs}); + + PlanRecurrentMedicalTaskRooms.fromJson(Map json) { + id = json['id']; + room = json['room'] != null ? new Room.fromJson(json['room']) : null; + if (json['planRecurrentMedicalTaskRoomTabs'] != null) { + planRecurrentMedicalTaskRoomTabs = []; + json['planRecurrentMedicalTaskRoomTabs'].forEach((v) { + planRecurrentMedicalTaskRoomTabs! + .add(new PlanRecurrentMedicalTaskRoomTabs.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + if (this.room != null) { + data['room'] = this.room!.toJson(); + } + if (this.planRecurrentMedicalTaskRoomTabs != null) { + data['planRecurrentMedicalTaskRoomTabs'] = this + .planRecurrentMedicalTaskRoomTabs! + .map((v) => v.toJson()) + .toList(); + } + return data; + } +} + +class Room { + int? id; + String? roomId; + + Room({this.id, this.roomId}); + + Room.fromJson(Map json) { + id = json['id']; + roomId = json['roomId']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['roomId'] = this.roomId; + return data; + } +} + +class PlanRecurrentMedicalTaskRoomTabs { + int? id; + String? tabName; + int? tabMedicalRoomId; + List? + planRecurrentMedicalTaskRoomTabAttributes; + + PlanRecurrentMedicalTaskRoomTabs( + {this.id, + this.tabName, + this.tabMedicalRoomId, + this.planRecurrentMedicalTaskRoomTabAttributes}); + + PlanRecurrentMedicalTaskRoomTabs.fromJson(Map json) { + id = json['id']; + tabName = json['tabName']; + tabMedicalRoomId = json['tabMedicalRoomId']; + if (json['planRecurrentMedicalTaskRoomTabAttributes'] != null) { + planRecurrentMedicalTaskRoomTabAttributes = + []; + json['planRecurrentMedicalTaskRoomTabAttributes'].forEach((v) { + planRecurrentMedicalTaskRoomTabAttributes! + .add(new PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['tabName'] = this.tabName; + data['tabMedicalRoomId'] = this.tabMedicalRoomId; + if (this.planRecurrentMedicalTaskRoomTabAttributes != null) { + data['planRecurrentMedicalTaskRoomTabAttributes'] = this + .planRecurrentMedicalTaskRoomTabAttributes! + .map((v) => v.toJson()) + .toList(); + } + return data; + } +} + +class PlanRecurrentMedicalTaskRoomTabAttributes { + int? id; + Attribute? attribute; + Null? attributeValue; + + PlanRecurrentMedicalTaskRoomTabAttributes( + {this.id, this.attribute, this.attributeValue}); + + PlanRecurrentMedicalTaskRoomTabAttributes.fromJson( + Map json) { + id = json['id']; + attribute = json['attribute'] != null + ? new Attribute.fromJson(json['attribute']) + : null; + attributeValue = json['attributeValue']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + if (this.attribute != null) { + data['attribute'] = this.attribute!.toJson(); + } + data['attributeValue'] = this.attributeValue; + return data; + } +} + +class Attribute { + String? name; + String? type; + String? key; + + Attribute({this.name, this.type, this.key}); + + Attribute.fromJson(Map json) { + name = json['name']; + type = json['type']; + key = json['key']; + } + + Map toJson() { + final Map data = new Map(); + data['name'] = this.name; + data['type'] = this.type; + data['key'] = this.key; + return data; + } +} \ No newline at end of file diff --git a/lib/new_views/pages/land_page/my_request/my_requests_page.dart b/lib/new_views/pages/land_page/my_request/my_requests_page.dart index bc0b6863..0519bd03 100644 --- a/lib/new_views/pages/land_page/my_request/my_requests_page.dart +++ b/lib/new_views/pages/land_page/my_request/my_requests_page.dart @@ -37,6 +37,7 @@ class _MyRequestsPageState extends State { context.translation.gasRefillRequest, context.translation.deviceTransferRequest, context.translation.preventiveMaintenance, + context.translation.recurrentWo, ]; _provider = Provider.of(context, listen: false); _provider!.reset(); diff --git a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart new file mode 100644 index 00000000..0f4abfdb --- /dev/null +++ b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_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/all_requests_and_count_model.dart'; +import 'package:test_sa/models/ppm/recurrent_wo.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart'; +import '../../../../views/widgets/requests/request_status.dart'; + +class RecurrentWoItemView extends StatelessWidget { + final RequestsDetails? requestDetails; + final bool showShadow; + + const RecurrentWoItemView({Key? key, this.requestDetails, this.showShadow = true}) : super(key: key); + + @override + Widget build(BuildContext context) { + if (requestDetails != null) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StatusLabel( + label: requestDetails!.priority!, + textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails!.priority!), + backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails!.priority!), + ), + 8.width, + StatusLabel( + label: requestDetails!.status!, + textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails!.status!), + backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails!.status!), + ), + 1.width.expanded, + Text( + requestDetails!.date?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), + ), + ], + ), + 8.height, + (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), + 8.height, + '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), + '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), + // '${context.translation.code}: ${request.code}'.bodyText(context), + '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.viewDetails, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + ), + 4.width, + Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).toShadowContainer(context, withShadow: showShadow).onPress(() async { + print('data i got is ${requestDetails?.id}'); + + RecurrentWo recurrentWo = await Provider.of(context,listen:false).getRecurrentWoById(context, id: requestDetails!.id!); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView( recurrentWo: recurrentWo))); + + }); + } + return SizedBox(); + } +} diff --git a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart index 783671aa..0a06c6d6 100644 --- a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart +++ b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart @@ -7,6 +7,7 @@ import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/new_views/pages/land_page/requests/asset_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/gas_refill_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/ppm_item_view.dart'; +import 'package:test_sa/new_views/pages/land_page/requests/recurrent_wo_item_view.dart'; import 'package:test_sa/new_views/pages/land_page/requests/service_request_item_view.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; @@ -25,24 +26,43 @@ class RequestItemViewList extends StatelessWidget { shrinkWrap: true, itemBuilder: (cxt, index) { if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading); - bool isServiceRequest = list[index].transactionType == 1; - bool isGasRefill = list[index].transactionType == 2; - bool isAssetTransfer = list[index].transactionType == 3; - bool isPPMs = list[index].transactionType == 4; + switch(list[index].transactionType){ + case 1: + return ServiceRequestItemView(requestDetails: list[index]); + case 2: + return GasRefillItemView(requestDetails: list[index]); + case 3: + return AssetItemView(requestDetails: list[index]); + case 4: + return PpmItemView(requestDetails: list[index]); + case 5: + return RecurrentWoItemView(requestDetails: list[index]); + default: + Container( + height: 100, + width: double.infinity, + color: Colors.grey, + ); - return isServiceRequest - ? ServiceRequestItemView(requestDetails: list[index]) - : isGasRefill - ? GasRefillItemView(requestDetails: list[index]) - : isPPMs - ? PpmItemView(requestDetails: list[index]) - : isAssetTransfer - ? AssetItemView(requestDetails: list[index]) - : Container( - height: 100, - width: double.infinity, - color: Colors.grey, - ); + } + // bool isServiceRequest = list[index].transactionType == 1; + // bool isGasRefill = list[index].transactionType == 2; + // bool isAssetTransfer = list[index].transactionType == 3; + // bool isPPMs = list[index].transactionType == 4; + // + // return isServiceRequest + // ? ServiceRequestItemView(requestDetails: list[index]) + // : isGasRefill + // ? GasRefillItemView(requestDetails: list[index]) + // : isPPMs + // ? PpmItemView(requestDetails: list[index]) + // : isAssetTransfer + // ? AssetItemView(requestDetails: list[index]) + // : Container( + // height: 100, + // width: double.infinity, + // color: Colors.grey, + // ); }, separatorBuilder: (cxt, index) => 8.height, itemCount: isLoading ? 6 : list.length); diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index 9496b7bc..4e9a8d6c 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -109,9 +109,7 @@ class _PpmDetailsPageState extends State { if (userProvider!.user!.type == UsersTypes.engineer && (ppm.visitStatusId != 270 && ppm.visitStatusId != 269)) AppFilledButton( onPressed: () async { - //TODO remove after testing.. - await Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView( request: widget.request))); - // await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: ppm, details: widget.request))); + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: ppm, details: widget.request))); setState(() {}); }, label: context.translation.updateRequest, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart index a50c8b81..1257bf88 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.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/all_requests_and_count_model.dart'; import 'package:test_sa/models/ppm/ppm.dart'; +import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; @@ -13,12 +15,13 @@ import 'package:test_sa/views/widgets/timer/app_timer.dart'; class AssetInfoWidget extends StatelessWidget { - final DummyModel? model; // Use `final` since it's a StatelessWidget + final RecurrentWoData? model; // Use `final` since it's a StatelessWidget AssetInfoWidget({super.key, required this.model}); @override Widget build(BuildContext context) { + double totalWorkingHours = 2.0; return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -26,38 +29,38 @@ class AssetInfoWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (model?.request?.priority != null) + if (model?.status != null) StatusLabel( - label: model?.request?.priority, - textColor: AppColor.getRequestStatusTextColorByName(context,model?.request?.priority), - backgroundColor: AppColor.getRequestStatusColorByName(context,model?.request?.priority), + label: model?.status?.name, + textColor: AppColor.getRequestStatusTextColorByName(context,model?.status?.name), + backgroundColor: AppColor.getRequestStatusColorByName(context,model?.status?.name), ), 8.height, - - model!.ppm!.assetName!.bodyText(context).custom(color:AppColor.black10 ), +// TODO need to replace this with correct data... + model!.site!.siteName!.bodyText(context).custom(color:AppColor.black10 ), 2.height, - '${context.translation.taskNo}: ${model!.ppm!.assetName}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.site}: ${model!.ppm!.siteName!.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${model!.ppm!.assignedEmployeeName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.scheduledDate}: ${'July 7, 2024' ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.taskNo}: ${model!.site!.id!}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.site}: ${model!.site!.siteName!}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), ], ).toShadowContainer(context), 12.height, - Column( + model!.planRecurrentMedicalTaskRooms!.isEmpty? Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildingInfoWidget(label: context.translation.department, value: model!.ppm!.departmentName!.cleanupWhitespace.capitalizeFirstOfEach,context: context), + buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), 8.height, - buildingInfoWidget(label: context.translation.floor, value: model!.ppm!.floorName!.cleanupWhitespace.capitalizeFirstOfEach,context: context), + buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), 8.height, - buildingInfoWidget(label: context.translation.room, value: model!.ppm!.roomName!.cleanupWhitespace.capitalizeFirstOfEach,context: context), + buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), 8.height, AppTimer( label: context.translation.timer, - timer: model!.timerModel, + timer: model!.recurrentWoTimerModel, width:double.infinity, - enabled: model!.timerModel?.endAt == null, + enabled: model!.recurrentWoTimerModel?.endAt == null, decoration: BoxDecoration( color: AppColor.neutral100, borderRadius: BorderRadius.circular(10), @@ -79,7 +82,7 @@ class AssetInfoWidget extends StatelessWidget { style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), ), Text( - " ${ServiceRequestUtils.formatTimerDuration(model!.totalWorkingHours.round())}", + " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", style: Theme.of(context).textTheme.bodyMedium, ), ], @@ -87,7 +90,7 @@ class AssetInfoWidget extends StatelessWidget { 8.height, ], // ], - ).toShadowContainer(context,padding: 12), + ).toShadowContainer(context,padding: 12):const SizedBox(), ], ); } diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 855021d9..09334adb 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -1,11 +1,13 @@ import 'package:flutter/cupertino.dart'; import 'package:test_sa/dashboard_latest/dashboard_view.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/ppm/recurrent_wo.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; class RoomInspectionCard extends StatefulWidget { - final Map? inspectionModel; + final PlanRecurrentMedicalTaskRoomTabs? inspectionModel; RoomInspectionCard({super.key, required this.inspectionModel}); @@ -19,25 +21,33 @@ class _RoomInspectionCardState extends State { @override void initState() { super.initState(); - inspectionValues = widget.inspectionModel?['info'] - ?.map((inspectionType) => inspectionType['value'] as bool) - .toList() ?? - []; + inspectionValues = widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes! + .map((inspectionType) => inspectionType.attributeValue != null) + .toList(); } @override Widget build(BuildContext context) { return Column( - children: widget.inspectionModel?['info'] - ?.asMap() - .entries - .map((entry) => inspectionStatusRadioWidget( - index: entry.key, - label: entry.value['label'], - context: context, - )) - .toList() ?? - [], + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.inspectionModel!.tabName! + .bodyText(context) + .custom(color: AppColor.neutral50, fontWeight: FontWeight.w600), + 8.height, + Column( + children: widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes + ?.asMap() + .entries + .map((entry) => inspectionStatusRadioWidget( + index: entry.key, + label: entry.value.attribute!.name??'', + context: context, + )) + .toList() ?? + [], + ) + ], ).toShadowContainer(context).paddingOnly(top: 12); } diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart index b8cb080f..25eea61a 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart @@ -3,13 +3,15 @@ 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/ppm/recurrent_wo.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; class RoomTabsWidget extends StatefulWidget { - const RoomTabsWidget({Key? key}) : super(key: key); + final RecurrentWoData? model; + const RoomTabsWidget({Key? key,required this.model}) : super(key: key); @override State createState() => _RoomTabsWidgetState(); @@ -34,9 +36,10 @@ class _RoomTabsWidgetState extends State { child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( - children: DummyData.roomData.asMap().entries.map((entry) { + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: widget.model!.planRecurrentMedicalTaskRooms!.asMap().entries.map((entry) { final int index = entry.key; - final String label = entry.value['name']; + final String label = entry.value.room!.roomId!; return GestureDetector( onTap: () { setState(() { @@ -78,7 +81,7 @@ class _RoomTabsWidgetState extends State { : ListView( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - children: DummyData.roomData[selectedIndex]['cards'].map((card) { + children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map((card) { return RoomInspectionCard(inspectionModel: card); }).toList(), ), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 81266b08..5ae21521 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -5,10 +5,10 @@ import 'package:test_sa/controllers/providers/api/ppm_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/all_requests_and_count_model.dart'; import 'package:test_sa/models/ppm/ppm.dart'; +import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -18,15 +18,13 @@ import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/compone import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; - -import 'components/room_inspection_card.dart'; import 'components/room_tabs_widget.dart'; class RecurrentWorkOrderView extends StatefulWidget { - static const String id = "/visit-details"; - final RequestsDetails request; + static const String id = "/recurrent_wo"; + final RecurrentWo recurrentWo; - const RecurrentWorkOrderView({Key? key, required this.request}) : super(key: key); + const RecurrentWorkOrderView({Key? key, required this.recurrentWo}) : super(key: key); @override _RecurrentWorkOrderViewState createState() { @@ -56,76 +54,63 @@ class _RecurrentWorkOrderViewState extends State { Widget build(BuildContext context) { userProvider ??= Provider.of(context, listen: false); ppmProvider ??= Provider.of(context, listen: false); - + print('data i got is ${widget.recurrentWo.recurrentWoData?.toJson()}'); RoomTabs.getRoomTabs(); return Scaffold( appBar: DefaultAppBar(title: context.translation.recurrentWo), //TODO refactor this after getting api... - body: Stack( - children: [ - FutureBuilder( - future: ppmProvider!.getPpmById(widget.request.id!), - builder: (context, snap) { - if (snap.connectionState == ConnectionState.waiting) { - return const ALoading(); - } else if (snap.hasData) { - Ppm ppm = snap.data as Ppm; - DummyModel testModel = DummyModel(widget.request, ppm, timerModel, totalWorkingHours); - return SingleChildScrollView( + body: widget.recurrentWo.recurrentWoData != null + ? Stack( + children: [ + SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - AssetInfoWidget(model: testModel), + AssetInfoWidget(model: widget.recurrentWo.recurrentWoData), 16.height, - const RoomTabsWidget(), + widget.recurrentWo.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty + ? RoomTabsWidget( + model: widget.recurrentWo.recurrentWoData, + ) + : const SizedBox(), ], ).paddingAll(12), - ); - } - return NoDataFound(message: context.translation.noDataFound); - }, - ).paddingOnly(bottom: 85), - FooterActionButton.footerContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - AppFilledButton( - label: context.translation.save, - buttonColor: AppColor.white60, - textColor: AppColor.black10, - onPressed: () async { - print('save clicked...'); - }, - ).expanded, - 12.width, - AppFilledButton( - label: context.translation.complete, - buttonColor: AppColor.primary10, - onPressed: () async { - print('complete clicked...'); - }, - ).expanded, + ).paddingOnly(bottom: 85), + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () async { + print('save clicked...'); + }, + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () async { + print('complete clicked...'); + }, + ).expanded, + ], + ), + ), ], - ), - ), - ], - ), + ) + : NoDataFound(message: context.translation.noDataFound).center, ); - } } - - - - - - - class RoomTabs { String label; int tag; + RoomTabs({ required this.label, required this.tag, @@ -133,9 +118,9 @@ class RoomTabs { static List getRoomTabs() { List roomTabs = []; - for(int i =0;i Date: Thu, 6 Feb 2025 09:23:21 +0300 Subject: [PATCH 4/5] save and complete api integrated for recurrent task --- lib/controllers/api_routes/urls.dart | 3 +- .../providers/api/all_requests_provider.dart | 62 ++++- lib/extensions/enum_extensions.dart | 15 + .../recurrent_task_inspection_data_type.dart | 4 + lib/models/ppm/recurrent_wo.dart | 257 +++++++++--------- lib/new_views/app_style/app_color.dart | 2 + .../requests/recurrent_wo_item_view.dart | 8 +- .../components/internal_request.dart | 1 + .../maintenance_request_main.dart | 6 - .../components/asset_info_widget.dart | 125 +++++---- .../components/room_inspection_card.dart | 123 ++++++--- .../components/room_tabs_widget.dart | 76 +++--- .../recurrent_work_order_view.dart | 176 ++++++------ 13 files changed, 498 insertions(+), 360 deletions(-) create mode 100644 lib/models/enums/recurrent_task_inspection_data_type.dart diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index b1959cfc..b40f11c2 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -80,8 +80,9 @@ class URLs { static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction'; static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; - static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; //Recurrent plan Api... + static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; + static get updateRecurrentPlanUrl=> '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer'; //service request..... diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 88cf8f95..ca8801b2 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -8,6 +8,7 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; +import 'package:test_sa/models/timer_model.dart'; import '../../../models/search_all_requests_model.dart'; @@ -19,6 +20,8 @@ class AllRequestsProvider extends ChangeNotifier { bool isOverdueLoading = false; bool isHighPriorityLoading = false; bool isCalendarLoading = false; + bool isLoading = false; + bool _isFilterRequestLoading = false; bool _isRequestCategoryLoading = false; @@ -50,12 +53,24 @@ class AllRequestsProvider extends ChangeNotifier { AllRequestsAndCount? _requestDetailList; AllRequestsAndCount? get allRequestsAndCount => _allRequestsAndCount; + AllRequestsAndCount? get highPriorityRequests => _highPriorityRequests; + AllRequestsAndCount? get overdueRequests => _overdueRequests; + // AllRequestsAndCount? get openRequests => _openRequests; // AllRequestsAndCount? get completedRequests => _completedRequests; AllRequestsAndCount? get requestDetailList => _requestDetailList; + RecurrentWoData? _recurrentWoData; + + RecurrentWoData? get recurrentWoData => _recurrentWoData; + + set recurrentWoData(RecurrentWoData? value) { + _recurrentWoData = value; + notifyListeners(); + } + set requestDetailList(AllRequestsAndCount? value) { _requestDetailList = value; notifyListeners(); @@ -117,10 +132,9 @@ class AllRequestsProvider extends ChangeNotifier { SearchAllRequestsModel? searchedModel; Future getAllRequests(BuildContext context, {int? typeTransaction, SearchAllRequestsModel? search}) async { - print('loading value is $isAllLoading'); if (isAllLoading == true) return -2; isAllLoading = true; - if (_allRequestsAndCount == null) notifyListeners(); + if (_allRequestsAndCount == null) notifyListeners(); Response response; try { if (search != null) { @@ -130,7 +144,7 @@ class AllRequestsProvider extends ChangeNotifier { } final type = typeTransaction == null ? search?.typeTransaction == null || (search?.typeTransaction?.isEmpty ?? false) - ? [1, 2, 3, 4,5]//added 5 to get recurrent wo ... + ? [1, 2, 3, 4, 5] //added 5 to get recurrent wo ... : search!.typeTransaction : [typeTransaction]; List status = (search?.statuses == null || (search?.statuses?.isEmpty ?? false)) ? (((search?.isArchived ?? false) ? [3] : [1, 2, 4])) : search!.statuses!; @@ -179,23 +193,51 @@ class AllRequestsProvider extends ChangeNotifier { } } - Future getRecurrentWoById(BuildContext context, {required int id}) async { + Future getRecurrentWoById({required int id}) async { + isLoading = true; Response response; try { response = await ApiManager.instance.get(URLs.getRecurrentPlanByIdUrl + "?planRecurrentTaskId=$id"); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); + notifyListeners(); + } + isLoading = false; + notifyListeners(); + return response.statusCode; } catch (error) { - throw (context.translation.failedToCompleteRequest); + isLoading = false; + stateCode = -1; + notifyListeners(); + return -1; } - if (response.statusCode >= 200 && response.statusCode < 300) { - RecurrentWo recurrentWo = RecurrentWo.fromJson(json.decode(response.body)); - return recurrentWo; + } - } else { - throw (("${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}")); + Future updateRecurrentWo({required int status}) async { + isLoading = true; + Response response; + try { + response = await ApiManager.instance.post(URLs.updateRecurrentPlanUrl, body: recurrentWoData!.toJson(status: status)); + print('response i got back is ${response.body}'); + stateCode = response.statusCode; + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + stateCode = -1; + notifyListeners(); + return -1; } } + void updateRecurrentWoTimer({TimerModel? timer}) { + recurrentWoData?.recurrentWoTimerModel = timer; + notifyListeners(); + } + Future getCalendarRequests({required DateTime from, DateTime? to}) async { if (isCalendarLoading == true) return -2; isCalendarLoading = true; diff --git a/lib/extensions/enum_extensions.dart b/lib/extensions/enum_extensions.dart index 0325affb..c6d10640 100644 --- a/lib/extensions/enum_extensions.dart +++ b/lib/extensions/enum_extensions.dart @@ -1,4 +1,5 @@ import 'package:test_sa/app_strings/app_asset.dart'; +import 'package:test_sa/models/enums/recurrent_task_inspection_data_type.dart'; import 'package:test_sa/models/enums/swipe_type.dart'; import 'package:test_sa/models/enums/work_order_next_step.dart'; @@ -94,6 +95,8 @@ extension IntExtensionsWorkOrder on int { } } + + extension EnumExtensionsSwipeType on SwipeTypeEnum { int getIntFromSwipeTypeEnum() { switch (this) { @@ -106,3 +109,15 @@ extension EnumExtensionsSwipeType on SwipeTypeEnum { } } } +extension StringExtensionsRecurrentTaskInpesctionDataType on String { + RecurrentTaskInspectionDataTypeEnum toRecurrentTaskInspectionDataTypeEnum() { + switch (this) { + case 'bool': + return RecurrentTaskInspectionDataTypeEnum.bool; + case 'number': + return RecurrentTaskInspectionDataTypeEnum.number; + default: + return RecurrentTaskInspectionDataTypeEnum.bool; + } + } +} diff --git a/lib/models/enums/recurrent_task_inspection_data_type.dart b/lib/models/enums/recurrent_task_inspection_data_type.dart new file mode 100644 index 00000000..478f780f --- /dev/null +++ b/lib/models/enums/recurrent_task_inspection_data_type.dart @@ -0,0 +1,4 @@ +enum RecurrentTaskInspectionDataTypeEnum { + bool, //bool + number, // number +} diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index 19d5d233..0fcc44c9 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -1,3 +1,5 @@ +import 'package:test_sa/extensions/enum_extensions.dart'; +import 'package:test_sa/models/enums/recurrent_task_inspection_data_type.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -9,16 +11,10 @@ class RecurrentWo { int? responseCode; bool? isSuccess; - RecurrentWo( - {this.recurrentWoData, - this.message, - this.title, - this.innerMessage, - this.responseCode, - this.isSuccess}); + RecurrentWo({this.recurrentWoData, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess}); RecurrentWo.fromJson(Map json) { - recurrentWoData = json['data'] != null ? RecurrentWoData.fromJson(json['data']) : null; + recurrentWoData = json['data'] != null ? RecurrentWoData.fromJson(json['data']) : null; message = json['message']; title = json['title']; innerMessage = json['innerMessage']; @@ -27,7 +23,7 @@ class RecurrentWo { } Map toJson() { - final Map data = {}; + final Map data = {}; if (recurrentWoData != null) { data['data'] = recurrentWoData!.toJson(); } @@ -51,75 +47,74 @@ class RecurrentWoData { Lookup? department; Lookup? room; List? planRecurrentMedicalTaskRooms; - List? planRecurrentTaskTimers; + List? planRecurrentTaskTimers; TimerModel? recurrentWoTimerModel = TimerModel(); + double? totalWorkingHours=0.0; RecurrentWoData( {this.id, - this.engineer, - this.scheduleDate, - this.status, - this.site, - this.building, - this.recurrentWoTimerModel, - this.floor, - this.department, - this.room, - this.planRecurrentMedicalTaskRooms, - this.planRecurrentTaskTimers}); + this.engineer, + this.scheduleDate, + this.status, + this.site, + this.building, + this.recurrentWoTimerModel, + this.floor, + this.department, + this.room, + this.planRecurrentMedicalTaskRooms, + this.planRecurrentTaskTimers, + this.totalWorkingHours}); RecurrentWoData.fromJson(Map json) { id = json['id']; - engineer = json['engineer'] != null - ? new Engineer.fromJson(json['engineer']) - : null; + engineer = json['engineer'] != null ? new Engineer.fromJson(json['engineer']) : null; scheduleDate = json['scheduleDate']; - status = - json['status'] != null ? Status.fromJson(json['status']) : null; + status = json['status'] != null ? Status.fromJson(json['status']) : null; site = json['site'] != null ? Site.fromJson(json['site']) : null; - building= json["building"] == null ? null : Lookup.fromJson(json["building"]); - floor= json["floor"] == null ? null : Lookup.fromJson(json["floor"]); - department= json["department"] == null ? null : Lookup.fromJson(json["department"]); - room= json["room"] == null ? null : Lookup.fromJson(json["room"]); + building = json["building"] == null ? null : Lookup.fromJson(json["building"]); + floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]); + department = json["department"] == null ? null : Lookup.fromJson(json["department"]); + room = json["room"] == null ? null : Lookup.fromJson(json["room"]); if (json['planRecurrentMedicalTaskRooms'] != null) { planRecurrentMedicalTaskRooms = []; json['planRecurrentMedicalTaskRooms'].forEach((v) { - planRecurrentMedicalTaskRooms! - .add(PlanRecurrentMedicalTaskRooms.fromJson(v)); + planRecurrentMedicalTaskRooms!.add(PlanRecurrentMedicalTaskRooms.fromJson(v)); }); } if (json['planRecurrentTaskTimers'] != null) { - //TODO match with exact data and replace... - // planRecurrentTaskTimers = []; - // json['planRecurrentTaskTimers'].forEach((v) { - // planRecurrentTaskTimers!.add(new Null.fromJson(v)); - // }); + planRecurrentTaskTimers = []; + json['planRecurrentTaskTimers'].forEach((v) { + planRecurrentTaskTimers?.add(PlanRecurrentTaskTimers.fromJson(v)); + }); + totalWorkingHours = json['planRecurrentTaskTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; } } - Map toJson() { + Map toJson({int? status = 0}) { final Map data = {}; + List taskRoomTabAttributesJson = []; + if (planRecurrentMedicalTaskRooms != null) { + taskRoomTabAttributesJson = planRecurrentMedicalTaskRooms + ?.expand((room) => room.planRecurrentMedicalTaskRoomTabs ?? []) + .expand((tab) => tab.planRecurrentMedicalTaskRoomTabAttributes ?? []) + .map((attribute) => attribute.toJson()) + .toList() ?? + []; + } data['id'] = id; - if (engineer != null) { - data['engineer'] = engineer!.toJson(); + data['statusValue'] = status; + + if (planRecurrentTaskTimers != null) { + data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); } - data['scheduleDate'] = scheduleDate; - if (status != null) { - data['status'] = status!.toJson(); + if (taskRoomTabAttributesJson.isNotEmpty) { + data['attributes'] = taskRoomTabAttributesJson; } - if (site != null) { - data['site'] = site!.toJson(); + else{ + data['attributes'] = []; } - if (planRecurrentMedicalTaskRooms != null) { - data['planRecurrentMedicalTaskRooms'] = - planRecurrentMedicalTaskRooms!.map((v) => v.toJson()).toList(); - } - if (planRecurrentTaskTimers != null) { - //TODO match with exact data and replace... - // data['planRecurrentTaskTimers'] = - // this.planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); - } return data; } } @@ -131,12 +126,7 @@ class Engineer { String? employeeId; int? languageId; - Engineer( - {this.userId, - this.userName, - this.email, - this.employeeId, - this.languageId}); + Engineer({this.userId, this.userName, this.email, this.employeeId, this.languageId}); Engineer.fromJson(Map json) { userId = json['userId']; @@ -147,12 +137,12 @@ class Engineer { } Map toJson() { - final Map data = new Map(); - data['userId'] = this.userId; - data['userName'] = this.userName; - data['email'] = this.email; - data['employeeId'] = this.employeeId; - data['languageId'] = this.languageId; + final Map data = {}; + data['userId'] = userId; + data['userName'] = userName; + data['email'] = email; + data['employeeId'] = employeeId; + data['languageId'] = languageId; return data; } } @@ -171,10 +161,10 @@ class Status { } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['name'] = this.name; - data['value'] = this.value; + final Map data = {}; + data['id'] = id; + data['name'] = name; + data['value'] = value; return data; } } @@ -191,9 +181,9 @@ class Site { } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['siteName'] = this.siteName; + final Map data = {}; + data['id'] =id; + data['siteName'] = siteName; return data; } } @@ -203,32 +193,27 @@ class PlanRecurrentMedicalTaskRooms { Room? room; List? planRecurrentMedicalTaskRoomTabs; - PlanRecurrentMedicalTaskRooms( - {this.id, this.room, this.planRecurrentMedicalTaskRoomTabs}); + PlanRecurrentMedicalTaskRooms({this.id, this.room, this.planRecurrentMedicalTaskRoomTabs}); PlanRecurrentMedicalTaskRooms.fromJson(Map json) { id = json['id']; - room = json['room'] != null ? new Room.fromJson(json['room']) : null; + room = json['room'] != null ? Room.fromJson(json['room']) : null; if (json['planRecurrentMedicalTaskRoomTabs'] != null) { planRecurrentMedicalTaskRoomTabs = []; json['planRecurrentMedicalTaskRoomTabs'].forEach((v) { - planRecurrentMedicalTaskRoomTabs! - .add(new PlanRecurrentMedicalTaskRoomTabs.fromJson(v)); + planRecurrentMedicalTaskRoomTabs!.add(PlanRecurrentMedicalTaskRoomTabs.fromJson(v)); }); } } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - if (this.room != null) { - data['room'] = this.room!.toJson(); + final Map data = {}; + data['id'] = id; + if (room != null) { + data['room'] = room!.toJson(); } - if (this.planRecurrentMedicalTaskRoomTabs != null) { - data['planRecurrentMedicalTaskRoomTabs'] = this - .planRecurrentMedicalTaskRoomTabs! - .map((v) => v.toJson()) - .toList(); + if (planRecurrentMedicalTaskRoomTabs != null) { + data['planRecurrentMedicalTaskRoomTabs'] = planRecurrentMedicalTaskRoomTabs!.map((v) => v.toJson()).toList(); } return data; } @@ -246,9 +231,9 @@ class Room { } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['roomId'] = this.roomId; + final Map data = {}; + data['id'] = id; + data['roomId'] = roomId; return data; } } @@ -257,39 +242,29 @@ class PlanRecurrentMedicalTaskRoomTabs { int? id; String? tabName; int? tabMedicalRoomId; - List? - planRecurrentMedicalTaskRoomTabAttributes; + List? planRecurrentMedicalTaskRoomTabAttributes; - PlanRecurrentMedicalTaskRoomTabs( - {this.id, - this.tabName, - this.tabMedicalRoomId, - this.planRecurrentMedicalTaskRoomTabAttributes}); + PlanRecurrentMedicalTaskRoomTabs({this.id, this.tabName, this.tabMedicalRoomId, this.planRecurrentMedicalTaskRoomTabAttributes}); PlanRecurrentMedicalTaskRoomTabs.fromJson(Map json) { id = json['id']; tabName = json['tabName']; tabMedicalRoomId = json['tabMedicalRoomId']; if (json['planRecurrentMedicalTaskRoomTabAttributes'] != null) { - planRecurrentMedicalTaskRoomTabAttributes = - []; + planRecurrentMedicalTaskRoomTabAttributes = []; json['planRecurrentMedicalTaskRoomTabAttributes'].forEach((v) { - planRecurrentMedicalTaskRoomTabAttributes! - .add(new PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(v)); + planRecurrentMedicalTaskRoomTabAttributes!.add( PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(v)); }); } } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - data['tabName'] = this.tabName; - data['tabMedicalRoomId'] = this.tabMedicalRoomId; - if (this.planRecurrentMedicalTaskRoomTabAttributes != null) { - data['planRecurrentMedicalTaskRoomTabAttributes'] = this - .planRecurrentMedicalTaskRoomTabAttributes! - .map((v) => v.toJson()) - .toList(); + final Map data = {}; + data['id'] = id; + data['tabName'] = tabName; + data['tabMedicalRoomId'] = tabMedicalRoomId; + if (planRecurrentMedicalTaskRoomTabAttributes != null) { + data['planRecurrentMedicalTaskRoomTabAttributes'] = planRecurrentMedicalTaskRoomTabAttributes!.map((v) => v.toJson()).toList(); } return data; } @@ -298,27 +273,20 @@ class PlanRecurrentMedicalTaskRoomTabs { class PlanRecurrentMedicalTaskRoomTabAttributes { int? id; Attribute? attribute; - Null? attributeValue; + dynamic attributeValue; - PlanRecurrentMedicalTaskRoomTabAttributes( - {this.id, this.attribute, this.attributeValue}); + PlanRecurrentMedicalTaskRoomTabAttributes({this.id, this.attribute, this.attributeValue}); - PlanRecurrentMedicalTaskRoomTabAttributes.fromJson( - Map json) { + PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(Map json) { id = json['id']; - attribute = json['attribute'] != null - ? new Attribute.fromJson(json['attribute']) - : null; - attributeValue = json['attributeValue']; + attribute = json['attribute'] != null ? Attribute.fromJson(json['attribute']) : null; + attributeValue = json['attributeValue'] ?? (json['attribute']['type'] == 'bool' ? (json['attributeValue']?.toString() == 'true') : json['attributeValue']); } Map toJson() { - final Map data = new Map(); - data['id'] = this.id; - if (this.attribute != null) { - data['attribute'] = this.attribute!.toJson(); - } - data['attributeValue'] = this.attributeValue; + final Map data = {}; + data['id'] = id; + data['attributeValue'] =attributeValue!=null? attributeValue.toString():attributeValue; return data; } } @@ -327,20 +295,47 @@ class Attribute { String? name; String? type; String? key; + RecurrentTaskInspectionDataTypeEnum? dataTypeEnum; - Attribute({this.name, this.type, this.key}); + Attribute({this.name, this.type, this.key, this.dataTypeEnum}); Attribute.fromJson(Map json) { name = json['name']; type = json['type']; + dataTypeEnum = json['type'] == null ? null : (json['type'] as String).toRecurrentTaskInspectionDataTypeEnum(); key = json['key']; } Map toJson() { - final Map data = new Map(); - data['name'] = this.name; - data['type'] = this.type; - data['key'] = this.key; + final Map data = {}; + data['name'] = name; + data['type'] = type; + data['key'] = key; + return data; + } +} + +class PlanRecurrentTaskTimers { + int? id; + String? startTime; + String? endTime; + dynamic workingHours; + + PlanRecurrentTaskTimers({this.id, this.startTime, this.endTime, this.workingHours}); + + PlanRecurrentTaskTimers.fromJson(Map json) { + id = json['id']; + startTime = json['startTime']; + endTime = json['endTime']; + workingHours = json['workingHours']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['startTime'] = startTime; + data['endTime'] = endTime; + data['workingHours'] = workingHours; return data; } -} \ No newline at end of file +} diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 448d1950..8ccc5700 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -60,10 +60,12 @@ class AppColor { static const Color red50 = Color(0xffD02127); static const Color red60 = Color(0xff8C050A); static const Color red70 = Color(0xffF63939); + static const Color red80 = Color(0xfffdcdcd); //green static const Color green40 = Color(0xffBAFFE1); static const Color green50 = Color(0xff62BE96); + static const Color green30 = Color(0xffd8efe5); static const Color green60 = Color(0xff065E38); static const Color green70 = Color(0xff54C166); static const Color green15 = Color(0xff157D14); diff --git a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart index 0f4abfdb..3d8b7c42 100644 --- a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart +++ b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart @@ -67,13 +67,9 @@ class RecurrentWoItemView extends StatelessWidget { ), ], ).toShadowContainer(context, withShadow: showShadow).onPress(() async { - print('data i got is ${requestDetails?.id}'); - - RecurrentWo recurrentWo = await Provider.of(context,listen:false).getRecurrentWoById(context, id: requestDetails!.id!); - Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView( recurrentWo: recurrentWo))); - + Navigator.of(context).push(MaterialPageRoute(builder: (_) => RecurrentWorkOrderView(taskId: requestDetails!.id))); }); } - return SizedBox(); + return const SizedBox(); } } diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart index e8043355..118fa3ce 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart @@ -101,6 +101,7 @@ class _InternalMaintenanceRequestState extends State print("timerProgress:$isRunning"); }, onChange: (timer) async { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; return true; }, diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index 3cc8a907..ad7b8a3c 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -101,12 +101,6 @@ class _MaintenanceRequestFormState extends State with Si if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { - ActivityMaintenanceTimers model = ActivityMaintenanceTimers( - id: 0, - startTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.startAt!.toIso8601String(), // Handle potential null - endTime: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.endAt?.toIso8601String(), // Handle potential null - workingHours: ((requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.durationInSecond ?? 0) / 60 / 60), - ); requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers =requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers??[]; requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( ActivityMaintenanceTimers( diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart index 1257bf88..343d5e31 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_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'; @@ -13,15 +15,14 @@ import 'package:test_sa/service_request_latest/utilities/service_request_utils.d import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; -class AssetInfoWidget extends StatelessWidget { +class RecurrentTaskAssetInfoWidget extends StatelessWidget { + final RecurrentWoData? model; - final RecurrentWoData? model; // Use `final` since it's a StatelessWidget - - AssetInfoWidget({super.key, required this.model}); + RecurrentTaskAssetInfoWidget({super.key, required this.model}); @override Widget build(BuildContext context) { - double totalWorkingHours = 2.0; + return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -32,54 +33,72 @@ class AssetInfoWidget extends StatelessWidget { if (model?.status != null) StatusLabel( label: model?.status?.name, - textColor: AppColor.getRequestStatusTextColorByName(context,model?.status?.name), - backgroundColor: AppColor.getRequestStatusColorByName(context,model?.status?.name), + textColor: AppColor.getRequestStatusTextColorByName(context, model?.status?.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, model?.status?.name), ), 8.height, -// TODO need to replace this with correct data... - model!.site!.siteName!.bodyText(context).custom(color:AppColor.black10 ), + model!.site!.siteName!.bodyText(context).custom(color: AppColor.black10), 2.height, - '${context.translation.taskNo}: ${model!.site!.id!}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.taskNo}: ${model!.id!}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.site}: ${model!.site!.siteName!}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), ], ).toShadowContainer(context), 12.height, - model!.planRecurrentMedicalTaskRooms!.isEmpty? Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + model!.planRecurrentMedicalTaskRooms!.isEmpty + ? Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + 8.height, + buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + 8.height, + buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach, context: context), + 8.height, + _timerWidget(context, model!.totalWorkingHours!) + ], + // ], + ).toShadowContainer(context, padding: 12) + : _timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), + ], + ); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours) { + return Consumer( + + builder: (context, snapshot,child) { + return Column( children: [ - buildingInfoWidget(label: context.translation.department, value: model!.department!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), - 8.height, - buildingInfoWidget(label: context.translation.floor, value: model!.floor!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), - 8.height, - buildingInfoWidget(label: context.translation.room, value: model!.room!.name!.cleanupWhitespace.capitalizeFirstOfEach,context: context), - 8.height, AppTimer( label: context.translation.timer, - timer: model!.recurrentWoTimerModel, - width:double.infinity, - enabled: model!.recurrentWoTimerModel?.endAt == null, + timer: snapshot.recurrentWoData?.recurrentWoTimerModel, + width: double.infinity, + enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null, decoration: BoxDecoration( color: AppColor.neutral100, borderRadius: BorderRadius.circular(10), ), timerProgress: (isRunning) {}, onChange: (timer) async { - timer = timer; + snapshot.updateRecurrentWoTimer(timer: timer); return true; }, ), - // if (totalWorkingHours > 0.0) ...[ 11.height, + if (totalWorkingHours > 0.0) ...[ Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ Text( "Total Working Time: ", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: context.isDark ? null : AppColor.neutral20, + fontWeight: FontWeight.w500, + ), ), Text( " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", @@ -87,39 +106,39 @@ class AssetInfoWidget extends StatelessWidget { ), ], ), + ], 8.height, ], - // ], - ).toShadowContainer(context,padding: 12):const SizedBox(), - ], + ); + } ); } +} - Widget buildingInfoWidget({required String label, required String value, required BuildContext context}) { - return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - label, - style: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.neutral120), - ), - 3.height, - Text( - value, - style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), - ) - ], - ).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false); - } +Widget buildingInfoWidget({required String label, required String value, required BuildContext context}) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + label, + style: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.neutral120), + ), + 3.height, + Text( + value, + style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), + ) + ], + ).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false); } -class DummyModel{ - RequestsDetails? request; - Ppm? ppm; - TimerModel? timerModel = TimerModel(); - double totalWorkingHours = 2; +class DummyModel { + RequestsDetails? request; + Ppm? ppm; + TimerModel? timerModel = TimerModel(); + double totalWorkingHours = 2; - DummyModel(this.request,this.ppm,this.timerModel,this.totalWorkingHours); + DummyModel(this.request, this.ppm, this.timerModel, this.totalWorkingHours); } diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 09334adb..56dd7470 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -1,10 +1,13 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:test_sa/dashboard_latest/dashboard_view.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/enums/recurrent_task_inspection_data_type.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; class RoomInspectionCard extends StatefulWidget { final PlanRecurrentMedicalTaskRoomTabs? inspectionModel; @@ -16,14 +19,11 @@ class RoomInspectionCard extends StatefulWidget { } class _RoomInspectionCardState extends State { - late List inspectionValues; // Add a list to store the state of switches + late List inspectionValues; @override void initState() { super.initState(); - inspectionValues = widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes! - .map((inspectionType) => inspectionType.attributeValue != null) - .toList(); } @override @@ -31,20 +31,30 @@ class _RoomInspectionCardState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - widget.inspectionModel!.tabName! - .bodyText(context) - .custom(color: AppColor.neutral50, fontWeight: FontWeight.w600), + widget.inspectionModel!.tabName!.bodyText(context).custom(color: AppColor.neutral50, fontWeight: FontWeight.w600), 8.height, Column( - children: widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes - ?.asMap() - .entries - .map((entry) => inspectionStatusRadioWidget( - index: entry.key, - label: entry.value.attribute!.name??'', - context: context, - )) - .toList() ?? + children: widget.inspectionModel!.planRecurrentMedicalTaskRoomTabAttributes?.asMap().entries.map((entry) { + final model = entry.value; + final attribute = model.attribute; + + switch (attribute?.dataTypeEnum) { + case RecurrentTaskInspectionDataTypeEnum.bool: + return inspectionStatusRadioWidget( + index: entry.key, + model: model, + context: context, + ); + case RecurrentTaskInspectionDataTypeEnum.number: + return inspectionStatusNumberWidget( + index: entry.key, + model: model, + context: context, + ); + default: + return const SizedBox.shrink(); // Handles any unexpected cases gracefully + } + }).toList() ?? [], ) ], @@ -53,39 +63,80 @@ class _RoomInspectionCardState extends State { Widget inspectionStatusRadioWidget({ required int index, - required String label, + required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context, }) { - String status = inspectionValues[index] ? 'Pass' : 'Fail'; + bool status = model.attributeValue; + String statusString = status ? 'Pass' : 'Fail'; + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - label - .bodyText2(context) - .custom(color: AppColor.white936, fontWeight: FontWeight.w500), - status - .bodyText2(context) - .custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), + model.attribute!.name!.bodyText2(context).custom(color: AppColor.white936, fontWeight: FontWeight.w500), + statusString.bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), ], ), - CupertinoSwitch( - thumbColor: - inspectionValues[index] ? AppColor.green50 : AppColor.red30, - activeColor: inspectionValues[index] - ? AppColor.green50.withOpacity(0.25) - : AppColor.red30.withOpacity(0.25), - value: inspectionValues[index], - onChanged: (state) { - setState(() { - inspectionValues[index] = state; - }); + SizedBox( + height: 24.toScreenHeight, + width: 41.toScreenWidth, + child: CupertinoSwitch( + thumbColor: status ? AppColor.green50 : AppColor.red30, + activeColor: AppColor.green30, + trackColor: AppColor.red80, + value: status, + onChanged: (state) { + setState(() { + model.attributeValue = state; + status = state; + }); + }, + ), + ) + ], + ).paddingOnly(bottom: 12); + } + + Widget inspectionStatusNumberWidget({ + required int index, + required PlanRecurrentMedicalTaskRoomTabAttributes model, + required BuildContext context, + }) { + final border = OutlineInputBorder( + borderRadius: BorderRadius.circular(4), // Optional: Slight rounding + borderSide: const BorderSide( + color: AppColor.white70, // Border color + width: 1, // 1px border + ), + ); + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + model.attribute!.name!.bodyText2(context).custom(color: AppColor.white936, fontWeight: FontWeight.w500), + TextFormField( + keyboardType: TextInputType.number, + initialValue: model.attributeValue??'', + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth), + filled: true, + fillColor: AppColor.neutral100, + constraints: const BoxConstraints( + maxHeight: 30, + maxWidth: 50, + ), + border: border, + enabledBorder: border, + focusedBorder: border, + ), + onChanged: (value){ + model.attributeValue=value; }, ), ], ).paddingOnly(bottom: 12); } } - diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart index 25eea61a..decd93e1 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart @@ -5,7 +5,6 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; -import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; @@ -25,57 +24,54 @@ class _RoomTabsWidgetState extends State { Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, children: [ Container( - padding: EdgeInsets.all(12.toScreenHeight), + padding: EdgeInsets.all(8.toScreenHeight), + height: 57.toScreenHeight, + width: double.infinity, decoration: BoxDecoration( color: context.isDark ? AppColor.neutral50 : AppColor.white10, borderRadius: BorderRadius.circular(10), ), - child: SingleChildScrollView( + child: ListView( scrollDirection: Axis.horizontal, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: widget.model!.planRecurrentMedicalTaskRooms!.asMap().entries.map((entry) { - final int index = entry.key; - final String label = entry.value.room!.roomId!; - return GestureDetector( - onTap: () { - setState(() { - isLoading = true; - selectedIndex = index; - //TODO replace with api response delay... - Future.delayed(const Duration(seconds: 1)).whenComplete(() { - setState(() { - isLoading = false; - }); + // mainAxisAlignment: MainAxisAlignment.spaceAround, + children: widget.model!.planRecurrentMedicalTaskRooms!.asMap().entries.map((entry) { + final int index = entry.key; + final String label = entry.value.room!.roomId!; + return GestureDetector( + onTap: () { + setState(() { + isLoading = true; + selectedIndex = index; + //TODO replace with api response delay... + Future.delayed(const Duration(seconds: 1)).whenComplete(() { + setState(() { + isLoading = false; }); }); - }, - child: Container( - margin: EdgeInsets.only(right: 8.toScreenWidth), - padding: EdgeInsets.symmetric( - vertical: 20.toScreenHeight, - horizontal: 30.toScreenWidth, - ), - alignment: Alignment.center, - decoration: BoxDecoration( - color: selectedIndex == index ? (context.isDark ? AppColor.neutral60 : AppColor.neutral110) : Colors.transparent, - borderRadius: BorderRadius.circular(7), - ), - child: label.bodyText(context).custom( - color: selectedIndex == index ? (context.isDark ? AppColor.white10 : AppColor.black20) : (context.isDark ? AppColor.neutral30 : AppColor.black20), - fontWeight: FontWeight.w600, - ), + }); + }, + child: Container( + // margin: EdgeInsets.only(right: 8.toScreenWidth), + height: 49.toScreenHeight, + padding: EdgeInsets.symmetric( + // vertical: 20.toScreenHeight, + horizontal: 30.toScreenWidth, ), - ); - }).toList(), - ), + alignment: Alignment.center, + decoration: BoxDecoration( + color: selectedIndex == index ? (context.isDark ? AppColor.neutral60 : AppColor.neutral110) : Colors.transparent, + borderRadius: BorderRadius.circular(7), + ), + child: label.bodyText(context).custom( + color:AppColor.white936, + ), + ), + ); + }).toList(), ), ), - 12.height, - // Display the Selected Tab Content isLoading ? SizedBox(height: 120.toScreenHeight, child: const ALoading().center) : ListView( diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 5ae21521..fb7f268d 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -1,15 +1,12 @@ -import 'package:flutter/cupertino.dart'; +import 'dart:developer'; + import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/ppm_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/widget_extensions.dart'; -import 'package:test_sa/models/all_requests_and_count_model.dart'; -import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; -import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; @@ -18,13 +15,14 @@ import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/compone import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; +import '../../../../../../controllers/providers/api/all_requests_provider.dart'; import 'components/room_tabs_widget.dart'; class RecurrentWorkOrderView extends StatefulWidget { static const String id = "/recurrent_wo"; - final RecurrentWo recurrentWo; + final int? taskId; - const RecurrentWorkOrderView({Key? key, required this.recurrentWo}) : super(key: key); + RecurrentWorkOrderView({Key? key, required this.taskId}) : super(key: key); @override _RecurrentWorkOrderViewState createState() { @@ -33,15 +31,12 @@ class RecurrentWorkOrderView extends StatefulWidget { } class _RecurrentWorkOrderViewState extends State { - UserProvider? userProvider; - TimerModel? timerModel = TimerModel(); - PpmProvider? ppmProvider; - - // double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; - double totalWorkingHours = 2.0; + AllRequestsProvider? allRequestsProvider; @override void initState() { + allRequestsProvider = Provider.of(context, listen: false); + Provider.of(context, listen: false).getRecurrentWoById(id: widget.taskId!); super.initState(); } @@ -52,75 +47,102 @@ class _RecurrentWorkOrderViewState extends State { @override Widget build(BuildContext context) { - userProvider ??= Provider.of(context, listen: false); - ppmProvider ??= Provider.of(context, listen: false); - print('data i got is ${widget.recurrentWo.recurrentWoData?.toJson()}'); - RoomTabs.getRoomTabs(); - return Scaffold( - appBar: DefaultAppBar(title: context.translation.recurrentWo), - //TODO refactor this after getting api... - body: widget.recurrentWo.recurrentWoData != null - ? Stack( - children: [ - SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AssetInfoWidget(model: widget.recurrentWo.recurrentWoData), - 16.height, - widget.recurrentWo.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty - ? RoomTabsWidget( - model: widget.recurrentWo.recurrentWoData, - ) - : const SizedBox(), - ], - ).paddingAll(12), - ).paddingOnly(bottom: 85), - FooterActionButton.footerContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + return Consumer(builder: (context, requestProvider, child) { + return Scaffold( + appBar: DefaultAppBar(title: context.translation.recurrentWo), + body: allRequestsProvider!.isLoading + ? const ALoading() + : requestProvider.recurrentWoData != null + ? Stack( children: [ - AppFilledButton( - label: context.translation.save, - buttonColor: AppColor.white60, - textColor: AppColor.black10, - onPressed: () async { - print('save clicked...'); - }, - ).expanded, - 12.width, - AppFilledButton( - label: context.translation.complete, - buttonColor: AppColor.primary10, - onPressed: () async { - print('complete clicked...'); - }, - ).expanded, + SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RecurrentTaskAssetInfoWidget(model: requestProvider.recurrentWoData), + // 8.height, + requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty + ? Column( + children: [ + 8.height, + RoomTabsWidget( + model: requestProvider.recurrentWoData, + ), + ], + ) + : const SizedBox(), + ], + ).paddingAll(12), + ).paddingOnly(bottom: 85), + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _updateTask( + context: context, + status: 0, + ), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _updateTask( + context: context, + status: 1, + ), + ).expanded, + ], + ), + ), ], - ), - ), - ], - ) - : NoDataFound(message: context.translation.noDataFound).center, - ); + ) + : NoDataFound(message: context.translation.noDataFound).center, + ); + }); } } -class RoomTabs { - String label; - int tag; +void _updateTask({required BuildContext context, required int status}) async { + + AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); + + if(validate(model: allRequestsProvider.recurrentWoData!)){ + allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; + + final workingHours = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt == null ? 0 : (allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt ?? DateTime.now()).difference(allRequestsProvider.recurrentWoData!.recurrentWoTimerModel!.startAt!).inSeconds; + print('working hours is ${workingHours}'); + return; + allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( + PlanRecurrentTaskTimers( + id: 0, + startTime: allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt?.toIso8601String(), + endTime: allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt?.toIso8601String(), + workingHours: ((allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.durationInSecond ?? 0) / 60 / 60), + ), + ); + await allRequestsProvider.updateRecurrentWo( + status: status, + ); + Navigator.pop(context); + } - RoomTabs({ - required this.label, - required this.tag, - }); - static List getRoomTabs() { - List roomTabs = []; - for (int i = 0; i < DummyData.roomData.length; i++) { - roomTabs.add(RoomTabs(label: DummyData.roomData[i]['name'], tag: i)); - } - return roomTabs; +} + +bool validate({required RecurrentWoData model}) { + if (model.recurrentWoTimerModel?.startAt == null) { + Fluttertoast.showToast(msg: "Working Hours Required"); + return false; + } + if (model.recurrentWoTimerModel?.endAt == null) { + Fluttertoast.showToast(msg: "Please Stop The Timer"); + return false; } + return true; } From ce1044f2014fe6392f3248d9d4ea95f7a0019ec9 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Thu, 6 Feb 2025 11:27:55 +0300 Subject: [PATCH 5/5] timer and working hours issue fixes --- .../providers/api/all_requests_provider.dart | 4 +- lib/l10n/app_ar.arb | 4 +- lib/l10n/app_en.arb | 5 +- lib/models/ppm/recurrent_wo.dart | 27 +-- .../requests/recurrent_wo_item_view.dart | 4 +- .../recurrent_wo/components/dummy_data.dart | 184 ------------------ .../components/room_inspection_card.dart | 14 +- ...info_widget.dart => task_info_widget.dart} | 4 +- .../recurrent_work_order_view.dart | 33 ++-- 9 files changed, 50 insertions(+), 229 deletions(-) delete mode 100644 lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart rename lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/{asset_info_widget.dart => task_info_widget.dart} (97%) diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index ca8801b2..94004f1f 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -62,7 +62,7 @@ class AllRequestsProvider extends ChangeNotifier { // AllRequestsAndCount? get completedRequests => _completedRequests; AllRequestsAndCount? get requestDetailList => _requestDetailList; - RecurrentWoData? _recurrentWoData; + RecurrentWoData? _recurrentWoData=RecurrentWoData(); RecurrentWoData? get recurrentWoData => _recurrentWoData; @@ -198,7 +198,6 @@ class AllRequestsProvider extends ChangeNotifier { Response response; try { response = await ApiManager.instance.get(URLs.getRecurrentPlanByIdUrl + "?planRecurrentTaskId=$id"); - stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); @@ -220,7 +219,6 @@ class AllRequestsProvider extends ChangeNotifier { Response response; try { response = await ApiManager.instance.post(URLs.updateRecurrentPlanUrl, body: recurrentWoData!.toJson(status: status)); - print('response i got back is ${response.body}'); stateCode = response.statusCode; isLoading = false; notifyListeners(); diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 6c613add..0fa2b641 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -530,10 +530,10 @@ "createdDate": "تاريخ الإنشاء", "employeeId": "رقم الموظف", "extensionNo": "رقم التمديد", - "recurrentWo": "أمر العمل المتكرر" + "checkIn": "تسجيل الدخول", "pmWo": "أمر العمل الوقائي", - "recurrentWo": "أمر العمل المتكرر", + "taskNo": "رقم المهمة", "assignEngineer": "تعيين مهندس", "scheduledDate": "التاريخ المجدول", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 143082d1..80cf85eb 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -537,10 +537,7 @@ "assignEngineer": "Assign Engineer", "scheduledDate": "Scheduled Date", "complete": "Complete", - "recurrentWo": "Recurrent WO" - "checkIn": "Check in", "createdDate": "Created Date", "employeeId": "Employee ID", - "extensionNo": "Extension No", - "recurrentWo": "Recurrent WO" + "extensionNo": "Extension No" } \ No newline at end of file diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index 0fcc44c9..acea8df2 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -49,7 +49,7 @@ class RecurrentWoData { List? planRecurrentMedicalTaskRooms; List? planRecurrentTaskTimers; TimerModel? recurrentWoTimerModel = TimerModel(); - double? totalWorkingHours=0.0; + double? totalWorkingHours = 0.0; RecurrentWoData( {this.id, @@ -82,12 +82,14 @@ class RecurrentWoData { planRecurrentMedicalTaskRooms!.add(PlanRecurrentMedicalTaskRooms.fromJson(v)); }); } + if (json['planRecurrentTaskTimers'] != null) { planRecurrentTaskTimers = []; json['planRecurrentTaskTimers'].forEach((v) { planRecurrentTaskTimers?.add(PlanRecurrentTaskTimers.fromJson(v)); }); - totalWorkingHours = json['planRecurrentTaskTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; + //TODO need to test this @waseem.. + totalWorkingHours = json['planRecurrentTaskTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDateTime']).difference(DateTime.parse(item['startDateTime'])).inSeconds) ?? 0; } } @@ -110,8 +112,7 @@ class RecurrentWoData { } if (taskRoomTabAttributesJson.isNotEmpty) { data['attributes'] = taskRoomTabAttributesJson; - } - else{ + } else { data['attributes'] = []; } @@ -182,7 +183,7 @@ class Site { Map toJson() { final Map data = {}; - data['id'] =id; + data['id'] = id; data['siteName'] = siteName; return data; } @@ -253,7 +254,7 @@ class PlanRecurrentMedicalTaskRoomTabs { if (json['planRecurrentMedicalTaskRoomTabAttributes'] != null) { planRecurrentMedicalTaskRoomTabAttributes = []; json['planRecurrentMedicalTaskRoomTabAttributes'].forEach((v) { - planRecurrentMedicalTaskRoomTabAttributes!.add( PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(v)); + planRecurrentMedicalTaskRoomTabAttributes!.add(PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(v)); }); } } @@ -286,7 +287,7 @@ class PlanRecurrentMedicalTaskRoomTabAttributes { Map toJson() { final Map data = {}; data['id'] = id; - data['attributeValue'] =attributeValue!=null? attributeValue.toString():attributeValue; + data['attributeValue'] = attributeValue != null ? attributeValue.toString() : attributeValue; return data; } } @@ -325,17 +326,17 @@ class PlanRecurrentTaskTimers { PlanRecurrentTaskTimers.fromJson(Map json) { id = json['id']; - startTime = json['startTime']; - endTime = json['endTime']; - workingHours = json['workingHours']; + startTime = json['startDateTime']; + endTime = json['endDateTime']; + workingHours = json['workingHour']; } Map toJson() { final Map data = {}; data['id'] = id; - data['startTime'] = startTime; - data['endTime'] = endTime; - data['workingHours'] = workingHours; + data['startDateTime'] = startTime; + data['endDateTime'] = endTime; + data['workingHour'] = workingHours; return data; } } diff --git a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart index 3d8b7c42..35e111ab 100644 --- a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart +++ b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart @@ -49,8 +49,8 @@ class RecurrentWoItemView extends StatelessWidget { 8.height, (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), 8.height, - '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), - '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), + '${context.translation.taskNo}: ${requestDetails!.id}'.bodyText(context), + '${context.translation.site}: ${requestDetails!.site}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), 16.height, diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart deleted file mode 100644 index 51b3e6bb..00000000 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart +++ /dev/null @@ -1,184 +0,0 @@ -class DummyData { - static List> roomData = [ - { - "name": "Room 1", - "cards": [ - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": true - }, - { - "label": "Room Humidity <35%", - "value": true - }, - { - "label": "Valve value", - "value": false - }, - { - "label": "Alarm Check", - "value": true - }, - { - "label": "Overall Result", - "value": true - } - ] - }, - { - "title": "Manifold", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": true - }, - { - "label": "Room Humidity <35%", - "value": true - }, - { - "label": "Valve value", - "value": false - }, - { - "label": "Alarm Check", - "value": true - } - ] - } - ] - }, - { - "name": "Room 2", - "cards": [ - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": true - }, - { - "label": "Room Humidity <35%", - "value": true - }, - { - "label": "Valve value", - "value": true - }, - { - "label": "Alarm Check", - "value": true - }, - { - "label": "Overall Result", - "value": true - } - ] - } - ] - }, - { - "name": "Room 3", - "cards": [ - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": false - }, - { - "label": "Room Humidity <35%", - "value": false - }, - { - "label": "Valve value", - "value": true - }, - { - "label": "Alarm Check", - "value": true - }, - { - "label": "Overall Result", - "value": false - } - ] - } - ] - }, - { - "name": "Room 4", - "cards": [ - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": false - }, - { - "label": "Room Humidity <35%", - "value": false - }, - { - "label": "Valve value", - "value": true - }, - { - "label": "Alarm Check", - "value": true - }, - { - "label": "Overall Result", - "value": false - } - ] - }, - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": false - }, - { - "label": "Room Humidity <35%", - "value": false - }, - { - "label": "Valve value", - "value": true - }, - { - "label": "Alarm Check", - "value": true - }, - ] - }, - { - "title": "General Inspection", - "info": [ - { - "label": "Room Temperature (15-35 C)", - "value": false - }, - { - "label": "Room Humidity <35%", - "value": false - }, - { - "label": "Valve value", - "value": true - }, - ] - } - - ] - } - ]; -} diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 56dd7470..f827aef5 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -66,7 +66,11 @@ class _RoomInspectionCardState extends State { required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context, }) { - bool status = model.attributeValue; + bool status = model.attribute != null + ? model.attributeValue == 'true' + ? true + : false + : false; String statusString = status ? 'Pass' : 'Fail'; return Row( @@ -85,7 +89,7 @@ class _RoomInspectionCardState extends State { width: 41.toScreenWidth, child: CupertinoSwitch( thumbColor: status ? AppColor.green50 : AppColor.red30, - activeColor: AppColor.green30, + activeColor: AppColor.green30, trackColor: AppColor.red80, value: status, onChanged: (state) { @@ -119,7 +123,7 @@ class _RoomInspectionCardState extends State { model.attribute!.name!.bodyText2(context).custom(color: AppColor.white936, fontWeight: FontWeight.w500), TextFormField( keyboardType: TextInputType.number, - initialValue: model.attributeValue??'', + initialValue: model.attributeValue ?? '', decoration: InputDecoration( contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth), filled: true, @@ -132,8 +136,8 @@ class _RoomInspectionCardState extends State { enabledBorder: border, focusedBorder: border, ), - onChanged: (value){ - model.attributeValue=value; + onChanged: (value) { + model.attributeValue = value; }, ), ], diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart similarity index 97% rename from lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart rename to lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 343d5e31..d3be2d64 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -15,10 +15,10 @@ import 'package:test_sa/service_request_latest/utilities/service_request_utils.d import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; -class RecurrentTaskAssetInfoWidget extends StatelessWidget { +class RecurrentTaskInfoWidget extends StatelessWidget { final RecurrentWoData? model; - RecurrentTaskAssetInfoWidget({super.key, required this.model}); + RecurrentTaskInfoWidget({super.key, required this.model}); @override Widget build(BuildContext context) { diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index fb7f268d..81cfc5cf 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; @@ -9,10 +7,10 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; -import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/asset_info_widget.dart'; -import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/dummy_data.dart'; +import 'package:test_sa/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import '../../../../../../controllers/providers/api/all_requests_provider.dart'; @@ -60,7 +58,7 @@ class _RecurrentWorkOrderViewState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - RecurrentTaskAssetInfoWidget(model: requestProvider.recurrentWoData), + RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData), // 8.height, requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty ? Column( @@ -114,22 +112,29 @@ void _updateTask({required BuildContext context, required int status}) async { if(validate(model: allRequestsProvider.recurrentWoData!)){ allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; - - final workingHours = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt == null ? 0 : (allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt ?? DateTime.now()).difference(allRequestsProvider.recurrentWoData!.recurrentWoTimerModel!.startAt!).inSeconds; - print('working hours is ${workingHours}'); - return; + DateTime ?startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt; + DateTime ?endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt; + final duration = (endTime?.difference(startTime!)); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( PlanRecurrentTaskTimers( id: 0, - startTime: allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt?.toIso8601String(), - endTime: allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt?.toIso8601String(), - workingHours: ((allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.durationInSecond ?? 0) / 60 / 60), + startTime: startTime?.toIso8601String(), + endTime: endTime?.toIso8601String(), + workingHours: (duration?.inSeconds ?? 0) / 60 / 60, ), ); await allRequestsProvider.updateRecurrentWo( status: status, - ); - Navigator.pop(context); + ).whenComplete((){ + if(status==1){// when click complete then this request remove from the list and status changes to closed.. + //TODO some issues data not properly refreshed need to check waseem + allRequestsProvider.getAllRequests(context,typeTransaction: 5); + } + allRequestsProvider.recurrentWoData?.recurrentWoTimerModel=null; + Navigator.pop(context); + Navigator.pop(context); + }); }