From fc0f98da1de46b98602c6faa202cf54620e40885 Mon Sep 17 00:00:00 2001 From: tahaalam Date: Wed, 26 Nov 2025 14:24:56 +0300 Subject: [PATCH 1/3] calender reminder added --- .../reports/problems/problems-report.html | 2 +- lib/core/utils/calender_utils_new.dart | 94 +++++++++++++++++++ lib/core/utils/date_util.dart | 3 +- .../appointment_details_page.dart | 70 ++++++++++++-- .../prescription_reminder_view.dart | 2 +- pubspec.yaml | 1 + 6 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 lib/core/utils/calender_utils_new.dart diff --git a/android/build/reports/problems/problems-report.html b/android/build/reports/problems/problems-report.html index 82570ba..866b270 100644 --- a/android/build/reports/problems/problems-report.html +++ b/android/build/reports/problems/problems-report.html @@ -650,7 +650,7 @@ code + .copy-button { diff --git a/lib/core/utils/calender_utils_new.dart b/lib/core/utils/calender_utils_new.dart new file mode 100644 index 0000000..b4c4bd7 --- /dev/null +++ b/lib/core/utils/calender_utils_new.dart @@ -0,0 +1,94 @@ +import 'dart:async'; + +import 'package:device_calendar_plus/device_calendar_plus.dart'; +import 'package:jiffy/jiffy.dart' show Jiffy; + +class CalenderUtilsNew { + final DeviceCalendar calender = DeviceCalendar.instance; + List writableCalender = []; + + CalenderUtilsNew._instance() { + getCalenders(); + } + + static final CalenderUtilsNew instance = CalenderUtilsNew._instance(); + + Future getCalenders() async { + CalendarPermissionStatus result = await DeviceCalendar.instance.hasPermissions(); + if(result != CalendarPermissionStatus.granted) await DeviceCalendar.instance.requestPermissions(); + var calenders = await calender.listCalendars(); + calenders.forEach((calender) { + if (!calender.readOnly) { + writableCalender.add(calender); + } + }); + } + + 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!); + + 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; + } + + + + FutureOr> getEvents() async { + var availableCalender = writableCalender.first; + DateTime startEventsDate = Jiffy.parseFromDateTime(DateTime.now()).subtract(days: 30).dateTime; + DateTime endEventsDate = Jiffy.parseFromDateTime(DateTime.now()).add(days: 120).dateTime; + return await calender.listEvents(startEventsDate, endEventsDate, calendarIds: [availableCalender.id]); + + } + + + FutureOr checkIfEventExist(String admissionId) async { + if(writableCalender.isEmpty)return false; + 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 checkAndRemove({required String id}) async { + if(writableCalender.isEmpty)return false; + 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; + } + } + return false; + } + + +} diff --git a/lib/core/utils/date_util.dart b/lib/core/utils/date_util.dart index a918706..ee2b4ec 100644 --- a/lib/core/utils/date_util.dart +++ b/lib/core/utils/date_util.dart @@ -17,8 +17,7 @@ class DateUtil { final endIndex = date.indexOf(end, startIndex + start.length); return DateTime.fromMillisecondsSinceEpoch(int.parse( date.substring(startIndex + start.length, endIndex), - )) - ; + )); } static DateTime convertStringToDateSaudiTimezone(String date, int projectId) { diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index e620783..ba110a2 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -1,10 +1,16 @@ import 'dart:async'; +import 'dart:collection'; +import 'dart:io'; +import 'package:device_calendar/device_calendar.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.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/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; @@ -62,11 +68,13 @@ class _AppointmentDetailsPageState extends State { @override void initState() { - scheduleMicrotask(() { - // if (AppointmentType.isArrived(widget.patientAppointmentHistoryResponseModel)) { - // prescriptionsViewModel.setPrescriptionsDetailsLoading(); - // prescriptionsViewModel.getPrescriptionDetails(getPrescriptionRequestModel()); - // } + scheduleMicrotask(() async { + CalenderUtilsNew calendarUtils = await CalenderUtilsNew.instance; + var doesExist = await calendarUtils.checkIfEventExist("${widget.patientAppointmentHistoryResponseModel.appointmentNo}"); + print("the appointment reminder exist $doesExist"); + myAppointmentsViewModel.setAppointmentReminder(doesExist, widget.patientAppointmentHistoryResponseModel); + + }); super.initState(); } @@ -272,10 +280,54 @@ class _AppointmentDetailsPageState extends State { // activeThumbColor: AppColors.successColor, activeTrackColor: AppColors.successColor.withValues(alpha: .15), value: widget.patientAppointmentHistoryResponseModel.hasReminder!, - onChanged: (newValue) { - setState(() { - myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel); - }); + onChanged: (newValue) async { + CalenderUtilsNew calender = CalenderUtilsNew.instance; + bool isEventAddedOrRemoved = false; + if(newValue == true){ + DateTime startDate = DateTime.now(); + DateTime endDate = DateUtil.convertStringToDate(widget + .patientAppointmentHistoryResponseModel.appointmentDate); + showReminderBottomSheet( + context, + endDate, + widget.patientAppointmentHistoryResponseModel.doctorNameObj??"", + "${widget.patientAppointmentHistoryResponseModel.appointmentNo}"??"", + "", + "", + title: "Appointment with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj}".needTranslation, + description:"${widget.patientAppointmentHistoryResponseModel.doctorNameObj} will be having an appointment on ${widget.patientAppointmentHistoryResponseModel.appointmentDate}".needTranslation, + onSuccess: () { + setState(() { + myAppointmentsViewModel.setAppointmentReminder(newValue, widget.patientAppointmentHistoryResponseModel); + }); + }, + isMultiAllowed: true, + onMultiDateSuccess: (int selectedIndex) async { + + isEventAddedOrRemoved = await calender.createOrUpdateEvent( + title: "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} on ${DateUtil.convertStringToDate(widget + .patientAppointmentHistoryResponseModel.appointmentDate)}, Appointment #${widget.patientAppointmentHistoryResponseModel.appointmentNo}".needTranslation, + description: "Appointment Reminder with ${widget.patientAppointmentHistoryResponseModel.doctorNameObj} in ${widget + .patientAppointmentHistoryResponseModel.projectName}", + scheduleDateTime: DateUtil.convertStringToDate(widget + .patientAppointmentHistoryResponseModel.appointmentDate), + eventId: "${widget.patientAppointmentHistoryResponseModel.appointmentNo}", + location: '', + reminderMinutes: selectedIndex + ); + setState(() { + myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel); + }); + }, + ); + }else { + isEventAddedOrRemoved = await calender.checkAndRemove( id:"${widget.patientAppointmentHistoryResponseModel.appointmentNo}", ); + setState(() { + myAppointmentsViewModel.setAppointmentReminder(isEventAddedOrRemoved, widget.patientAppointmentHistoryResponseModel); + }); + } + + }, ), ], diff --git a/lib/presentation/prescriptions/prescription_reminder_view.dart b/lib/presentation/prescriptions/prescription_reminder_view.dart index 8b7df0b..2f1154f 100644 --- a/lib/presentation/prescriptions/prescription_reminder_view.dart +++ b/lib/presentation/prescriptions/prescription_reminder_view.dart @@ -100,7 +100,7 @@ class _PrescriptionReminderViewState extends State { text: LocaleKeys.setReminder.tr(), onPressed: () { Navigator.of(context).pop(); - widget.setReminder(_selectedOption); + widget.setReminder(_options[_selectedOption]); }, backgroundColor: AppColors.bgGreenColor, borderColor: AppColors.bgGreenColor, diff --git a/pubspec.yaml b/pubspec.yaml index 3d6604c..23e3ea9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,6 +45,7 @@ dependencies: file_picker: ^10.3.2 local_auth: ^2.3.0 share_plus: ^11.1.0 + device_calendar_plus: ^0.3.1 device_calendar: git: https://github.com/bardram/device_calendar manage_calendar_events: ^2.0.3 From e0e41d19007d8677949b3c09851424a1518ac504 Mon Sep 17 00:00:00 2001 From: tahaalam Date: Thu, 27 Nov 2025 16:13:30 +0300 Subject: [PATCH 2/3] 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 b4c4bd7..28084a9 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 aac25c1..0e6bce7 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 ba110a2..58958ee 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 acf03f5..39a0b05 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!); }, ); }, From e200479332a321fc0a840c34dc8e57b2962f5518 Mon Sep 17 00:00:00 2001 From: tahaalam Date: Sun, 30 Nov 2025 10:27:42 +0300 Subject: [PATCH 3/3] old calender util deleted --- lib/core/utils/calendar_utils.dart | 316 ------------------ .../appointment_details_page.dart | 3 +- .../prescription_detail_page.dart | 2 - .../prescriptions/prescription_item_view.dart | 4 +- lib/widgets/common_bottom_sheet.dart | 54 +++ 5 files changed, 57 insertions(+), 322 deletions(-) delete mode 100644 lib/core/utils/calendar_utils.dart diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart deleted file mode 100644 index 2068db9..0000000 --- a/lib/core/utils/calendar_utils.dart +++ /dev/null @@ -1,316 +0,0 @@ -import 'dart:async'; -import 'dart:collection'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:ui'; - -import 'package:device_calendar/device_calendar.dart'; -import 'package:flutter/widgets.dart'; -import 'package:hmg_patient_app_new/core/dependencies.dart'; -import 'package:hmg_patient_app_new/core/utils/date_util.dart'; -import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; -import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart'; -import 'package:hmg_patient_app_new/services/dialog_service.dart'; -import 'package:hmg_patient_app_new/services/permission_service.dart'; -import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; -import 'package:jiffy/jiffy.dart'; -import 'package:manage_calendar_events/manage_calendar_events.dart' as ios; -import 'package:permission_handler/permission_handler.dart'; -import 'package:timezone/data/latest.dart' as tzl; - -final DeviceCalendarPlugin deviceCalendarPlugin = DeviceCalendarPlugin(); -final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin(); - -class CalendarUtils { - static Completer? _completer; - - dynamic get writableCalendars => calendars.firstWhere((c) => !c.isReadOnly!); - dynamic calendars; - - CalendarUtils._(this.calendars); - - // static Future getInstance() async { - // if (_completer == null) { - // _completer = Completer(); - // print(_completer!.isCompleted); - // try { - // final dynamic calendarsResult; - // if (Platform.isIOS) { - // calendarsResult = await _myPlugin.getCalendars(); - // if (!_completer!.isCompleted) { - // _completer?.complete(CalendarUtils._(await calendarsResult!)); - // } - // } else { - // calendarsResult = await deviceCalendarPlugin.retrieveCalendars(); - // if (!_completer!.isCompleted) { - // _completer?.complete(CalendarUtils._(await calendarsResult.data!)); - // } - // } - // } on Exception catch (e) { - // if (!_completer!.isCompleted) { - // _completer!.completeError(e); - // } - // } - // } - // return _completer!.future; - // } - - static Future getInstance() async { - tzl.initializeTimeZones(); - if (_completer != null) { - return _completer!.future; - } - _completer = Completer(); - try { - final dynamic calendarsResult; - if (Platform.isIOS) { - calendarsResult = await _myPlugin.getCalendars(); - _completer!.complete(CalendarUtils._(calendarsResult)); - } else { - calendarsResult = await deviceCalendarPlugin.retrieveCalendars(); - _completer!.complete(CalendarUtils._(calendarsResult.data)); - } - } catch (e) { - _completer!.completeError(e); - } - - return _completer!.future; - } - - Future createOrUpdateEvents({List? scheduleList, String? title, String? description, List? scheduleDateTime, List? daysOfWeek}) async { - tzl.initializeTimeZones(); - List events = []; - Location _currentLocation; - if (DateTime.now().timeZoneName == "+04") - _currentLocation = getLocation('Asia/Dubai'); - else - _currentLocation = getLocation('Asia/Riyadh'); - - scheduleDateTime!.forEach((element) { - RecurrenceRule recurrenceRule = RecurrenceRule( - // RecurrenceFrequency.Daily, - // daysOfWeek: daysOfWeek, - // endDate: element, - until: element, frequency: Frequency.daily, - ); - //added byAamir Tz Time - Event event = Event(writableCalendars!.id, - recurrenceRule: recurrenceRule, - start: TZDateTime.from(element, _currentLocation), - end: TZDateTime.from(element.add(Duration(minutes: 30)), _currentLocation), - title: title, - description: description); - events.add(event); - }); - - events.forEach((element) { - deviceCalendarPlugin.createOrUpdateEvent(element); - }); - } - - Future createOrUpdateEvent({required String title, required String description, required String location, DateTime? scheduleDateTime, String? eventId}) async { - RecurrenceRule recurrenceRule = RecurrenceRule( - // RecurrenceFrequency.Daily, - // daysOfWeek: daysOfWeek, - // endDate: scheduleDateTime, - until: scheduleDateTime, frequency: Frequency.daily, - ); - - Location _currentLocation; - // if (DateTime.now().timeZoneName == "+04") - // _currentLocation = getLocation('Asia/Dubai'); - // else - _currentLocation = getLocation('Asia/Riyadh'); - - TZDateTime scheduleDateTimeUTZ = TZDateTime.from(scheduleDateTime!, _currentLocation); - - print("writableCalendars-name: " + writableCalendars.name); - print("writableCalendars-Id: " + writableCalendars.id); - print("writableCalendarsToString: " + writableCalendars.toString()); - print("writableCalendarsToString: " + writableCalendars!.id!); - Event event = Event( - writableCalendars!.id, - start: scheduleDateTimeUTZ, - end: scheduleDateTimeUTZ.add(Duration(minutes: 30)), - title: title, - description: description, - ); - - ios.CalendarEvent iosCalEvent = - ios.CalendarEvent(location: location, startDate: scheduleDateTimeUTZ, endDate: scheduleDateTimeUTZ.add(Duration(minutes: 30)), title: title, description: description, isAllDay: false); - - if (Platform.isAndroid) { - Result result = await deviceCalendarPlugin.hasPermissions(); - print(result); - await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) { - print("catchError " + e.toString()); - }).whenComplete(() { - print("whenComplete Calender ID " + eventId!); - }); - } else { - await _myPlugin.createEvent(calendarId: writableCalendars.id!, event: iosCalEvent).catchError((e) { - print("catchError " + e.toString()); - }).whenComplete(() { - print("whenComplete Calender ID iOS " + eventId!); - }); - } - } - - deleteEvent(String _calendarId, String _eventId) async { - if (Platform.isIOS) { - await _myPlugin.deleteEvent(calendarId: _calendarId, eventId: _eventId); - } else { - await deviceCalendarPlugin.deleteEvent(_calendarId, _eventId); - } - } - - Future retrieveEvents( - String calendarId, - RetrieveEventsParams retrieveEventsParams, - ) async { - if (Platform.isIOS) { - return await _myPlugin.getEvents(calendarId: calendarId); - } else { - return await deviceCalendarPlugin.retrieveEvents(calendarId, retrieveEventsParams); - } - } - - Future createCalendar( - String calendarName, { - Color? calendarColor, - String? localAccountName, - }) async { - return await deviceCalendarPlugin.createCalendar(calendarName, calendarColor: calendarColor, localAccountName: localAccountName); - } -} - -Future> requestPermissions() async { - var permissionResults = [Permission.calendarFullAccess].request(); - return permissionResults; -} - -showReminderBottomSheet(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, - {required Function() onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool isMultiAllowed = false}) async { - if (Platform.isAndroid) { - if (await PermissionService.isCalendarPermissionEnabled()) { - _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, - onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); - } else { - // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async { - // if (await Permission.calendarFullAccess.request().isGranted) { - // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, - // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); - // } - // }); - } - } else { - if (await Permission.calendarWriteOnly.request().isGranted) { - if (await Permission.calendarFullAccess.request().isGranted) { - _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, - onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); - } - } - } -} - -Future _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, - {required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async { - showCommonBottomSheetWithoutHeight(providedContext, title: "Set the timer of reminder".needTranslation, child: PrescriptionReminderView( - setReminder: (int value) async { - if (!isMultiAllowed!) { - if (onMultiDateSuccess == null) { - CalendarUtils calendarUtils = await CalendarUtils.getInstance(); - await calendarUtils.createOrUpdateEvent( - title: title ?? "You have appointment with Dr. ".needTranslation + doctorName, - description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, - scheduleDateTime: dateTime, - eventId: eventId, - location: ''); - onSuccess(); - } - } else { - onMultiDateSuccess!(value); - } - }, - ), callBackFunc: () {}, isFullScreen: false); -} - -setCalender(BuildContext context, - {required String eventId, required int selectedMinutes, int? frequencyNumber, required int days, required String orderDate, required String itemDescriptionN, required String route}) async { - DateTime actualDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, 8, 0); - frequencyNumber ??= 2; //Some time frequency number is null so by default will be 2 - - int remainingDays = days - (Jiffy.parseFromDateTime(DateTime.now()).diff(Jiffy.parseFromDateTime(DateUtil.convertStringToDate(orderDate)), unit: Unit.day) as int); - if (remainingDays.isNegative) { - getIt.get().showErrorBottomSheet(message: "Prescription date has been already passed you can not add a reminder for this prescription."); - return; - } - CalendarUtils calendarUtils = await CalendarUtils.getInstance(); - - try { - for (int i = 0; i < remainingDays; i++) { - //event for number of days. - for (int j = 0; j < frequencyNumber; j++) { - // event for number of times per day. - if (j != 0) { - actualDate.add(new Duration(hours: 8)); // 8 hours addition for daily dose. - } - //Time subtraction from actual reminder time. like before 30, or 1 hour. - - actualDate = Jiffy.parseFromDateTime(actualDate).subtract(minutes: selectedMinutes).dateTime; - - calendarUtils.createOrUpdateEvent( - title: "$itemDescriptionN} Prescription Reminder", - description: "$itemDescriptionN $frequencyNumber $route ", - scheduleDateTime: actualDate, - eventId: eventId + (i.toString() + j.toString()), - location: '', //event id with varitions - ); - - actualDate = DateTime(actualDate.year, actualDate.month, actualDate.day, 8, 0); - } - actualDate = Jiffy.parseFromDateTime(actualDate).add(days: 1).dateTime; - } - } catch (ex) { - getIt.get().showErrorBottomSheet(message: "catch:$ex"); - } -} - -Future checkAndRemove(hasReminder, {bool delete = false, String itemDescriptionN = ""}) async { - final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin(); - CalendarUtils calendarUtils = await CalendarUtils.getInstance(); - DateTime startEventsDate = Jiffy.parseFromDateTime(DateTime.now()).subtract(days: 30).dateTime; - DateTime endEventsDate = Jiffy.parseFromDateTime(DateTime.now()).add(days: 120).dateTime; - RetrieveEventsParams params = RetrieveEventsParams(startDate: startEventsDate, endDate: endEventsDate); - - if (calendarUtils.calendars != null) { - if (Platform.isAndroid) { - await processEvents(calendarUtils.calendars, calendarUtils, params, delete, itemDescriptionN, hasReminder); - } else { - List? iosCalendars = await _myPlugin.getCalendars(); - if (iosCalendars != null) { - await processEvents(iosCalendars.map((cal) => Calendar(id: cal.id, name: cal.name, accountName: cal.accountName)).toList(), calendarUtils, params, delete, itemDescriptionN, hasReminder); - } - } - } -} - -Future processEvents(List calendars, calendarUtils, params, delete, String itemDescriptionN, hasReminder) async { - for (var calendar in calendars) { - Result> events = await calendarUtils.retrieveEvents(calendar.id!, params); - for (var event in events.data!) { - if (event.title!.contains(itemDescriptionN)) { - if (delete) { - await calendarUtils.deleteEvent(calendar, event); - // AppToast.showSuccessToast(message: TranslationBase.of(context).reminderCancelSuccess); - hasReminder = false; - } else { - hasReminder = false; - // setState(() { - // hasReminder = true; - // }); - } - } - } - } -} diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 58958ee..d80d32e 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -8,7 +8,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.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/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; @@ -293,7 +292,7 @@ class _AppointmentDetailsPageState extends State { DateTime startDate = DateTime.now(); DateTime endDate = DateUtil.convertStringToDate(widget .patientAppointmentHistoryResponseModel.appointmentDate); - showReminderBottomSheet( + BottomSheetUtils().showReminderBottomSheet( context, endDate, widget.patientAppointmentHistoryResponseModel.doctorNameObj??"", diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index d5e8138..a38ff92 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -4,7 +4,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; -import 'package:hmg_patient_app_new/core/utils/calendar_utils.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; @@ -41,7 +40,6 @@ class _PrescriptionDetailPageState extends State { @override void initState() { - checkAndRemove(false); // locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context); // WidgetsBinding.instance.addPostFrameCallback((_) => locationUtils.getCurrentLocation()); if (!widget.isFromAppointments) { diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart index 39a0b05..100d963 100644 --- a/lib/presentation/prescriptions/prescription_item_view.dart +++ b/lib/presentation/prescriptions/prescription_item_view.dart @@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart'; 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'; @@ -11,6 +10,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/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; class PrescriptionItemView extends StatelessWidget { @@ -169,7 +169,7 @@ class PrescriptionItemView extends StatelessWidget { DateTime startDate = DateTime.now(); DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt()); - showReminderBottomSheet( + BottomSheetUtils().showReminderBottomSheet( context, endDate, "", diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart index 99ff230..9312519 100644 --- a/lib/widgets/common_bottom_sheet.dart +++ b/lib/widgets/common_bottom_sheet.dart @@ -1,11 +1,65 @@ +import 'dart:io' show Platform; + 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/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'; +import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart'; +import 'package:hmg_patient_app_new/services/permission_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class BottomSheetUtils{ + showReminderBottomSheet(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, + {required Function() onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool isMultiAllowed = false}) async { + if (Platform.isAndroid) { + if (await PermissionService.isCalendarPermissionEnabled()) { + _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + } else { + // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async { + // if (await Permission.calendarFullAccess.request().isGranted) { + // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + // } + // }); + } + } else { + if (await Permission.calendarWriteOnly.request().isGranted) { + if (await Permission.calendarFullAccess.request().isGranted) { + _showReminderBottomSheet(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + } + } + } + } + + Future _showReminderBottomSheet(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, + {required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async { + showCommonBottomSheetWithoutHeight(providedContext, title: "Set the timer of reminder".needTranslation, child: PrescriptionReminderView( + setReminder: (int value) async { + if (!isMultiAllowed!) { + if (onMultiDateSuccess == null) { + CalenderUtilsNew calendarUtils = CalenderUtilsNew.instance; + await calendarUtils.createOrUpdateEvent( + title: title ?? "You have appointment with Dr. ".needTranslation + doctorName, + description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, + scheduleDateTime: dateTime, + eventId: eventId, + location: ''); + onSuccess(); + } + } else { + onMultiDateSuccess!(value); + } + }, + ), callBackFunc: () {}, isFullScreen: false); + } +} void showCommonBottomSheet(BuildContext context, {required Widget child, Function(String?)? callBackFunc,