From 904f1919d4230a99835cbf24dd13e4f02374a2df Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Sun, 17 Nov 2024 14:05:12 +0300 Subject: [PATCH] all changes implemented --- assets/images/reminder_icon.svg | 6 + lib/controllers/api_routes/urls.dart | 3 + lib/dashboard_latest/dashboard_provider.dart | 113 +++++---- lib/dashboard_latest/dashboard_view.dart | 1 - .../widgets/request_category_fragment.dart | 46 ++-- .../widgets/requests_fragment.dart | 6 +- lib/extensions/enum_extensions.dart | 8 + lib/main.dart | 9 +- lib/models/enums/work_order_next_step.dart | 2 + .../activity_maintenance_model.dart | 11 +- .../new_models/work_order_detail_model.dart | 51 +++- .../requests/request_paginated_listview.dart | 1 + .../pages/land_page/requests_list_page.dart | 17 +- .../fault_description_provider.dart | 2 - .../need_visit_reminder_time_provider.dart | 35 +++ .../service_request_detail_provider.dart | 30 ++- .../utilities/service_request_utils.dart | 94 ++++---- .../action_button/footer_action_button.dart | 23 ++ .../components/activities_list_view.dart | 12 +- .../service_request_bottomsheet.dart | 224 +++++++++--------- .../views/components/initial_visit_card.dart | 30 ++- .../service_request_detail_view.dart | 14 +- .../components/weekly_calendar_fragment.dart | 9 +- .../components/internal_request.dart | 220 ++++++++++------- .../maintenance_request_main.dart | 41 +++- .../service_request_detail_main_view.dart | 16 +- 26 files changed, 648 insertions(+), 376 deletions(-) create mode 100644 assets/images/reminder_icon.svg create mode 100644 lib/providers/work_order/need_visit_reminder_time_provider.dart diff --git a/assets/images/reminder_icon.svg b/assets/images/reminder_icon.svg new file mode 100644 index 00000000..20da0cfd --- /dev/null +++ b/assets/images/reminder_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 7dda4726..74822eb6 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -43,6 +43,7 @@ class URLs { static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; + static get engineerDashboardUpcoming=> '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming'; static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept'; static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject'; @@ -53,6 +54,7 @@ class URLs { static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity'; static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; + static get engineerSetReminderUrl=> '$_baseUrl/ServiceRequest/EngineerSetReminder'; static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById'; static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode'; static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; @@ -123,6 +125,7 @@ class URLs { static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415"; + static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211"; static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302"; static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index 6081170f..68c61821 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/widgets.dart'; import 'package:http/http.dart'; @@ -51,7 +52,7 @@ class DashBoardProvider extends ChangeNotifier { List tabs = []; - void setTabs({required UsersTypes userType, required BuildContext context}) { + void setTabs({required UsersTypes userType, required BuildContext context}) { tabs = CategoryTabs.getTabs(userType: userType, context: context); } @@ -71,8 +72,9 @@ class DashBoardProvider extends ChangeNotifier { _requestDetailList = null; dashboardCount = null; } - void refreshDashboard({required UsersTypes userType,required BuildContext context}) { - setTabs(userType:userType,context: context); + + void refreshDashboard({required UsersTypes userType, required BuildContext context}) { + setTabs(userType: userType, context: context); getDashBoardCount(usersType: userType); resetRequestDataList(); getRequestDetail(usersType: userType, status: tabs[currentListIndex].tag); @@ -143,7 +145,11 @@ class DashBoardProvider extends ChangeNotifier { } void getHighPriorityRequests({bool showLoader = true, required UsersTypes usersType}) { - getRequestDetail(showLoader: showLoader, usersType: usersType, isHighPriority: true); + getRequestDetail( + showLoader: showLoader, + usersType: usersType, + isHighPriority: true, + ); } void getOverdueRequests({bool showLoader = true, required UsersTypes usersType}) { @@ -170,19 +176,21 @@ class DashBoardProvider extends ChangeNotifier { getRequestDetail(showLoader: showLoader, usersType: usersType, status: 4); } - Future getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false}) async { + Future getRequestDetail({bool showLoader = true, required UsersTypes usersType, int? status, bool isHighPriority = false, bool isOverdue = false, String? date}) async { if (showLoader) { isDetailLoading = showLoader; notifyListeners(); } - Response response; String url = ''; if (usersType == UsersTypes.engineer) { - if(status==0){ + //these checks are to call different apis for dashboard for engineer... + if (status == 0) { + url = URLs.engineerDashboardUpcoming; + } else if (status == 1) { url = URLs.engineerDashboardNotAssignDetails; - }else{ + } else { url = URLs.engineerDashboardDetailsUrl; } } else { @@ -190,52 +198,17 @@ class DashBoardProvider extends ChangeNotifier { } try { Map body = {"pageNumber": pageNum, "pageSize": pageItemNumber}; - if (status != null&&status!=0) body["statusValue"] = status; + + if (status != null && status == 0) { + body["date"] = date ?? DateTime.now().toIso8601String(); + } else { + body["statusValue"] = status; + } if (isHighPriority) body["isHighPriority"] = true; if (isOverdue) body["isOverdue"] = true; response = await ApiManager.instance.post(url, body: body); stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - if (_requestDetailList == null) { - _requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body)); - } else { - _requestDetailList!.data!.addAll(DD.DashboardDetail.fromJson(json.decode(response.body)).data ?? []); - } - if (_requestDetailList!.data!.length >= pageItemNumber) { - nextPage = true; - } else { - nextPage = false; - } - } else { - requestDetailList = null; - } - if (showLoader) { - isDetailLoading = false; - } - notifyListeners(); - return response.statusCode; - } catch (error) { - if (showLoader) { - isDetailLoading = false; - } - stateCode = -1; - notifyListeners(); - return -1; - } - } - Future getEngineerDashboardNotAssignedDetail({bool showLoader = true,}) async { - if (showLoader) { - isDetailLoading = showLoader; - notifyListeners(); - } - - Response response; - - try { - Map body = {"pageNumber": pageNum, "pageSize": pageItemNumber}; - response = await ApiManager.instance.post(URLs.engineerDashboardNotAssignDetails, body: body); - stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { if (_requestDetailList == null) { _requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body)); @@ -265,6 +238,48 @@ class DashBoardProvider extends ChangeNotifier { } } + // Future getDashboardEngineerUpcoming({bool showLoader = true, required String date}) async { + // if (showLoader) { + // isDetailLoading = showLoader; + // notifyListeners(); + // } + // + // + // Response response; + // + // try { + // Map body = {"pageNumber": pageNum, "pageSize": pageItemNumber}; + // response = await ApiManager.instance.post(URLs.engineerDashboardNotAssignDetails, body: body); + // stateCode = response.statusCode; + // if (response.statusCode >= 200 && response.statusCode < 300) { + // if (_requestDetailList == null) { + // _requestDetailList = DD.DashboardDetail.fromJson(json.decode(response.body)); + // } else { + // _requestDetailList!.data!.addAll(DD.DashboardDetail.fromJson(json.decode(response.body)).data ?? []); + // } + // if (_requestDetailList!.data!.length >= pageItemNumber) { + // nextPage = true; + // } else { + // nextPage = false; + // } + // } else { + // requestDetailList = null; + // } + // if (showLoader) { + // isDetailLoading = false; + // } + // notifyListeners(); + // return response.statusCode; + // } catch (error) { + // if (showLoader) { + // isDetailLoading = false; + // } + // stateCode = -1; + // notifyListeners(); + // return -1; + // } + // } + bool get isDetailLoading => _isDetailLoading; set isDetailLoading(bool value) { diff --git a/lib/dashboard_latest/dashboard_view.dart b/lib/dashboard_latest/dashboard_view.dart index 6457ec2b..ce8c6f23 100644 --- a/lib/dashboard_latest/dashboard_view.dart +++ b/lib/dashboard_latest/dashboard_view.dart @@ -70,7 +70,6 @@ class _DashboardViewState extends State { if (isFCM) { FirebaseNotificationManger.initialized(context); NotificationManger.initialisation((notificationDetails) { - print('i am called with notification details ${notificationDetails.toString()}'); FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload!)); }, (id, title, body, payload) async {}); diff --git a/lib/dashboard_latest/widgets/request_category_fragment.dart b/lib/dashboard_latest/widgets/request_category_fragment.dart index ef40a6df..ea04a212 100644 --- a/lib/dashboard_latest/widgets/request_category_fragment.dart +++ b/lib/dashboard_latest/widgets/request_category_fragment.dart @@ -23,29 +23,29 @@ class RequestCategoryFragment extends StatelessWidget { bool isNurse = (Provider.of(context, listen: false).user?.type) == UsersTypes.normal_user; return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ //TODO uncommit this to get the calendar card.. - // !isNurse - // ? Column( - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // context.translation.allWorkOrder.heading4(context), - // GestureDetector( - // onTap: () { - // dashboardProvider.isShowDashBoardCalendar = !dashboardProvider.isShowDashBoardCalendar; - // }, - // child: dashboardProvider.isShowDashBoardCalendar ? AppAsset.listIcon.toSvgAsset() : AppAsset.calendarIcon.toSvgAsset()) - // ], - // ), - // dashboardProvider.isShowDashBoardCalendar - // ? Padding( - // padding: EdgeInsets.only(top: 12.toScreenHeight), - // child: const WeeklyCalendarFragment(), - // ) - // : const SizedBox(), - // ], - // ).paddingOnly(start: 16, end: 16) - // : + !isNurse&&dashboardProvider.tabs[dashboardProvider.currentListIndex].tag==0 + ? Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + context.translation.allWorkOrder.heading4(context), + GestureDetector( + onTap: () { + dashboardProvider.isShowDashBoardCalendar = !dashboardProvider.isShowDashBoardCalendar; + }, + child: dashboardProvider.isShowDashBoardCalendar ? AppAsset.listIcon.toSvgAsset() : AppAsset.calendarIcon.toSvgAsset()) + ], + ), + dashboardProvider.isShowDashBoardCalendar + ? Padding( + padding: EdgeInsets.only(top: 12.toScreenHeight), + child: const WeeklyCalendarFragment(), + ) + : const SizedBox(), + ], + ).paddingOnly(start: 14, end: 12) + : context.translation.allWorkOrder.heading4(context).paddingOnly(start: 16, end: 16), getTabs( requestsProvider: dashboardProvider, diff --git a/lib/dashboard_latest/widgets/requests_fragment.dart b/lib/dashboard_latest/widgets/requests_fragment.dart index bff7e1b0..0b7a5958 100644 --- a/lib/dashboard_latest/widgets/requests_fragment.dart +++ b/lib/dashboard_latest/widgets/requests_fragment.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -35,7 +36,7 @@ class RequestsFragment extends StatelessWidget { context.isDark ? AppColor.redStatus(context) : AppColor.red30, ), listItem(snapshot.dashboardCount?.data?.countOverdue ?? 0, "overdue", context.translation.overdue, context, snapshot.isAllCountLoading, 1, AppColor.yellowIcon(context)), - listItem(snapshot.dashboardCount?.data?.countOpen ?? 0, "new_request", ApiManager.instance.user?.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, + listItem(snapshot.dashboardCount?.data?.countInprogress ?? 0, "new_request", ApiManager.instance.user?.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, context, snapshot.isAllCountLoading, 2, AppColor.primary10), listItem(snapshot.dashboardCount?.data?.countComplete ?? 0, "complete_request", context.translation.completed, context, snapshot.isAllCountLoading, 3, AppColor.greenStatus(context)), ], @@ -47,8 +48,9 @@ class RequestsFragment extends StatelessWidget { return GestureDetector( onTap: isLoading ? null - : () { + : () async { Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index, title))); + Provider.of(context, listen: false).refreshDashboard(userType: Provider.of(context, listen: false).user!.type!, context: context); }, child: Column( crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/extensions/enum_extensions.dart b/lib/extensions/enum_extensions.dart index 54e1714c..9e634cb6 100644 --- a/lib/extensions/enum_extensions.dart +++ b/lib/extensions/enum_extensions.dart @@ -33,6 +33,10 @@ extension EnumExtensionsWorkOrder on WorkOrderNextStepEnum { case WorkOrderNextStepEnum.waitingForRequesterToConfirm: //replace with correct value... return 31; + case WorkOrderNextStepEnum.eFixRemotely: + return 35; + case WorkOrderNextStepEnum.eNeedVisit: + return 36; } } } @@ -62,6 +66,10 @@ extension IntExtensionsWorkOrder on int { return WorkOrderNextStepEnum.assetRetirementManagementApproval; case 31: return WorkOrderNextStepEnum.waitingForRequesterToConfirm; + case 35: + return WorkOrderNextStepEnum.eFixRemotely; + case 36: + return WorkOrderNextStepEnum.eNeedVisit; default: return WorkOrderNextStepEnum.onlyView; } diff --git a/lib/main.dart b/lib/main.dart index c73c364e..c3079aec 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -54,6 +54,7 @@ import 'package:test_sa/providers/service_request_providers/requested_through_pr import 'package:test_sa/providers/service_request_providers/type_of_request_provider.dart'; import 'package:test_sa/providers/work_order/activity_status_provider.dart'; import 'package:test_sa/providers/work_order/fault_description_provider.dart'; +import 'package:test_sa/providers/work_order/need_visit_reminder_time_provider.dart'; import 'package:test_sa/providers/work_order/reason_provider.dart'; import 'package:test_sa/providers/work_order/retirement_type_provider.dart'; import 'package:test_sa/providers/work_order/service_type_provider.dart'; @@ -79,6 +80,7 @@ import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_pa import 'package:test_sa/views/widgets/departments/single_department_picker.dart'; import 'package:test_sa/views/widgets/equipment/asset_detail_page.dart'; import 'package:test_sa/views/widgets/equipment/single_device_picker.dart'; +import 'controllers/notification/notification_manger.dart'; import 'controllers/providers/api/gas_refill_comments.dart'; import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; @@ -93,9 +95,9 @@ import 'package:timezone/timezone.dart' as tz; void main() async { WidgetsFlutterBinding.ensureInitialized(); - // _configureLocalTimeZone(); - // NotificationManger.initialisation((notificationDetails) { - // }, (id, title, body, payload) async {}); + _configureLocalTimeZone(); + NotificationManger.initialisation((notificationDetails) { + }, (id, title, body, payload) async {}); if (Platform.isIOS) { await Firebase.initializeApp( @@ -232,6 +234,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => FaultDescriptionProvider()), ChangeNotifierProvider(create: (_) => RetirementTypeProvider()), ChangeNotifierProvider(create: (_) => ActivityStatusProvider()), + ChangeNotifierProvider(create: (_) => NeedVisitReminderTimeProvider()), ///todo deleted //ChangeNotifierProvider(create: (_) => AssetTypesProvider()), diff --git a/lib/models/enums/work_order_next_step.dart b/lib/models/enums/work_order_next_step.dart index 7c8bbcf7..20405c21 100644 --- a/lib/models/enums/work_order_next_step.dart +++ b/lib/models/enums/work_order_next_step.dart @@ -4,6 +4,8 @@ enum WorkOrderNextStepEnum { nTakeAction, // 5 eRejectAccept, // 9 eFixRemotelyNeedVisit, // 12 + eFixRemotely, // 35 + eNeedVisit, // 36 eArrived, // 15 verifyAssetDetail, // 16 activity, // 17 diff --git a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart index 0bc584cf..4b249619 100644 --- a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart +++ b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart @@ -4,6 +4,7 @@ import 'package:test_sa/models/new_models/assistant_employee.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; +import 'package:test_sa/models/timer_model.dart'; class ActivityMaintenanceHelperModel { int? id; @@ -32,6 +33,8 @@ class ActivityMaintenanceHelperModel { SuppEngineerWorkOrders? supEngineer; ActivityMaintenanceAssistantEmployees? modelAssistantEmployees; List? assistantEmployees; + List? activityMaintenanceTimers=[]; + TimerModel? activityMaintenanceTimerModel = TimerModel(); ActivityMaintenanceHelperModel( {this.id, @@ -43,6 +46,7 @@ class ActivityMaintenanceHelperModel { this.supplier, this.endTime, this.workingHour, + this.activityMaintenanceTimerModel, this.travelHours, this.repairLocation, this.assignedEmployeeId, @@ -55,6 +59,7 @@ class ActivityMaintenanceHelperModel { this.assistantEmployees, this.supEngineer, this.assignedEmployee, + this.activityMaintenanceTimers, this.modelAssistantEmployees}); @@ -76,10 +81,8 @@ class ActivityMaintenanceHelperModel { data['supplierStartTime'] = supplierStartTime?.toIso8601String(); data['supplierEndTime'] = supplierEndTime?.toIso8601String(); data['supplierWorkingHour'] = supplierWorkingHour; - // //TODO remove this when backend fix this on their side.. - // if(activityStatus!=null){ - // data['lastSituationId'] = activityStatus?.id; - // } + //TODO fix this properly... + data['activityMaintenanceTimers'] = activityMaintenanceTimers; if (assistantEmployees != null&&assistantEmployees!.isNotEmpty) { data['assistantEmployees'] = [modelAssistantEmployees?.toJson()]; } diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index dd8dc6fb..956b6c85 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -61,6 +61,7 @@ class WorkOrderData { required this.assignedEmployee, required this.lastActivityStatus, required this.status, + required this.setReminder, required this.nextStep, required this.assetVerificationType, required this.workOrderContactPerson, @@ -106,6 +107,7 @@ class WorkOrderData { WorkOrderAssignedEmployee? assignedEmployee; Lookup? lastActivityStatus; Lookup? status; + Lookup? setReminder; Lookup? nextStep; int? assetVerificationType; List workOrderContactPerson; @@ -150,8 +152,9 @@ class WorkOrderData { room: json["room"], assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]), assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]), - lastActivityStatus: json["lastActivityStatus"]!=null?Lookup.fromJson(json["lastActivityStatus"]):null, + lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null, status: json["status"] == null ? null : Lookup.fromJson(json["status"]), + setReminder: json["setReminder"] == null ? null : Lookup.fromJson(json["setReminder"]), nextStep: json["nextStep"] == null ? null : Lookup.fromJson(json["nextStep"]), assetVerificationType: json["assetVerificationType"], workOrderContactPerson: json["workOrderContactPerson"] == null ? [] : List.from(json["workOrderContactPerson"]!.map((x) => WorkOrderContactPerson.fromJson(x))), @@ -174,7 +177,7 @@ class WorkOrderData { totalWorkingHours: json["totalWorkingHours"], workOrderHistory: json["workOrderHistory"] == null ? [] : List.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))), activities: json["activities"] == null ? [] : List.from(json["activities"]!.map((x) => Activities.fromJson(x))), - needAVisitDateTime: DateTime.tryParse(json["requestedDate"] ?? ""), + needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""), needAVisitComment: json["needAVisitComment"], activityAssetToBeRetireds: json["activityAssetToBeRetireds"] == null ? [] : List.from(json["activityAssetToBeRetireds"]!.map((x) => x)), ); @@ -200,6 +203,7 @@ class WorkOrderData { "assignedEmployee": assignedEmployee?.toJson(), "lastActivityStatus": lastActivityStatus, "status": status?.toJson(), + "setReminder": setReminder?.toJson(), "nextStep": nextStep?.toJson(), "assetVerificationType": assetVerificationType, "workOrderContactPerson": workOrderContactPerson.map((x) => x?.toJson()).toList(), @@ -298,6 +302,7 @@ class WorkOrderAssignedEmployee { "languageId": languageId, }; } + class AssetLoan { AssetLoan({ required this.id, @@ -336,8 +341,6 @@ class AssetLoan { }; } - - class Activities { int? id; int? orderNo; @@ -535,8 +538,8 @@ class WorkOrderHistory { WorkOrderHistory({ required this.id, required this.workorderStatus, - this.assetVerificationType, - this.photoVerfication, + this.assetVerificationType, + this.photoVerfication, required this.activityStatus, required this.date, required this.timeDifference, @@ -554,7 +557,7 @@ class WorkOrderHistory { Lookup? assetVerificationType; dynamic activityStatus; DateTime? date; - String timeDifference =''; + String timeDifference = ''; String? photoVerfication; WorkOrderAssignedEmployee? user; Lookup? step; @@ -617,6 +620,7 @@ class ActivityMaintenance { String? supplierEndTime; double? supplierWorkingHours; List? assistantEmployees; + List? activityMaintenanceTimers; ActivityMaintenance( {this.id, @@ -628,6 +632,7 @@ class ActivityMaintenance { this.travelHours, this.repairLocation, this.assignedEmployee, + this.activityMaintenanceTimers, this.technicalComment, this.supplier, this.supplierEngineer, @@ -647,7 +652,6 @@ class ActivityMaintenance { repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; technicalComment = json['technicalComment']; - //json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]), supplier = json["supplier"] == null ? null : Lookup.fromJson(json["supplier"]); supplierEngineer = json["supplierEngineer"] == null ? null : Lookup.fromJson(json["supplierEngineer"]); @@ -661,6 +665,12 @@ class ActivityMaintenance { assistantEmployees!.add(ActivityMaintenanceAssistantEmployees.fromJson(v)); }); } + if (json['activityMaintenanceTimers'] != null) { + activityMaintenanceTimers = []; + json['activityMaintenanceTimers'].forEach((v) { + activityMaintenanceTimers!.add(ActivityMaintenanceTimers.fromJson(v)); + }); + } } Map toJson() { @@ -766,3 +776,28 @@ class ActivityMaintenanceAssistantEmployees { return data; } } + +class ActivityMaintenanceTimers { + int? id; + String? startTime; + String? endTime; + dynamic workingHours; + + ActivityMaintenanceTimers({this.id, this.startTime, this.endTime, this.workingHours}); + + ActivityMaintenanceTimers.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; + } +} diff --git a/lib/new_views/pages/land_page/requests/request_paginated_listview.dart b/lib/new_views/pages/land_page/requests/request_paginated_listview.dart index 8665c755..7e3c5aec 100644 --- a/lib/new_views/pages/land_page/requests/request_paginated_listview.dart +++ b/lib/new_views/pages/land_page/requests/request_paginated_listview.dart @@ -17,6 +17,7 @@ class RequestPaginatedListview extends StatelessWidget { @override Widget build(BuildContext context) { + print('count i got is ${totalCount}'); return ListView.builder( itemCount: list.length < totalCount ? list.length + 1 : list.length, controller: scrollController, 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 eb58aff8..8301a4e6 100644 --- a/lib/new_views/pages/land_page/requests_list_page.dart +++ b/lib/new_views/pages/land_page/requests_list_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -31,8 +33,11 @@ class _RequestsListPageState extends State { void initState() { super.initState(); _dashBoardProvider = Provider.of(context, listen: false); - _dashBoardProvider.resetRequestDataList(); - callRequestApis(); + scheduleMicrotask(() async { + _dashBoardProvider.resetRequestDataList(); + callRequestApis(); + }); + handleScroll(); } @@ -46,8 +51,11 @@ class _RequestsListPageState extends State { _scrollController = ScrollController(); int pageNo = 1; _scrollController.addListener(() async { - if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_dashBoardProvider.isDetailLoading) { + if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && + !_dashBoardProvider.isDetailLoading && + (_dashBoardProvider.requestDetailList!.data!.length < _dashBoardProvider.requestDetailList!.totalRows!.toInt())) { pageNo = pageNo + 1; + _dashBoardProvider.pageNum = pageNo; callRequestApis(showLoader: false, pageNo: pageNo); } }); @@ -95,10 +103,11 @@ class _RequestsListPageState extends State { })); } - Future callRequestApis({bool showLoader = true, int pageNo = 1, int pageSize = 12}) async { + Future callRequestApis({bool showLoader = true, int pageNo = 1, int pageSize = 10}) async { UsersTypes usersTypes = Provider.of(context, listen: false).user!.type!; if (widget.index == 0) { // high priority + _dashBoardProvider.getHighPriorityRequests(usersType: usersTypes, showLoader: showLoader); } else if (widget.index == 1) { // overdue diff --git a/lib/providers/work_order/fault_description_provider.dart b/lib/providers/work_order/fault_description_provider.dart index 670cb9e0..7f53e538 100644 --- a/lib/providers/work_order/fault_description_provider.dart +++ b/lib/providers/work_order/fault_description_provider.dart @@ -26,8 +26,6 @@ class FaultDescriptionProvider extends ChangeNotifier { try { response = await ApiManager.instance.get(URLs.getFaultDescription+"?assetId=$assetId",); - print('url is ${URLs.getFaultDescription+"?assetId=$assetId"}'); - print('response of get fault is ${response.body}'); List list = []; if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received diff --git a/lib/providers/work_order/need_visit_reminder_time_provider.dart b/lib/providers/work_order/need_visit_reminder_time_provider.dart new file mode 100644 index 00000000..791be80f --- /dev/null +++ b/lib/providers/work_order/need_visit_reminder_time_provider.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class NeedVisitReminderTimeProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getVisitReminderTimeValue); + print('response i got is ${response.body}'); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index b62ab23e..bd7f5958 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -123,6 +123,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier { void updateNeedVisitHelperModel(NeedVisitHelperModel? value) { needVisitHelperModel = value; + log ("value:${value!.visitDate.toString()}"); notifyListeners(); } @@ -380,6 +381,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + notifyListeners(); } isLoading = false; notifyListeners(); @@ -469,6 +471,33 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + //engineer Confirm Arrive...... + Future engineerSetReminder({required int workOrderId, required int reminderId}) async { + Response response; + try { + //"workOrderCreatedById": "string" + Map body = { + "workOrderId": workOrderId, + "setReminderId": reminderId, + }; + isLoading = true; + notifyListeners(); + response = await ApiManager.instance.post(URLs.engineerSetReminderUrl, body: body); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + } + if (response.statusCode >= 200 && response.statusCode < 300) {} + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (e) { + log("engineer accept [error] : $e"); + isLoading = false; + notifyListeners(); + return -1; + } + } //assignEngineerToWorkOrder...... Future assignEngineerWorkOrder({required String workOrderId, required String engineerId}) async { try { @@ -739,7 +768,6 @@ class ServiceRequestDetailProvider extends ChangeNotifier { body: activityMaintenanceHelperModel!.toJson(), ); stateCode = response.statusCode; - print('response of activity maintenace part is ${response.body}'); if (response.statusCode >= 200 && response.statusCode < 300) { // currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); // updateCurrentWorkOrder(currentWorkOrder); diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index ba5d154e..62c588bf 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -16,6 +16,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:huawei_push/huawei_push.dart' as h_push; + class ServiceRequestUtils { static double calculateAndAssignWorkingHours({ required DateTime? startTime, @@ -33,6 +34,7 @@ class ServiceRequestUtils { return -1; // Indicating invalid input } } + static String calculateTimeDifference(DateTime startDate, DateTime endDate) { try { Duration diff = startDate.difference(endDate); @@ -52,9 +54,31 @@ class ServiceRequestUtils { } } - static void getQrCode({required BuildContext context }) async{ + static String formatTimerDuration(int seconds) { + int hours = seconds ~/ 3600; + int minutes = (seconds % 3600) ~/ 60; + int remainingSeconds = seconds % 60; + + String formattedDuration = ''; + if (hours > 0) { + formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; + } + if (minutes > 0) { + formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; + } + if (remainingSeconds > 0) { + formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; + } + if (formattedDuration.isEmpty) { + formattedDuration = 'Less than a second'; + } + + return formattedDuration.trim(); + } + + static void getQrCode({required BuildContext context}) async { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - ServiceRequestDetailProvider requestDetailProvider = Provider.of(context,listen:false); + ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); String? base64String = await requestDetailProvider.getQrCode(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId ?? 0); Navigator.pop(context); if (base64String != null) { @@ -66,7 +90,7 @@ class ServiceRequestUtils { builder: (BuildContext context) { return AlertDialog( backgroundColor: Colors.white, - title:context.translation.scanQr.heading6(context).center, + title: context.translation.scanQr.heading6(context).center, content: Image.memory( bytes, // Displaying the QR code from base64 fit: BoxFit.contain, // Ensure the image fits well in the dialog @@ -74,61 +98,41 @@ class ServiceRequestUtils { return const Icon(Icons.error, color: Colors.red); }, ), - ); }, ); } else { print('Failed to get the QR code'); } - - } - - - static Widget testScheduleNotificationButton({required BuildContext context}){ - return ElevatedButton( - child: const Text('Schedule notifications'), - onPressed: () { - // debugPrint('Notification Scheduled for $D'); - // NotificationManger.showNotification(context: context, title: 'test notification', subtext: 'test notification', hashcode: 1); - - DateTime scheduleTime= DateTime.now().add(const Duration(seconds: 10)); - NotificationManger.scheduleNotification( - title: 'Scheduled Notification', - body: '$scheduleTime', - scheduledNotificationDateTime: scheduleTime);(); - }, - ); + static void scheduleNotification({required BuildContext context, required DateTime scheduleDateTime}) { + DateTime scheduleTime = scheduleDateTime; + NotificationManger.scheduleNotification(title: 'Scheduled Notification', body: '$scheduleTime', scheduledNotificationDateTime: scheduleTime); } + //steps: //add permission for andriod.. //add string in info.plist for ios... //create event.. - static Widget testAddEventToCalendarButton({required BuildContext context}){ - return ElevatedButton( - child: const Text('Add Event to Calendar'), - onPressed: () async { - var currentLocation = getLocation( await FlutterTimezone.getLocalTimezone()); - setLocalLocation(currentLocation); - await Future.delayed(const Duration(seconds: 2)); - var eventToCreate = Event( - "1", - title: "test123", - description: "test", - start: TZDateTime.now(currentLocation), - end: TZDateTime.now(currentLocation).add(const Duration(seconds: 10)), - ); - - final createEventResult = - await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); - if (createEventResult!.isSuccess) { - Fluttertoast.showToast(msg: 'added successfully'); - } - }, + static void addEventToCalendar({required BuildContext context, required DateTime start, required DateTime end,required String title}) async { + var currentLocation = getLocation(await FlutterTimezone.getLocalTimezone()); + setLocalLocation(currentLocation); + await Future.delayed(const Duration(seconds: 2)); + TZDateTime startDate = TZDateTime.from(start, currentLocation); + TZDateTime endDate = TZDateTime.from(end, currentLocation); + var eventToCreate = Event( + "1", + title: title, + description: "You have reminder for Visit", + start: startDate, + end: endDate, ); + print('title i got is ${eventToCreate.title}'); + await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); + } + // Map messageData = message.data; // if (messageData["notificationType"] != null && messageData["accept"] != null) { // if (messageData["notificationType"] == "arrivalConfirmation") { @@ -141,7 +145,6 @@ class ServiceRequestUtils { // } // } - static Future listenForApproval() async { print('listen for approval called..'); bool isVerified = false; @@ -198,6 +201,7 @@ class ServiceRequestUtils { return false; } } + class ConfirmArrivalNotificationModel { final String? transactionType; final String? requestId; @@ -234,4 +238,4 @@ class ConfirmArrivalNotificationModel { 'accept': accept, }; } -} \ No newline at end of file +} diff --git a/lib/service_request_latest/views/components/action_button/footer_action_button.dart b/lib/service_request_latest/views/components/action_button/footer_action_button.dart index e99854e9..400738ab 100644 --- a/lib/service_request_latest/views/components/action_button/footer_action_button.dart +++ b/lib/service_request_latest/views/components/action_button/footer_action_button.dart @@ -201,6 +201,29 @@ class FooterActionButton { textColor: AppColor.neutral150, fontSize: 12.toScreenWidth, )); + case WorkOrderNextStepEnum.eFixRemotely: + return footerContainer( + child: AppFilledButton( + label: context.translation.fixedRemotely, + maxWidth: true, + buttonColor: AppColor.green70, + onPressed: () async { + requestDetailProvider.fixRemotelyHelperModel = FixRemotelyHelperModel(); + ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context); + }, + ), + ); + case WorkOrderNextStepEnum.eNeedVisit: + return footerContainer( + child: AppFilledButton( + label: context.translation.needAVisit, + maxWidth: true, + buttonColor: AppColor.neutral50, + onPressed: () async { + requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(); + ServiceRequestBottomSheet.initialVisitBottomSheet(context: context); + }, + )); } } else { if (workOrderNextStepStatus == WorkOrderNextStepEnum.nTakeAction) { diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index b8c982d1..f2159926 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -20,6 +20,7 @@ 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/service_request_detail_provider.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/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart'; @@ -248,7 +249,9 @@ class _ActivitiesListViewState extends State { } Widget maintenanceActivityCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider, required BuildContext context, required Activities activity}) { - print('activity i got is ${activity.toJson()}'); + double totalWorkingHours = + activity.activityMaintenance?.activityMaintenanceTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; + return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -296,16 +299,16 @@ class _ActivitiesListViewState extends State { ), 3.height, Text( - '${context.translation.workingHours}: ${activity.activityMaintenance?.workingHours??'-'}', + '${context.translation.workingHours}: ${totalWorkingHours > 0.0 ? ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()) : '-'}', style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), 2.height, - if(activity.activityMaintenance?.assignedEmployee!=null&&activity.activityMaintenance!.assistantEmployees!.isNotEmpty)...[ + if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ Text( '${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}', style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), - ]else...[ + ] else ...[ Text( '${context.translation.assignedEmployee}: ${activity.activityMaintenance?.assignedEmployee?.userName}', style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), @@ -359,6 +362,7 @@ class _ActivitiesListViewState extends State { supplierStartTime: activity.activityMaintenance?.supplierStartTime != null ? DateTime.parse(activity.activityMaintenance!.supplierStartTime!) : null, supplierEndTime: activity.activityMaintenance?.supplierEndTime != null ? DateTime.parse(activity.activityMaintenance!.supplierEndTime!) : null, supplierWorkingHour: activity.activityMaintenance?.supplierWorkingHours, + activityMaintenanceTimers: activity.activityMaintenance?.activityMaintenanceTimers ?? [], supplier: activity.activityMaintenance?.supplier != null ? SupplierDetails( id: activity.activityMaintenance?.supplier?.id, diff --git a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart index 22e87f85..b3d9bfc9 100644 --- a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart +++ b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -17,6 +18,7 @@ import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/providers/service_request_providers/reject_reason_provider.dart'; +import 'package:test_sa/providers/work_order/need_visit_reminder_time_provider.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart'; @@ -31,12 +33,12 @@ import '../../../../new_views/common_widgets/app_filled_button.dart'; import '../../../../new_views/common_widgets/app_text_form_field.dart'; class ServiceRequestBottomSheet { - static buildBottomSheetParent({required BuildContext context, required Widget childWidget,bool ?isDismissible}) { + static buildBottomSheetParent({required BuildContext context, required Widget childWidget, bool? isDismissible}) { return showModalBottomSheet( context: context, useSafeArea: true, isScrollControlled: true, - isDismissible:isDismissible??true, + isDismissible: isDismissible ?? true, backgroundColor: Colors.transparent, builder: (context) => SingleChildScrollView( child: childWidget, @@ -202,14 +204,14 @@ class ServiceRequestBottomSheet { buttonColor: AppColor.green70, loading: false, onPressed: () async { - if(requestDetailProvider.fixRemotelyHelperModel?.startDate==null&&requestDetailProvider.fixRemotelyHelperModel?.endDate==null){ + if (requestDetailProvider.fixRemotelyHelperModel?.startDate == null && requestDetailProvider.fixRemotelyHelperModel?.endDate == null) { "Please Select start and end date".showToast; return; } requestDetailProvider.fixRemotelyHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder?.data?.requestId; requestDetailProvider.engineerFixRemotely(); Navigator.pop(context); - const SizedBox().flushBar(context: context, title: '', message: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm); + const SizedBox().flushBar(context: context, title: '', message: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm); }, ), ), @@ -246,25 +248,24 @@ class ServiceRequestBottomSheet { date: requestDetailProvider.needVisitHelperModel?.visitDate, formatDateWithTime: true, onDatePicker: (selectedDate) { - if (selectedDate != null) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - requestDetailProvider.needVisitHelperModel?.visitDate = selectedDateTime; - requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel); - } - }); - } + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + requestDetailProvider.needVisitHelperModel?.visitDate = selectedDateTime; + requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel); + print('selected date time i got is ${requestDetailProvider.needVisitHelperModel?.visitDate}'); + } + }); }, ), 8.height, @@ -290,24 +291,30 @@ class ServiceRequestBottomSheet { buttonColor: AppColor.primary10, loading: false, onPressed: () async { - if(requestDetailProvider.needVisitHelperModel?.visitDate==null){ + if (requestDetailProvider.needVisitHelperModel?.visitDate == null) { "Please select visit date".showToast; return; } if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { - requestDetailProvider.updateNeedVisitHelperModel(NeedVisitHelperModel( - workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId, - visitDate: requestDetailProvider.needVisitHelperModel?.visitDate, - comment: requestDetailProvider.needVisitHelperModel?.comment, - )); + requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; + // requestDetailProvider.updateNeedVisitHelperModel(NeedVisitHelperModel( + // workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId, + // visitDate: requestDetailProvider.needVisitHelperModel?.visitDate, + // comment: requestDetailProvider.needVisitHelperModel?.comment, + // )); + print('visit date i got is ${requestDetailProvider.needVisitHelperModel?.visitDate}'); requestDetailProvider.engineerUpdateNeedVisit(); + // await requestDetailProvider.getWorkOrderById(id: requestDetailProvider.needVisitHelperModel!.workOrderId!); } else { requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; requestDetailProvider.engineerNeedVisit(); requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(); + getReminderTimeList(context: context); + initialVisitReminderBottomSheet(context: context); } - Navigator.pop(context); - // initialVisitReminderBottomSheet(context: context); + + Navigator.pop(context); + // }, ), @@ -317,49 +324,60 @@ class ServiceRequestBottomSheet { })); } - static Future initialVisitReminderBottomSheet({required BuildContext context}) { - String selectedReminderTime = '10 minutes before'; + static Future getReminderTimeList({required BuildContext context}) async { + NeedVisitReminderTimeProvider timeProvider = Provider.of(context, listen: false); + timeProvider.reset(); + WidgetsBinding.instance.addPostFrameCallback((_) { + timeProvider.getDate(); + }); + } + static Future initialVisitReminderBottomSheet({required BuildContext context, Lookup? reminder}) { + Lookup selectedReminderTime = reminder ?? Lookup(); Widget reminderTimeWidget({required BuildContext context}) { - List reminderTimeList = ['5 minutes before', '10 minutes before', '15 minutes before']; + return Consumer(builder: (cxt, snapshot, _) { + if (snapshot.loading) { + return const ALoading(); + } - return StatefulBuilder( - builder: (context, setState) { - return Wrap( - direction: Axis.vertical, - runSpacing: 8, - spacing: 8, - children: [ - for (var element in reminderTimeList) - Row( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 24, - height: 24, - child: Radio( - value: element, - activeColor: Colors.red, - fillColor: MaterialStateColor.resolveWith((states) { - if (states.contains(MaterialState.selected)) return AppColor.primary10; - return AppColor.neutral130; - }), - groupValue: selectedReminderTime, - onChanged: (String? value) { - setState(() { - selectedReminderTime = value!; - }); - }, + return StatefulBuilder( + builder: (context, setState) { + return Wrap( + direction: Axis.vertical, + runSpacing: 8, + spacing: 20, + children: [ + for (var element in snapshot.items) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: Colors.red, + fillColor: MaterialStateColor.resolveWith((states) { + if (states.contains(MaterialState.selected)) return AppColor.primary10; + return AppColor.neutral130; + }), + groupValue: selectedReminderTime, + onChanged: (Lookup? value) { + setState(() { + selectedReminderTime = value!; + }); + }, + ), ), - ), - 8.width, - Text(element, style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral120)), - ], - ) - ], - ); - }, - ); + 8.width, + Text(element.name ?? '', style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral120)), + ], + ) + ], + ); + }, + ).toShimmer(isShow: snapshot.loading); + }); } return buildBottomSheetParent( @@ -380,7 +398,7 @@ class ServiceRequestBottomSheet { alignment: AlignmentDirectional.centerStart, child: context.translation.youCanSetTheReminderInAlarmToRemindYouBeforeVisit.bodyText2(context), ), - 12.height, + 30.height, reminderTimeWidget(context: context), 30.height, Row( @@ -393,20 +411,6 @@ class ServiceRequestBottomSheet { textColor: AppColor.black10, loading: false, onPressed: () async { - if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { - requestDetailProvider.updateNeedVisitHelperModel( - NeedVisitHelperModel( - workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId, - visitDate: requestDetailProvider.needVisitHelperModel?.visitDate, - comment: requestDetailProvider.needVisitHelperModel?.comment, - ), - ); - requestDetailProvider.engineerUpdateNeedVisit(); - } else { - requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; - requestDetailProvider.engineerNeedVisit(); - requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(); - } Navigator.pop(context); }, ), @@ -418,19 +422,16 @@ class ServiceRequestBottomSheet { buttonColor: AppColor.primary10, loading: false, onPressed: () async { - if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { - requestDetailProvider.updateNeedVisitHelperModel( - NeedVisitHelperModel( - workOrderId: requestDetailProvider.needVisitHelperModel?.workOrderId, - visitDate: requestDetailProvider.needVisitHelperModel?.visitDate, - comment: requestDetailProvider.needVisitHelperModel?.comment, - ), - ); - requestDetailProvider.engineerUpdateNeedVisit(); - } else { - requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; - requestDetailProvider.engineerNeedVisit(); - requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel(); + requestDetailProvider.engineerSetReminder(workOrderId: requestDetailProvider.currentWorkOrder!.data!.requestId!, reminderId: selectedReminderTime.id!); + try { + DateTime visitDateTime = DateTime.parse(requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime.toString()); + DateTime updatedDateTime = visitDateTime.subtract(Duration(minutes: selectedReminderTime.value ?? 0)); + if (updatedDateTime.isAfter(DateTime.now())) { + ServiceRequestUtils.scheduleNotification(context: context, scheduleDateTime: updatedDateTime); + ServiceRequestUtils.addEventToCalendar(context: context, start: updatedDateTime, end: visitDateTime, title: context.translation.needAVisit); + } + } catch (e) { + log('error $e'); } Navigator.pop(context); }, @@ -445,6 +446,7 @@ class ServiceRequestBottomSheet { ), ); } + static Future getQRCodeBottomSheet({required BuildContext context}) async { // Show the loading dialog while fetching QR code showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); @@ -481,12 +483,12 @@ class ServiceRequestBottomSheet { child: isLoading ? const ALoading() // Show loader while fetching the new QR code : Image.memory( - bytes, // Displaying the QR code from base64 - fit: BoxFit.contain, // Ensure the image fits well in the dialog - errorBuilder: (context, error, stackTrace) { - return const Icon(Icons.error, color: Colors.red); - }, - ), + bytes, // Displaying the QR code from base64 + fit: BoxFit.contain, // Ensure the image fits well in the dialog + errorBuilder: (context, error, stackTrace) { + return const Icon(Icons.error, color: Colors.red); + }, + ), ), ), 12.height, @@ -538,7 +540,6 @@ class ServiceRequestBottomSheet { }, ), 16.height, - ], ); }, @@ -549,7 +550,6 @@ class ServiceRequestBottomSheet { } } - static Future rejectRequestBottomSheet({required BuildContext context}) { TextEditingController _commentController = TextEditingController(); return buildBottomSheetParent( @@ -854,7 +854,7 @@ class ServiceRequestBottomSheet { buttonColor: AppColor.green70, loading: false, onPressed: () { - if(feedback.isEmpty){ + if (feedback.isEmpty) { "Please provide feedback".showToast; return; } @@ -1045,8 +1045,8 @@ class ServiceRequestBottomSheet { ], ); })); - } + static Future nurseVerifyArrivalBottomSheet({required BuildContext context}) { return buildBottomSheetParent( context: context, @@ -1094,7 +1094,7 @@ class ServiceRequestBottomSheet { buttonColor: AppColor.green70, onPressed: () async { Navigator.pop(context); - int? status = await requestDetailProvider.nurseConfirmEngineerArrival(workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId ?? 0); + int? status = await requestDetailProvider.nurseConfirmEngineerArrival(workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId ?? 0); if (status == 200) { requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); } @@ -1105,13 +1105,13 @@ class ServiceRequestBottomSheet { ], ); })); - } + static Future waitingForApprovalBottomSheet({required BuildContext context}) { return buildBottomSheetParent( context: context, childWidget: Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { - return Column( + return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -1132,7 +1132,5 @@ class ServiceRequestBottomSheet { ], ); })); - } - } diff --git a/lib/service_request_latest/views/components/initial_visit_card.dart b/lib/service_request_latest/views/components/initial_visit_card.dart index 3d777768..cd39e894 100644 --- a/lib/service_request_latest/views/components/initial_visit_card.dart +++ b/lib/service_request_latest/views/components/initial_visit_card.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; @@ -9,9 +11,18 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; -class InitialVisitCard extends StatelessWidget { +class InitialVisitCard extends StatefulWidget { const InitialVisitCard({Key? key}) : super(key: key); + @override + State createState() => _InitialVisitCardState(); +} + +class _InitialVisitCardState extends State { + @override + void initState() { + super.initState(); + } @override Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, snapshot) { @@ -27,13 +38,22 @@ class InitialVisitCard extends StatelessWidget { children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - requestDetailProvider.needVisitHelperModel!.visitDate.toString().toInitialVisitCardFormat, + requestDetailProvider.needVisitHelperModel!.visitDate != null ? requestDetailProvider.needVisitHelperModel!.visitDate.toString().toInitialVisitCardFormat : '', textAlign: TextAlign.end, style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.black10), ), - "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() { - ServiceRequestBottomSheet.initialVisitBottomSheet(context: context); - }), + Row( + children: [ + "reminder_icon".toSvgAsset(height: 21, width: 21).onPress(() { + ServiceRequestBottomSheet.getReminderTimeList(context: context); + ServiceRequestBottomSheet.initialVisitReminderBottomSheet(context: context, reminder: requestDetailProvider.currentWorkOrder?.data?.setReminder); + }), + 24.width, + "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() { + ServiceRequestBottomSheet.initialVisitBottomSheet(context: context); + }), + ], + ), ]), 2.height, context.translation.visitDateAndTime.bodyText2(context).custom(color: AppColor.neutral120), diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index efd45665..a79a0681 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -25,7 +25,7 @@ import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; class ServiceRequestDetailView extends StatelessWidget { - ServiceRequestDetailView({Key? key}) : super(key: key); + const ServiceRequestDetailView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -54,6 +54,7 @@ class ServiceRequestDetailView extends StatelessWidget { ).expanded, FooterActionButton.requestDetailsFooterWidget( workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, + // workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit, activities: requestProvider.currentWorkOrder!.data?.activities ?? [], userProvider: _userProvider, context: context), @@ -213,7 +214,6 @@ class ServiceRequestDetailView extends StatelessWidget { '${context.translation.assetStatus}: ${workOrder.equipmentStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), - //TODO need to confirm from backend.. Text( '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), @@ -330,11 +330,11 @@ class ServiceRequestDetailView extends StatelessWidget { if (requestDetailProvider.currentWorkOrder!.data!.needAVisitDateTime != null && userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { - requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel( - workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, - visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime, - comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment, - ); + // requestDetailProvider.needVisitHelperModel = NeedVisitHelperModel( + // workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, + // visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime, + // comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment, + // ); return const InitialVisitCard(); } else { return const SizedBox(); diff --git a/lib/service_request_latest/views/components/weekly_calendar_fragment.dart b/lib/service_request_latest/views/components/weekly_calendar_fragment.dart index 0261d9eb..335f93cf 100644 --- a/lib/service_request_latest/views/components/weekly_calendar_fragment.dart +++ b/lib/service_request_latest/views/components/weekly_calendar_fragment.dart @@ -1,9 +1,12 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; class WeeklyCalendarFragment extends StatefulWidget { @@ -51,6 +54,10 @@ class _WeeklyCalendarFragmentState extends State { setState(() { selectedDate = currentDate; // Update selected date on tap }); + log('selected date:${selectedDate?.toIso8601String()}'); + DashBoardProvider dashBoardProvider = Provider.of(context, listen: false); + dashBoardProvider.resetRequestDataList(); + dashBoardProvider.getRequestDetail(usersType: UsersTypes.engineer, date: selectedDate?.toIso8601String(), status: 0); }, ); }, @@ -94,7 +101,7 @@ class _WeeklyCalendarFragmentState extends State { decoration: ShapeDecoration( color: AppColor.background(context), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), + borderRadius: BorderRadius.circular(10), side: isSelected ? const BorderSide(color: AppColor.primary10, width: 2) // Blue border if selected : BorderSide.none, 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 a2e5caaf..e8043355 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 @@ -12,6 +12,7 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/timer/app_timer.dart'; import '../../../../../models/lookup.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; @@ -37,8 +38,7 @@ class _InternalMaintenanceRequestState extends State _requestDetailProvider = Provider.of(context, listen: false); super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - _travellingHoursController.text = - _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : ''; + _travellingHoursController.text= _requestDetailProvider?.activityMaintenanceHelperModel?.travelHours != null ? _requestDetailProvider!.activityMaintenanceHelperModel!.travelHours.toString() : ''; }); // _isLoading = true; } @@ -55,6 +55,7 @@ class _InternalMaintenanceRequestState extends State @override Widget build(BuildContext context) { return Consumer(builder: (context, requestDetailProvider, child) { + double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; return SingleChildScrollView( child: Column( children: [ @@ -92,95 +93,136 @@ class _InternalMaintenanceRequestState extends State }, ), 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; - requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - _workingHoursController.clear(); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - }, - ); - } - }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); - if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && - selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { - "End Date time must be greater then start date".showToast; - return; - } - requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - }, - ); - } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: _workingHoursController, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, + AppTimer( + label: context.translation.timer, + timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, + enabled: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel?.endAt == null, + timerProgress: (isRunning) { + print("timerProgress:$isRunning"); + }, + onChange: (timer) async { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; + return true; + }, ), + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // ADatePicker( + // label: context.translation.startTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // _workingHoursController.clear(); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // 8.width, + // ADatePicker( + // label: context.translation.endTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); + // if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && + // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { + // "End Date time must be greater then start date".showToast; + // return; + // } + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // ], + // ), 8.height, + if (totalWorkingHours > 0.0) ...[ + Container( + height: 56.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + alignment: Alignment.centerLeft, + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral40 : AppColor.background(context), + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + 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, + ), + ], + ), + ), + 8.height, + ], + // if (totalWorkingHours > 0.0) ...[ + // AppTextFormField( + // labelText: context.translation.workingHours, + // backgroundColor: AppColor.neutral80, + // controller: _workingHoursController, + // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', + // textAlign: TextAlign.center, + // labelStyle: AppTextStyles.textFieldLabelStyle, + // enable: false, + // showShadow: false, + // style: Theme.of(context).textTheme.titleMedium, + // ), + // 8.height, + // ], AppTextFormField( labelText: context.translation.travelingHours, controller: _travellingHoursController, 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 ce7ab161..2f03666a 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 @@ -99,10 +99,25 @@ class _MaintenanceRequestFormState extends State with Si //TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; - print('model is ${requestDetailProvider.activityMaintenanceHelperModel?.toJson()}'); if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { - + print('value of timer is ${requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel.toString()}'); + 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), + ); + print('model i got is ${model.toJson()}'); + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers =requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers??[]; + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( + 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), + ), + ); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); int status = -1; if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { @@ -130,23 +145,33 @@ class _MaintenanceRequestFormState extends State with Si } bool validate({required ActivityMaintenanceHelperModel model}) { - print('employee id is ${model.assignedEmployeeId}'); + if (model.activityStatus == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); return false; - } else if (model.startTime == null) { - Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.startTime}"); + } + if (model.activityMaintenanceTimerModel?.startAt == null) { + Fluttertoast.showToast(msg: "Working Hours Required"); return false; - } else if (model.endTime == null) { - Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.endTime}"); + } + if (model.activityMaintenanceTimerModel?.endAt == null) { + Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } + // if (model.startTime == null) { + // Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.startTime}"); + // return false; + // } + // if (model.endTime == null) { + // Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.endTime}"); + // return false; + // } // else if (model.travelHours == null) { // Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.travelingHours}"); // return false; // } - else if (model.repairLocation == null) { + if (model.repairLocation == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.repairLocation}"); return false; } diff --git a/lib/service_request_latest/views/service_request_detail_main_view.dart b/lib/service_request_latest/views/service_request_detail_main_view.dart index 2b9be210..a5f647d4 100644 --- a/lib/service_request_latest/views/service_request_detail_main_view.dart +++ b/lib/service_request_latest/views/service_request_detail_main_view.dart @@ -7,6 +7,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/work_order_next_step.dart'; +import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; @@ -43,6 +44,11 @@ class _ServiceRequestDetailMainState extends State { if (isNurse && (_requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.waitingForRequesterToConfirm)) { ServiceRequestBottomSheet.nurseVerifyArrivalBottomSheet(context: context); } + _requestProvider.needVisitHelperModel = NeedVisitHelperModel( + workOrderId: _requestProvider.currentWorkOrder?.data?.requestId, + visitDate: _requestProvider.currentWorkOrder?.data?.needAVisitDateTime, + comment: _requestProvider.currentWorkOrder?.data?.needAVisitComment, + ); } @override @@ -62,10 +68,6 @@ class _ServiceRequestDetailMainState extends State { bool isNurse = (Provider.of(context, listen: false).user?.type) == UsersTypes.normal_user; return WillPopScope( onWillPop: () async { - ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - if (requestDetailProvider.timer != null && requestDetailProvider.timer!.isActive) { - requestDetailProvider.stopTimer(); - } stopTimer(); return true; }, @@ -91,7 +93,7 @@ class _ServiceRequestDetailMainState extends State { : IconButton( icon: const Icon(Icons.home), onPressed: () { - stopTimer(); + // stopTimer(); Navigator.pop(context); }, ), @@ -126,10 +128,10 @@ class _ServiceRequestDetailMainState extends State { ), ), 12.height, - TabBarView( + const TabBarView( children: [ ServiceRequestDetailView(), - const HistoryLogView(), + HistoryLogView(), ], ).expanded, ],