From e0e41d19007d8677949b3c09851424a1518ac504 Mon Sep 17 00:00:00 2001 From: tahaalam Date: Thu, 27 Nov 2025 16:13:30 +0300 Subject: [PATCH] calender reminder added on appointment and pescription --- lib/core/utils/calender_utils_new.dart | 130 +++++++++++++++--- .../prescriptions_view_model.dart | 15 ++ .../appointment_details_page.dart | 8 +- .../prescriptions/prescription_item_view.dart | 36 +++-- 4 files changed, 157 insertions(+), 32 deletions(-) diff --git a/lib/core/utils/calender_utils_new.dart b/lib/core/utils/calender_utils_new.dart index b4c4bd71..28084a91 100644 --- a/lib/core/utils/calender_utils_new.dart +++ b/lib/core/utils/calender_utils_new.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:device_calendar_plus/device_calendar_plus.dart'; +import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:jiffy/jiffy.dart' show Jiffy; class CalenderUtilsNew { @@ -25,34 +26,86 @@ class CalenderUtilsNew { } FutureOr createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId, int? reminderMinutes}) async { - print("the reminder minutes are $reminderMinutes"); if (writableCalender.isEmpty) { await getCalenders(); } var writableCalendars = writableCalender.first; - - print("writableCalendars-name: " + writableCalendars.name); - print("writableCalendars-Id: " + writableCalendars.id); - print("writableCalendarsToString: " + writableCalendars.toString()); - print("writableCalendarsToString: " + writableCalendars!.id!); - + String eventResult = ""; CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions(); if(result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions(); print(result); - String eventResult = await DeviceCalendar.instance.createEvent( - calendarId: writableCalendars!.id, - title: title, - description: description, - startDate: scheduleDateTime!, - endDate: scheduleDateTime!.add(Duration(minutes: 30)), - reminderMinutes: reminderMinutes - ); - - print("the event Result is ${eventResult}"); - return eventResult.isNotEmpty; + + // String eventId = await getEventIdIfEventExist(title!.split("#").last); + // if (eventId.isEmpty) { + eventResult = await DeviceCalendar.instance.createEvent( + calendarId: writableCalendars!.id, + title: title, + description: description, + startDate: scheduleDateTime!, + endDate: scheduleDateTime!.add(Duration(minutes: 30)), + reminderMinutes: reminderMinutes); + return eventResult.isNotEmpty; + // } + + // await DeviceCalendar.instance.updateEvent( + // eventId: eventId, + // title: title, + // description: description, + // startDate: scheduleDateTime!, + // endDate: scheduleDateTime!.add(Duration(minutes: 30)), + // ); + + // return eventId.isNotEmpty; } + FutureOr createMultipleEvents( + {required int reminderMinutes, + int? frequencyNumber, + required int days, + required String orderDate, + required String itemDescriptionN, + required String route, + Function(String)? onFailure, + String? prescriptionNumber}) async { + DateTime currentDay = DateTime.now(); + DateTime actualDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0); + print("the frequency is $frequencyNumber"); + frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2 + int interval = calculateIntervalAsPerFrequency(frequencyNumber); + // int remainingDays = days - (Jiffy.parseFromDateTime(DateTime.now()).diff(Jiffy.parseFromDateTime(DateUtil.convertStringToDate(orderDate)), unit: Unit.day) as int); + Duration difference = (actualDate.difference(DateUtil.convertStringToDate(orderDate))); + int remainingDays = 5; + // if (remainingDays.isNegative) { + // onFailure?.call("Prescription date has been already passed you can not add a reminder for this prescription."); + // return false; + // } + + bool statusOfOperation = false; + + for (int i = 0; i < remainingDays; i++) { + //event for number of days. + for (int j = 0; j < frequencyNumber; j++) { + statusOfOperation = await createOrUpdateEvent( + title: "$itemDescriptionN} Medication about to due for prescription , #$prescriptionNumber", + description: "$itemDescriptionN $frequencyNumber $route ", + scheduleDateTime: actualDate, + location: '', //event id with varitions + reminderMinutes: reminderMinutes + ); + if (!statusOfOperation) return false; + + actualDate = actualDate.add(Duration(hours: interval)); + // if (actualDate.difference(currentDay).inDays == 1) break; + } + // actualDate = actualDate.add(Duration(days: 1)); + } + return statusOfOperation; + } + + int calculateIntervalAsPerFrequency(int frequencyNumber) { + return 24 ~/ frequencyNumber; + } FutureOr> getEvents() async { var availableCalender = writableCalender.first; @@ -64,24 +117,41 @@ class CalenderUtilsNew { FutureOr checkIfEventExist(String admissionId) async { - if(writableCalender.isEmpty)return false; + if (writableCalender.isEmpty) { + await getCalenders(); + } List events = await getEvents(); if(events.isEmpty) return false; for(var event in events){ List title = event.title!.split("#"); - print("the splitted admission id is ${title}"); + if(title.contains(admissionId)) return true; } return false; } + FutureOr getEventIdIfEventExist(String admissionId) async { + if (writableCalender.isEmpty) { + await getCalenders(); + } + List events = await getEvents(); + if (events.isEmpty) return ""; + for (var event in events) { + List title = event.title!.split("#"); + if (title.contains(admissionId)) return event.eventId; + } + return ""; + } + FutureOr checkAndRemove({required String id}) async { - if(writableCalender.isEmpty)return false; + if (writableCalender.isEmpty) { + await getCalenders(); + } List events = await getEvents(); if(events.isEmpty) return false; for(var event in events){ List title = event.title!.split("#"); - print("the splitted admission id is ${title}"); + if(title.contains(id)) { calender.deleteEvent(eventId: event.eventId); return true; @@ -90,5 +160,21 @@ class CalenderUtilsNew { return false; } + FutureOr checkAndRemoveMultipleItems({required String id}) async { + if (writableCalender.isEmpty) { + await getCalenders(); + } + List events = await getEvents(); + if(events.isEmpty) return false; + bool statusOfOperation = false; + for(var event in events){ + List title = event.title.split("#"); + if(title.contains(id)) { + calender.deleteEvent(eventId: event.eventId); + statusOfOperation = true; + } + } + return statusOfOperation; + } } diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart index aac25c14..0e6bce78 100644 --- a/lib/features/prescriptions/prescriptions_view_model.dart +++ b/lib/features/prescriptions/prescriptions_view_model.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart'; import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/patient_prescriptions_response_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_detail_response_model.dart'; import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; class PrescriptionsViewModel extends ChangeNotifier { @@ -40,6 +43,11 @@ class PrescriptionsViewModel extends ChangeNotifier { notifyListeners(); } + + checkIfReminderExistForPrescription(int index) async { + prescriptionDetailsList[index].hasReminder = await CalenderUtilsNew.instance.checkIfEventExist(prescriptionDetailsList[index].itemID?.toString() ?? ""); + } + setPrescriptionsDetailsLoading() { isPrescriptionsDetailsLoading = true; prescriptionDetailsList.clear(); @@ -121,6 +129,9 @@ class PrescriptionsViewModel extends ChangeNotifier { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { prescriptionDetailsList = apiResponse.data!; + prescriptionDetailsList.forEach((element) async { + await checkIfReminderExistForPrescription(prescriptionDetailsList.indexOf(element)); + }); isPrescriptionsDetailsLoading = false; notifyListeners(); if (onSuccess != null) { @@ -173,4 +184,8 @@ class PrescriptionsViewModel extends ChangeNotifier { }, ); } + + showError(String errorMessage) { + getIt().showErrorBottomSheet(message: errorMessage); + } } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index ba110a2e..58958ee3 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -73,7 +73,9 @@ class _AppointmentDetailsPageState extends State { var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}"); print("the appointment reminder exist $doesExist"); myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel); + setState((){ + }); }); super.initState(); @@ -142,6 +144,10 @@ class _AppointmentDetailsPageState extends State { }, onCancelTap: () async { myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); + var isEventAddedOrRemoved = await CalenderUtilsNew.instance.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", ); + setState(() { + myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel); + }); LoaderBottomSheet.showLoader(loadingText: "Cancelling Appointment, Please Wait...".needTranslation); await myAppointmentsViewModel.cancelAppointment( patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, @@ -323,7 +329,7 @@ class _AppointmentDetailsPageState extends State { }else { isEventAddedOrRemoved = await calender.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", ); setState(() { - myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel); + myAppointmentsViewModel.setAppointmentReminder(!isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel); }); } diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart index acf03f58..39a0b05b 100644 --- a/lib/presentation/prescriptions/prescription_item_view.dart +++ b/lib/presentation/prescriptions/prescription_item_view.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/utils/calendar_utils.dart'; +import 'package:hmg_patient_app_new/core/utils/calender_utils_new.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; @@ -10,6 +11,7 @@ import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_mo import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; class PrescriptionItemView extends StatelessWidget { int index; @@ -154,9 +156,14 @@ class PrescriptionItemView extends StatelessWidget { activeTrackColor: AppColors.successColor.withValues(alpha: .15), value: isLoading ? false : prescriptionVM.prescriptionDetailsList[index].hasReminder!, onChanged: (newValue) async { + CalenderUtilsNew calender = CalenderUtilsNew.instance; + if (prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false) { - await checkAndRemove(prescriptionVM.prescriptionDetailsList[index].hasReminder, delete: true); - prescriptionVM.notify(); + LoaderBottomSheet.showLoader(loadingText: "Removing Reminders"); + bool resultValue = await calender.checkAndRemoveMultipleItems(id:prescriptionVM.prescriptionDetailsList[index].itemID.toString()); + + prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]); + LoaderBottomSheet.hideLoader(); return; } @@ -173,18 +180,29 @@ class PrescriptionItemView extends StatelessWidget { description: "${prescriptionVM.prescriptionDetailsList[index].itemDescription} ${prescriptionVM.prescriptionDetailsList[index].frequency} ${prescriptionVM.prescriptionDetailsList[index].route} ", onSuccess: () { - prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]); + }, isMultiAllowed: true, - onMultiDateSuccess: (int selectedIndex) { - setCalender(context, - eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(), - selectedMinutes: selectedIndex, + onMultiDateSuccess: (int selectedIndex) async{ + bool isEventAdded = await calender.createMultipleEvents( + reminderMinutes: selectedIndex, frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(), - days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(), + days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(), orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!, itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!, - route: prescriptionVM.prescriptionDetailsList[index].route!); + route: prescriptionVM.prescriptionDetailsList[index].route!, + onFailure: (errorMessage)=> prescriptionVM.showError(errorMessage), + prescriptionNumber: prescriptionVM.prescriptionDetailsList[index].itemID.toString(), + ); + prescriptionVM.setPrescriptionItemReminder(isEventAdded, prescriptionVM.prescriptionDetailsList[index]); + // setCalender(context, + // eventId: prescriptionVM.prescriptionDetailsList[index].itemID.toString(), + // selectedMinutes: selectedIndex, + // frequencyNumber: prescriptionVM.prescriptionDetailsList[index].frequencyNumber?.toInt(), + // days: prescriptionVM.prescriptionDetailsList[index].days!.toInt(), + // orderDate: prescriptionVM.prescriptionDetailsList[index].orderDate!, + // itemDescriptionN: prescriptionVM.prescriptionDetailsList[index].itemDescription!, + // route: prescriptionVM.prescriptionDetailsList[index].route!); }, ); },