diff --git a/lib/controllers/notification/notification_manger.dart b/lib/controllers/notification/notification_manger.dart index ca4e92d6..b101bd3f 100644 --- a/lib/controllers/notification/notification_manger.dart +++ b/lib/controllers/notification/notification_manger.dart @@ -87,7 +87,7 @@ class NotificationManger { } static Future scheduleNotification( - {int id = 0, + {int?id, String? title, String? body, String? payLoad, @@ -95,7 +95,7 @@ class NotificationManger { print('time i got is ${scheduledNotificationDateTime}'); return localNotificationsPlugin.zonedSchedule( - id, + id??0, title, body, // tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)), @@ -108,4 +108,8 @@ class NotificationManger { uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime); } + static Future cancelNotificationById(int notificationId) async { + await localNotificationsPlugin.cancel(notificationId); + print("Notification with ID $notificationId has been canceled."); + } } diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index 03d5527c..f44a0071 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -193,7 +193,7 @@ class DashBoardProvider extends ChangeNotifier { Response response; String url = ''; if (usersType == UsersTypes.engineer) { - // Todo need to check pagination for not assigned task @waseem. + //need to check pagination for not assigned task @waseem. print('status i got is $status'); print('id i got is $tabId'); diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index ada3ad45..4c52daba 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'dart:io'; import 'dart:async'; import 'package:device_calendar/device_calendar.dart'; @@ -12,6 +13,7 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/notification/notification_manger.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; @@ -103,63 +105,269 @@ class ServiceRequestUtils { }, ); } else { - print('Failed to get the QR code'); + log('Failed to get the QR code'); } } - static void scheduleNotification({required BuildContext context, required DateTime scheduleDateTime}) { + static void scheduleOrUpdateNotification({required BuildContext context, required DateTime scheduleDateTime, required String workOrderId}) async{ DateTime scheduleTime = scheduleDateTime; - NotificationManger.scheduleNotification(title: 'Scheduled Notification', body: '$scheduleTime', scheduledNotificationDateTime: scheduleTime); + await NotificationManger.cancelNotificationById(workOrderId.hashCode); + NotificationManger.scheduleNotification(id: workOrderId.hashCode,title: 'Scheduled Notification', body: '$scheduleTime', scheduledNotificationDateTime: scheduleTime); } //steps: //add permission for andriod.. //add string in info.plist for ios... + //tz.TZDateTime.from(movieScreening.dateTime, tz.local) some time you need to add this while making build.. //create event.. - static void addEventToCalendar({required BuildContext context, required DateTime start, required DateTime end,required String title,required int ? requestId}) async { + static void addOrUpdateEventToCalendar({ + required BuildContext context, + required DateTime start, + required DateTime end, + required String title, + String? workOrderNumber, + }) async { + final deviceCalendarPlugin = DeviceCalendarPlugin(); + final currentLocation = getLocation(await FlutterTimezone.getLocalTimezone()); + TZDateTime startDate = TZDateTime.from(start, currentLocation); + TZDateTime endDate = TZDateTime.from(end, currentLocation); + setLocalLocation(currentLocation); + final calendarsResult = await deviceCalendarPlugin.retrieveCalendars(); + if (calendarsResult.data?.isEmpty ?? true) { + 'No calendars available on the device.'.showToast; + return; + } + + // Select a write able calendar + final writableCalendar = calendarsResult.data?.firstWhere( + (calendar) => calendar.isReadOnly == false, + orElse: () => Calendar(id: '', name: 'Default', isReadOnly: true), + ); + + if (writableCalendar == null || writableCalendar.isReadOnly==true) { + log('No writable calendar found.'); + 'No writable calendar found.'.showToast; + return; // Handle the case where no writable calendar exists + } + + + final eventsResult = await deviceCalendarPlugin.retrieveEvents( + writableCalendar.id!, + RetrieveEventsParams(startDate: start.subtract(Duration(days: 7)), endDate: end.add(Duration(days: 30))), + ); + if (!(eventsResult.isSuccess && eventsResult.data != null)) { + "Failed to retrieve reminders.".showToast; + return; + } + + // Find an event with the matching workOrderNumber in the description + final matchingEvent = eventsResult.data!.firstWhere( + (event) => event.description?.contains('$workOrderNumber') ?? false, + orElse: () => Event('0',eventId: null), + ); - var currentLocation = getLocation(await FlutterTimezone.getLocalTimezone()); - final calendarsResult = await DeviceCalendarPlugin().retrieveCalendars(); + if (matchingEvent.eventId != null) { + // Update the existing event + matchingEvent.title = title; + matchingEvent.start = startDate; + matchingEvent.end = endDate; - if (calendarsResult.data?.isNotEmpty ?? false) { - setLocalLocation(currentLocation); - await Future.delayed(const Duration(seconds: 2)); - TZDateTime startDate = TZDateTime.from(start, currentLocation); - TZDateTime endDate = TZDateTime.from(end, currentLocation); - final calendarId = calendarsResult.data!.first.id; // Use the first calendar + // Save the updated event + final updateResult = await deviceCalendarPlugin.createOrUpdateEvent(matchingEvent); - var eventToCreate = Event( - calendarId, - eventId: requestId.toString(), + if (updateResult?.isSuccess == true) { + log('Reminder updated successfully: ${updateResult?.data}'); + "Reminder updated successfully on device calendar".showToast; + } else { + log('Failed to update reminder: ${updateResult?.errors}'); + "Failed to update reminder on device calendar".showToast; + } + } else { + // add event to calendar.. + final eventToCreate = Event( + writableCalendar.id, title: title, - description: "You have a reminder for a visit", + description: 'You have a reminder for a visit for work order $workOrderNumber', start: startDate, end: endDate, ); - final response = await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); - print("Response of adding calendar is ${response?.data}"); - } else { - // "No calendars available on the device.".showToast(); + final createResult = await deviceCalendarPlugin.createOrUpdateEvent(eventToCreate); + + if (createResult?.isSuccess == true) { + log('Reminder added successfully: ${createResult?.data}'); + //TODO need to confirm to show the message to user... + 'Reminder added to device calendar'.showToast; + } else { + log('Failed to add reminder: ${createResult?.errors}'); + 'Failed to add reminder to device calendar'.showToast; + } } + } + + + // static void addEventToCalendar({ + // required BuildContext context, + // required DateTime start, + // required DateTime end, + // required String title, + // String? workOrderNumber, + // }) async { + // final deviceCalendarPlugin = DeviceCalendarPlugin(); + // + // // Retrieve current timezone + // final currentLocation = getLocation(await FlutterTimezone.getLocalTimezone()); // setLocalLocation(currentLocation); - // await Future.delayed(const Duration(seconds: 2)); + // + // // Retrieve calendars + // final calendarsResult = await deviceCalendarPlugin.retrieveCalendars(); + // + // if (calendarsResult.data?.isEmpty ?? true) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('No calendars available on the device.')), + // ); + // return; + // } + // + // // Select a writable calendar + // final writableCalendar = calendarsResult.data?.firstWhere( + // (calendar) => calendar.isReadOnly == false, + // orElse: () => Calendar(id: '', name: 'Default', isReadOnly: true), + // ); + // + // if (writableCalendar == null || writableCalendar.isReadOnly==true) { + // log('No writable calendar found.'); + // return; // Handle the case where no writable calendar exists + // } + // // Convert start and end times // TZDateTime startDate = TZDateTime.from(start, currentLocation); // TZDateTime endDate = TZDateTime.from(end, currentLocation); - // var eventToCreate = Event( - // '0', - // // eventId:requestId.toString(), + // + // // Create event + // final eventToCreate = Event( + // writableCalendar.id, // title: title, - // description: "You have reminder for Visit", + // description: 'You have a reminder for a visit for work order $workOrderNumber ', // start: startDate, // end: endDate, // ); - // print('event to add i got is ${eventToCreate.toJson()}'); - // final response = await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); - // print("response of adding calander is ${response?.data}"); // - } + // // Create or update the event + // final response = await deviceCalendarPlugin.createOrUpdateEvent(eventToCreate); + // + // if (response?.isSuccess == true) { + // log('Event added successfully: ${response?.data}'); + // } else { + // log('Failed to add event: ${response?.errors}'); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Failed to add event to calendar.')), + // ); + // } + // } + + // static Future updateEventOnCalendar({ + // required BuildContext context, + // required String calendarId, + // required int requestId, + // required String updatedTitle, + // required DateTime updatedStart, + // required DateTime updatedEnd, + // }) async { + // final deviceCalendarPlugin = DeviceCalendarPlugin(); + // + // // Retrieve all events in the calendar + // final eventsResult = await deviceCalendarPlugin.retrieveEvents( + // calendarId, + // RetrieveEventsParams(), + // ); + // + // if (!(eventsResult.isSuccess && eventsResult.data != null)) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Failed to retrieve events.')), + // ); + // return; + // } + // + // // Find the event with the matching requestId + // final matchingEvent = eventsResult.data!.firstWhere( + // (event) => event.eventId == requestId.toString(), + // orElse: () => null, + // ); + // + // if (matchingEvent == null) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Event not found for requestId: $requestId')), + // ); + // return; + // } + // + // // Update the event's details + // matchingEvent.title = updatedTitle; + // matchingEvent.start = updatedStart; + // matchingEvent.end = updatedEnd; + // + // // Save the updated event + // final updateResult = await deviceCalendarPlugin.createOrUpdateEvent(matchingEvent); + // + // if (updateResult?.isSuccess == true) { + // log('Event updated successfully: ${updateResult?.data}'); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Event updated successfully.')), + // ); + // } else { + // log('Failed to update event: ${updateResult?.errors}'); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text('Failed to update event.')), + // ); + // } + // } + + + // static void addEventToCalendar({required BuildContext context, required DateTime start, required DateTime end,required String title,required int ? requestId}) async { + // + // + // var currentLocation = getLocation(await FlutterTimezone.getLocalTimezone()); + // final calendarsResult = await DeviceCalendarPlugin().retrieveCalendars(); + // + // if (calendarsResult.data?.isNotEmpty ?? false) { + // setLocalLocation(currentLocation); + // await Future.delayed(const Duration(seconds: 2)); + // TZDateTime startDate = TZDateTime.from(start, currentLocation); + // TZDateTime endDate = TZDateTime.from(end, currentLocation); + // final calendarId = calendarsResult.data!.first.id; // Use the first calendar + // + // var eventToCreate = Event( + // calendarId, + // eventId: requestId.toString(), + // title: title, + // description: "You have a reminder for a visit", + // start: startDate, + // end: endDate, + // ); + // final response = await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); + // log("Response of adding calendar is ${response?.data}"); + // } else { + // // "No calendars available on the device.".showToast(); + // + // } + // // setLocalLocation(currentLocation); + // // await Future.delayed(const Duration(seconds: 2)); + // // TZDateTime startDate = TZDateTime.from(start, currentLocation); + // // TZDateTime endDate = TZDateTime.from(end, currentLocation); + // // var eventToCreate = Event( + // // '0', + // // // eventId:requestId.toString(), + // // title: title, + // // description: "You have reminder for Visit", + // // start: startDate, + // // end: endDate, + // // ); + // // log('event to add i got is ${eventToCreate.toJson()}'); + // // final response = await DeviceCalendarPlugin().createOrUpdateEvent(eventToCreate); + // // log("response of adding calander is ${response?.data}"); + // // + // } // Map messageData = message.data; // if (messageData["notificationType"] != null && messageData["accept"] != null) { @@ -174,7 +382,7 @@ class ServiceRequestUtils { // } static Future listenForApproval() async { - print('listen for approval called..'); + log('listen for approval called..'); bool isVerified = false; Completer completer = Completer(); @@ -192,13 +400,13 @@ class ServiceRequestUtils { } } }, onError: (Object error) { - print("onMessageReceivedStream:${error.toString()}"); + log("onMessageReceivedStream:${error.toString()}"); completer.complete(false); // Handle any error }); } else { // Using Firebase FirebaseMessaging.onMessage.listen((RemoteMessage message) { - print('message data received: ${message.data}'); + log('message data received: ${message.data}'); ConfirmArrivalNotificationModel notificationModel = ConfirmArrivalNotificationModel.fromJson(message.data); if (notificationModel.requestId != null && notificationModel.accept != null) { if (notificationModel.accept == 'True') { 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 04083f0f..f9881ab3 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 @@ -298,6 +298,25 @@ class ServiceRequestBottomSheet { if (requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.eArrived) { requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; requestDetailProvider.engineerUpdateNeedVisit(); + try { + DateTime visitDateTime = requestDetailProvider.needVisitHelperModel!.visitDate!; + int ?reminderMinutes = requestDetailProvider.currentWorkOrder!.data!.setReminder?.value; + DateTime updatedDateTime = visitDateTime.subtract(Duration(minutes: reminderMinutes ?? 0)); + if (updatedDateTime.isAfter(DateTime.now())) { + // ServiceRequestUtils.scheduleNotification(context: context, scheduleDateTime: updatedDateTime); + ServiceRequestUtils.addOrUpdateEventToCalendar( + context: context, + start: updatedDateTime, + end: visitDateTime, + title: context.translation.needAVisit, + workOrderNumber: requestDetailProvider.currentWorkOrder!.data!.workOrderNo!); + } + else{ + // "Visit date is before the reminder time selected".showToast; + } + } catch (e) { + log('error $e'); + } Navigator.pop(context); } else { requestDetailProvider.needVisitHelperModel?.workOrderId = requestDetailProvider.currentWorkOrder!.data!.requestId; @@ -419,13 +438,18 @@ class ServiceRequestBottomSheet { 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( + ServiceRequestUtils.addOrUpdateEventToCalendar( context: context, start: updatedDateTime, end: visitDateTime, title: context.translation.needAVisit, - requestId: requestDetailProvider.currentWorkOrder!.data!.requestId!); + workOrderNumber: requestDetailProvider.currentWorkOrder!.data!.workOrderNo!); + // uncommit this to add schedule notification need to confirm what to do in case of update.... + // ServiceRequestUtils.scheduleOrUpdateNotification(context: context, scheduleDateTime: updatedDateTime,workOrderId: requestDetailProvider.currentWorkOrder!.data!.workOrderNo!); + + } + else{ + "Visit date is before the reminder time selected".showToast; } } catch (e) { log('error $e');