From 4c328b2cba12cf9d39cc5d99f6b3288a3de34437 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 18 Feb 2025 17:22:00 +0300 Subject: [PATCH] recurrent task timer improvements. --- .../providers/api/all_requests_provider.dart | 4 + lib/models/new_models/dashboard_detail.dart | 1 - lib/models/ppm/recurrent_wo.dart | 2 + .../pages/land_page/requests_list_page.dart | 2 - .../maintenance_request_main.dart | 3 +- .../components/room_inspection_card.dart | 91 ++++++++----------- .../components/room_tabs_widget.dart | 7 +- .../components/task_info_widget.dart | 65 ++++++------- .../recurrent_work_order_view.dart | 68 +++++++------- 9 files changed, 108 insertions(+), 135 deletions(-) diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 94004f1f..f4f96064 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -233,6 +233,10 @@ class AllRequestsProvider extends ChangeNotifier { void updateRecurrentWoTimer({TimerModel? timer}) { recurrentWoData?.recurrentWoTimerModel = timer; + if (timer?.startAt != null && timer?.endAt != null) { + recurrentWoData?.timerModelList = recurrentWoData?.timerModelList ?? []; + recurrentWoData?.timerModelList!.add(timer!); + } notifyListeners(); } diff --git a/lib/models/new_models/dashboard_detail.dart b/lib/models/new_models/dashboard_detail.dart index 9e091277..d71932a5 100644 --- a/lib/models/new_models/dashboard_detail.dart +++ b/lib/models/new_models/dashboard_detail.dart @@ -11,7 +11,6 @@ class DashboardDetail { DashboardDetail.fromJson(Map json) { totalRows = json['totalRows']; - print('total rows is $totalRows'); if (json['data'] != null) { data = []; json['data'].forEach((v) { diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index 9241a518..4844ce65 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -52,6 +52,7 @@ class RecurrentWoData { List? planRecurrentTaskTimers; TimerModel? recurrentWoTimerModel = TimerModel(); double? totalWorkingHours = 0.0; + List? timerModelList = []; RecurrentWoData( {this.id, @@ -68,6 +69,7 @@ class RecurrentWoData { this.room, this.planRecurrentMedicalTaskRooms, this.planRecurrentTaskTimers, + this.timerModelList, this.totalWorkingHours}); RecurrentWoData.fromJson(Map json) { diff --git a/lib/new_views/pages/land_page/requests_list_page.dart b/lib/new_views/pages/land_page/requests_list_page.dart index a62b5980..45aa9994 100644 --- a/lib/new_views/pages/land_page/requests_list_page.dart +++ b/lib/new_views/pages/land_page/requests_list_page.dart @@ -51,8 +51,6 @@ class _RequestsListPageState extends State { _scrollController = ScrollController(); int pageNo = 1; _scrollController.addListener(() async { - log('loading value i got is ${_dashBoardProvider.isDetailLoading}'); - log('total rows i got is ${_dashBoardProvider.requestDetailList!.totalRows}'); if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_dashBoardProvider.isDetailLoading && (_dashBoardProvider.requestDetailList!.data!.length < _dashBoardProvider.requestDetailList!.totalRows!.toInt())) { 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 1236fd92..90f4ebcd 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 @@ -46,9 +46,10 @@ class _MaintenanceRequestFormState extends State with Si @override Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { + bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; return Scaffold( backgroundColor: AppColor.neutral110, - appBar: DefaultAppBar(title: context.translation.maintenanceRequest), + appBar: DefaultAppBar(title: isUpdate ? "Update Activity" : "New Activity"), body: Stack( children: [ DefaultTabController( 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 0eccc069..16cb8850 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,15 +1,10 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:test_sa/dashboard_latest/dashboard_view.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/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'; -import 'package:toggle_switch/toggle_switch.dart'; class RoomInspectionCard extends StatefulWidget { final PlanRecurrentMedicalTaskRoomTabs? inspectionModel; @@ -21,7 +16,8 @@ class RoomInspectionCard extends StatefulWidget { } class _RoomInspectionCardState extends State { - int selectedIndex =0; + int selectedIndex = 0; + @override void initState() { super.initState(); @@ -34,33 +30,28 @@ class _RoomInspectionCardState extends State { children: [ widget.inspectionModel!.tabName!.bodyText(context).custom(color: AppColor.neutral50, fontWeight: FontWeight.w600), 8.height, - Column( - 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() ?? - [], + Container( + color: Colors.white10, + child: Column( + 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() ?? + [], + ), ) ], ).toShadowContainer(context).paddingOnly(top: 12); } + Widget inspectionStatusRadioWidget({ required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, @@ -68,8 +59,8 @@ class _RoomInspectionCardState extends State { }) { bool status = model.attribute != null ? model.attributeValue == 'true' - ? true - : false + ? true + : false : false; return Row( @@ -79,17 +70,15 @@ class _RoomInspectionCardState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - width: 220.toScreenWidth, - child: Text( - model.attribute!.name!, - overflow: TextOverflow.ellipsis, - maxLines: 1, // Ensures text is limited to one line before ellipsis - ), + Text( + model.attribute!.name!, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936), ), (status ? 'Pass' : 'Fail').bodyText2(context).custom(color: AppColor.neutral120, fontWeight: FontWeight.w500), ], - ), + ).expanded, GestureDetector( onTap: () { setState(() { @@ -102,7 +91,7 @@ class _RoomInspectionCardState extends State { height: 30.toScreenHeight, padding: EdgeInsetsDirectional.all(4.toScreenHeight), decoration: BoxDecoration( - color:AppColor.white80, + color: AppColor.white80, borderRadius: BorderRadius.circular(5), ), child: Row( @@ -113,7 +102,7 @@ class _RoomInspectionCardState extends State { isActive: status, activeColor: AppColor.green20, inactiveColor: Colors.transparent, - textColor: status ? AppColor.green50 :AppColor.black20, + textColor: status ? AppColor.green50 : AppColor.black20, ), buildToggleOption( label: "FAIL", @@ -127,8 +116,9 @@ class _RoomInspectionCardState extends State { ), ), ], - ).paddingOnly(bottom: 12); + ).paddingOnly(top: 6, bottom: 6); } + Widget buildToggleOption({ required String label, required bool isActive, @@ -148,7 +138,6 @@ class _RoomInspectionCardState extends State { ); } - // Widget inspectionStatusRadioWidget({ // required int index, // required PlanRecurrentMedicalTaskRoomTabAttributes model, @@ -195,11 +184,7 @@ class _RoomInspectionCardState extends State { // ).paddingOnly(bottom: 12); // } - Widget inspectionStatusNumberWidget({ - required int index, - required PlanRecurrentMedicalTaskRoomTabAttributes model, - required BuildContext context, - }) { + Widget inspectionStatusNumberWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) { final border = OutlineInputBorder( borderRadius: BorderRadius.circular(4), // Optional: Slight rounding borderSide: const BorderSide( @@ -219,7 +204,7 @@ class _RoomInspectionCardState extends State { contentPadding: EdgeInsets.symmetric(horizontal: 5.toScreenWidth), filled: true, fillColor: AppColor.neutral100, - constraints: BoxConstraints( + constraints: BoxConstraints( maxWidth: 99.toScreenWidth, maxHeight: 30.toScreenHeight, ), @@ -232,14 +217,10 @@ class _RoomInspectionCardState extends State { }, ), ], - ).paddingOnly(bottom: 12); + ).paddingOnly(bottom: 6, top: 6); } } - - - - // // I need it here .... // Container( // padding: EdgeInsets.all(6.toScreenHeight), @@ -297,4 +278,4 @@ class _RoomInspectionCardState extends State { // // onToggle: (index) { // // print('switched to: $index'); // // }, -// // ), \ No newline at end of file +// // ), 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 1aa6fa01..9d7f01b0 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 @@ -37,6 +37,7 @@ class _RoomTabsWidgetState extends State { child: ListView( scrollDirection: Axis.horizontal, // mainAxisAlignment: MainAxisAlignment.spaceAround, + padding: EdgeInsets.zero, children: widget.model!.planRecurrentMedicalTaskRooms!.asMap().entries.map((task) { final int index = task.key; final String label = task.value.room!.roomId!; @@ -65,9 +66,7 @@ class _RoomTabsWidgetState extends State { color: selectedIndex == index ? (context.isDark ? AppColor.neutral60 : AppColor.neutral110) : Colors.transparent, borderRadius: BorderRadius.circular(7), ), - child: label.bodyText(context).custom( - color: AppColor.white936, - ), + child: label.bodyText(context).custom(color: AppColor.white936), ), ); }).toList(), @@ -77,7 +76,7 @@ class _RoomTabsWidgetState extends State { ? const ALoading().paddingOnly(top: 150) : ListView( shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, 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/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 46cd88e4..ad99c375 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -22,7 +22,6 @@ class RecurrentTaskInfoWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -39,7 +38,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { 8.height, model!.title!.bodyText(context).custom(color: AppColor.black10), 2.height, - '${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.taskNo}: ${model!.taskNo!}'.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), @@ -67,51 +66,43 @@ class RecurrentTaskInfoWidget extends StatelessWidget { } Widget _timerWidget(BuildContext context, double totalWorkingHours) { - return Consumer( - - builder: (context, snapshot,child) { - return Column( - children: [ - AppTimer( - label: context.translation.timer, - 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 { - snapshot.updateRecurrentWoTimer(timer: timer); - return true; - }, + return Consumer(builder: (context, snapshot, child) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTimer( + label: context.translation.timer, + timer: snapshot.recurrentWoData?.recurrentWoTimerModel, + width: double.infinity, + // enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null, + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), ), - 11.height, - if (totalWorkingHours > 0.0) ...[ + timerProgress: (isRunning) {}, + onChange: (timer) async { + snapshot.updateRecurrentWoTimer(timer: timer); + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start, children: [ + 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120), + 8.width, Text( - "Total Working Time: ", - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: context.isDark ? null : AppColor.neutral20, - fontWeight: FontWeight.w500, - ), - ), - Text( - " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyMedium, + ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), + style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), ), ], ), - ], - 8.height, ], - ); - } - ); + ], + ); + }); } } 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 fc62b613..8b3eb979 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 @@ -13,11 +13,12 @@ import 'package:test_sa/service_request_latest/views/components/action_button/fo 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'; import 'components/room_tabs_widget.dart'; class RecurrentWorkOrderView extends StatefulWidget { - static const String routeName = "/recurrent_wo"; + static const String routeName = "/recurrent_wo"; final int? taskId; RecurrentWorkOrderView({Key? key, required this.taskId}) : super(key: key); @@ -51,7 +52,7 @@ class _RecurrentWorkOrderViewState extends State { body: allRequestsProvider!.isLoading ? const ALoading() : requestProvider.recurrentWoData != null - ? Stack ( + ? Stack( children: [ SingleChildScrollView( child: Column( @@ -64,9 +65,7 @@ class _RecurrentWorkOrderViewState extends State { ? Column( children: [ 8.height, - RoomTabsWidget( - model: requestProvider.recurrentWoData, - ), + RoomTabsWidget(model: requestProvider.recurrentWoData), ], ) : const SizedBox(), @@ -81,19 +80,13 @@ class _RecurrentWorkOrderViewState extends State { label: context.translation.save, buttonColor: AppColor.white60, textColor: AppColor.black10, - onPressed: () => _updateTask( - context: context, - status: 0, - ), + onPressed: () => _updateTask(context: context, status: 0), ).expanded, 12.width, AppFilledButton( label: context.translation.complete, buttonColor: AppColor.primary10, - onPressed: () => _updateTask( - context: context, - status: 1, - ), + onPressed: () => _updateTask(context: context, status: 1), ).expanded, ], ), @@ -107,37 +100,42 @@ class _RecurrentWorkOrderViewState extends State { } void _updateTask({required BuildContext context, required int status}) async { - AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); - if(validate(model: allRequestsProvider.recurrentWoData!)){ + if (validate(model: allRequestsProvider.recurrentWoData!)) { allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; - DateTime ?startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt; - DateTime ?endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt; - final duration = (endTime?.difference(startTime!)); + 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: startTime?.toIso8601String(), - endTime: endTime?.toIso8601String(), - workingHours: (duration?.inSeconds ?? 0) / 60 / 60, - ), - ); - await allRequestsProvider.updateRecurrentWo( + + allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( + PlanRecurrentTaskTimers( + id: 0, + startTime: timer.startAt!.toIso8601String(), // Handle potential null + endTime: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + + await allRequestsProvider + .updateRecurrentWo( status: status, - ).whenComplete((){ - if(status==1){// when click complete then this request remove from the list and status changes to closed.. + ) + .whenComplete(() { + if (status == 1) { + // when click complete then this request remove from the list and status changes to closed.. allRequestsProvider.reset(); - allRequestsProvider.getAllRequests(context,typeTransaction: 5); + allRequestsProvider.getAllRequests(context, typeTransaction: 5); } - allRequestsProvider.recurrentWoData?.recurrentWoTimerModel=null; - Navigator.pop(context); - Navigator.pop(context); + allRequestsProvider.recurrentWoData?.recurrentWoTimerModel = null; + Navigator.pop(context); + Navigator.pop(context); }); } - - } bool validate({required RecurrentWoData model}) {