From cb4601050c187dbf6e3b03729ba9a28d7c30794d Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 8 Sep 2025 17:20:21 +0300 Subject: [PATCH 1/3] prescription reminder bottom sheet added. --- assets/images/svg/bell.svg | 4 + lib/core/app_assets.dart | 1 + lib/core/utils/calendar_utils.dart | 175 ++++++++++-------- lib/extensions/string_extensions.dart | 4 +- .../prescription_detail_page.dart | 11 +- .../prescription_reminder_view.dart | 116 ++++++++++++ lib/theme/colors.dart | 1 + lib/widgets/common_bottom_sheet.dart | 49 ++++- 8 files changed, 275 insertions(+), 86 deletions(-) create mode 100644 assets/images/svg/bell.svg create mode 100644 lib/presentation/prescriptions/prescription_reminder_view.dart diff --git a/assets/images/svg/bell.svg b/assets/images/svg/bell.svg new file mode 100644 index 0000000..82be912 --- /dev/null +++ b/assets/images/svg/bell.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index ac3cfe6..c70a309 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -13,6 +13,7 @@ class AppAssets { static const String email = '$svgBasePath/email.svg'; static const String globe = '$svgBasePath/globe.svg'; static const String cancel = '$svgBasePath/cancel.svg'; + static const String bell = '$svgBasePath/bell.svg'; static const String login1 = '$svgBasePath/login1.svg'; static const String tamara = '$svgBasePath/tamara.svg'; static const String confirm = '$svgBasePath/confirm.svg'; diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart index 54b550f..00a5958 100644 --- a/lib/core/utils/calendar_utils.dart +++ b/lib/core/utils/calendar_utils.dart @@ -7,6 +7,7 @@ import 'package:device_calendar/device_calendar.dart'; import 'package:flutter/widgets.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.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'; @@ -54,88 +55,100 @@ class CalendarUtils { return permissionResults; } - // showReminderDialog(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()) { - // _showReminderDialog(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) { - // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, - // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); - // } - // } - // } - // } + showReminderDialog(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 _showReminderDialog(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 { - // return showDialog( - // context: providedContext, - // barrierDismissible: true, // user must tap button! - // builder: (BuildContext context) { - // return Dialog( - // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)), - // insetPadding: EdgeInsets.all(21), - // child: ReminderDialog( - // onClick: (int i) async { - // String text = ""; - // if (i == 0) { - // // Before 30 mints - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(minutes: 30).dateTime; - // text = "30 minutes"; - // // dateTime.add(new Duration(minutes: -30)); - // } else if (i == 1) { - // // Before 1 hour - // // dateTime.add(new Duration(minutes: -60)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1).dateTime; - // text = "1 hours"; - // } else if (i == 2) { - // // Before 1 hour and 30 mints - // // dateTime.add(new Duration(minutes: -90)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1, minutes: 30).dateTime; - // text = "1 hours 30 minutes"; - // } else if (i == 3) { - // // Before 2 hours - // // dateTime.add(new Duration(minutes: -120)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 2).dateTime; - // text = "2 hours"; - // } - // if (!isMultiAllowed!) { - // if (onMultiDateSuccess == null) { - // CalendarUtils calendarUtils = await CalendarUtils.getInstance(); - // await calendarUtils.createOrUpdateEvent( - // title: title ?? "TranslationBase.of(providedContext).reminderTitle".needTranslation + " " + doctorName, - // description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, - // scheduleDateTime: dateTime, - // eventId: eventId, location: ''); - // onSuccess(); - // } - // } else { - // onMultiDateSuccess!(i); - // } - // // await _analytics.logEvent( - // // name: name.trim().toLowerCase(), - // // parameters: safeParameters, - // // ); - // // todo @sikander discuss analytics for reminder - // // locator().appointment.appointment_reminder_time(reminde_before: text); - // }, - // ), - // ); - // }, - // ); - // } + 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 { + showCommonBottomSheet( + providedContext, + child: Column(children: [ + + ],), + callBackFunc: () {}, + title: "", + isCloseButtonVisible: false, + isFullScreen: false, height: null, + ); + + // return showDialog( + // context: providedContext, + // barrierDismissible: true, // user must tap button! + // builder: (BuildContext context) { + // return Dialog( + // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)), + // insetPadding: EdgeInsets.all(21), + // child: ReminderDialog( + // onClick: (int i) async { + // String text = ""; + // if (i == 0) { + // // Before 30 mints + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(minutes: 30).dateTime; + // text = "30 minutes"; + // // dateTime.add(new Duration(minutes: -30)); + // } else if (i == 1) { + // // Before 1 hour + // // dateTime.add(new Duration(minutes: -60)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1).dateTime; + // text = "1 hours"; + // } else if (i == 2) { + // // Before 1 hour and 30 mints + // // dateTime.add(new Duration(minutes: -90)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1, minutes: 30).dateTime; + // text = "1 hours 30 minutes"; + // } else if (i == 3) { + // // Before 2 hours + // // dateTime.add(new Duration(minutes: -120)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 2).dateTime; + // text = "2 hours"; + // } + // if (!isMultiAllowed!) { + // if (onMultiDateSuccess == null) { + // CalendarUtils calendarUtils = await CalendarUtils.getInstance(); + // await calendarUtils.createOrUpdateEvent( + // title: title ?? "TranslationBase.of(providedContext).reminderTitle".needTranslation + " " + doctorName, + // description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, + // scheduleDateTime: dateTime, + // eventId: eventId, + // location: ''); + // onSuccess(); + // } + // } else { + // onMultiDateSuccess!(i); + // } + // // await _analytics.logEvent( + // // name: name.trim().toLowerCase(), + // // parameters: safeParameters, + // // ); + // // todo @sikander discuss analytics for reminder + // // locator().appointment.appointment_reminder_time(reminde_before: text); + // }, + // ), + // ); + // }, + // ); + } static Future getInstance() async { tzl.initializeTimeZones(); diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 0f04824..3dfe75f 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -203,9 +203,9 @@ extension EmailValidator on String { style: TextStyle(fontSize: 19.fSize, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4), ); - Widget toText20({Color? color, bool isBold = false}) => Text( + Widget toText20({Color? color,FontWeight? weight, bool isBold = false}) => Text( this, - style: TextStyle(fontSize: 20.fSize, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4), + style: TextStyle(fontSize: 20.fSize, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4), ); Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index 1f8e0a2..fbc44ba 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -12,8 +12,10 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.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/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.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/shimmer/movies_shimmer_widget.dart'; import 'package:provider/provider.dart'; @@ -309,8 +311,7 @@ class _PrescriptionDetailPageState extends State { LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), "Notify me before the consumption time".toText10(color: AppColors.textColorLight), ], - ), - SizedBox(width: 12.h), + ).expanded, Switch( activeColor: AppColors.successColor, activeTrackColor: AppColors.successColor.withValues(alpha: .15), @@ -319,6 +320,12 @@ class _PrescriptionDetailPageState extends State { setState(() { prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]); }); + showCommonBottomSheetWithoutHeight(context, title: "Set the timer of reminder".needTranslation, child: PrescriptionReminderView( + setReminder: (int value) { + DateTime startDate = DateTime.now(); + DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt()); + }, + ), callBackFunc: () {}, isFullScreen: false); }, ), ], diff --git a/lib/presentation/prescriptions/prescription_reminder_view.dart b/lib/presentation/prescriptions/prescription_reminder_view.dart new file mode 100644 index 0000000..69758df --- /dev/null +++ b/lib/presentation/prescriptions/prescription_reminder_view.dart @@ -0,0 +1,116 @@ +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/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +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'; + +class PrescriptionReminderView extends StatefulWidget { + Function(int) setReminder; + + PrescriptionReminderView({Key? key, required this.setReminder}) : super(key: key); + + @override + _PrescriptionReminderViewState createState() { + return _PrescriptionReminderViewState(); + } +} + +class _PrescriptionReminderViewState extends State { + final List _options = [15, 30, 60, 90]; + int _selectedOption = 0; // Nullable to represent no selection initially + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + spacing: 16.h, + children: [ + Container( + width: double.infinity, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24), + child: ListView.builder( + itemCount: _options.length, + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(top: 8, bottom: 8), + shrinkWrap: true, + itemBuilder: (context, index) { + return Theme( + data: Theme.of(context).copyWith( + listTileTheme: ListTileThemeData(horizontalTitleGap: 4), + ), + child: RadioListTile( + title: Text( + "${_options[index]} minutes before".needTranslation, + style: TextStyle( + fontSize: 16.h, + fontWeight: FontWeight.w500, + ), + ), + value: index, + fillColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.selected)) { + return AppColors.primaryRedColor; + } + return Color(0xffEEEEEE); + }), + contentPadding: EdgeInsets.only(left: 12.h, right: 12.h), + groupValue: _selectedOption, + onChanged: (int? newValue) { + setState(() { + _selectedOption = newValue!; + }); + }, + ), + ); + }, + ), + ), + Row( + spacing: 16.h, + children: [ + Expanded( + child: CustomButton( + text: LocaleKeys.cancel.tr(), + onPressed: () { + Navigator.of(context).pop(); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + icon: AppAssets.cancel, + iconColor: AppColors.primaryRedColor, + ), + ), + Expanded( + child: CustomButton( + text: LocaleKeys.setReminder.tr(), + onPressed: () { + Navigator.of(context).pop(); + widget.setReminder(_selectedOption); + }, + backgroundColor: AppColors.bgGreenColor, + borderColor: AppColors.bgGreenColor, + textColor: Colors.white, + icon: AppAssets.bell, + ), + ), + ], + ), + ], + ); + } +} diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index 5cb9ced..5fb0df4 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -12,6 +12,7 @@ class AppColors { static const lightGray = Color(0xFFF4F5F7); static const lightPurple = Color(0xFFB7A3E6); static const scaffoldBgColor = Color(0xFFF8F8F8); + static const bottomSheetBgColor = Color(0xFFF8F8FA); static const lightGreyEFColor = Color(0xffeaeaff); static const greyF7Color = Color(0xffF7F7F7); static const lightGrayColor = Color(0xff808080); diff --git a/lib/widgets/common_bottom_sheet.dart b/lib/widgets/common_bottom_sheet.dart index f6039eb..95f8fc5 100644 --- a/lib/widgets/common_bottom_sheet.dart +++ b/lib/widgets/common_bottom_sheet.dart @@ -7,7 +7,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; void showCommonBottomSheet(BuildContext context, - {required Widget child, required VoidCallback callBackFunc, String? title, required double height, bool isCloseButtonVisible = true, bool isFullScreen = true}) { + {required Widget child, required VoidCallback callBackFunc, String? title, required double? height, bool isCloseButtonVisible = true, bool isFullScreen = true}) { showModalBottomSheet( sheetAnimationStyle: AnimationStyle( duration: Duration(milliseconds: 500), // Custom animation duration @@ -86,3 +86,50 @@ class ButtonSheetContent extends StatelessWidget { ); } } + +void showCommonBottomSheetWithoutHeight( + BuildContext context, { + required Widget child, + required VoidCallback callBackFunc, + String title = "", + bool isCloseButtonVisible = true, + bool isFullScreen = true, +}) { + showModalBottomSheet( + sheetAnimationStyle: AnimationStyle( + duration: Duration(milliseconds: 500), // Custom animation duration + reverseDuration: Duration(milliseconds: 300), // Custom reverse animation duration + ), + context: context, + isScrollControlled: true, + showDragHandle: false, + backgroundColor: AppColors.bottomSheetBgColor, + builder: (BuildContext context) { + return SafeArea( + top: false, + left: false, + right: false, + child: Container( + padding: EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 12), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.bottomSheetBgColor, borderRadius: 24.h), + child: Column( + mainAxisSize: MainAxisSize.min, + spacing: 16.h, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (title.isNotEmpty) title.toText20(weight: FontWeight.w600).expanded, + Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon, iconColor: Color(0xff2B353E)).onPress(() { + Navigator.of(context).pop(); + }), + ], + ), + child, + ], + )), + ); + }).then((value) { + callBackFunc(); + }); +} From d464721733233be8d0a74e8fc23e0fabc90d8bcf Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 9 Sep 2025 10:04:06 +0300 Subject: [PATCH 2/3] merge conflict fixed. --- assets/images/svg/reminder_bell.svg | 4 ++++ ios/Runner/Runner.entitlements | 17 ++++++++++++++++ lib/core/app_assets.dart | 2 +- lib/core/utils/calendar_utils.dart | 20 +++++++++---------- .../prescription_reminder_view.dart | 2 +- 5 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 assets/images/svg/reminder_bell.svg create mode 100644 ios/Runner/Runner.entitlements diff --git a/assets/images/svg/reminder_bell.svg b/assets/images/svg/reminder_bell.svg new file mode 100644 index 0000000..82be912 --- /dev/null +++ b/assets/images/svg/reminder_bell.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..319178a --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,17 @@ + + + + + aps-environment + development + com.apple.developer.in-app-payments + + merchant.com.hmgwebservices + merchant.com.hmgwebservices.uat + + com.apple.developer.nfc.readersession.formats + + TAG + + + diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index edab028..76c643b 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -85,7 +85,7 @@ class AppAssets { static const String uae_dirham_symbol = '$svgBasePath/uae_dirham_symbol.svg'; static const String directions_icon = '$svgBasePath/directions_icon.svg'; static const String apple_pay_button = '$svgBasePath/pay_with_apple_pay.svg'; - static const String bell = '$svgBasePath/bell.svg'; + static const String reminder_bell = '$svgBasePath/reminder_bell.svg'; //bottom navigation// diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart index 00a5958..297ae2f 100644 --- a/lib/core/utils/calendar_utils.dart +++ b/lib/core/utils/calendar_utils.dart @@ -81,16 +81,16 @@ class CalendarUtils { 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 { - showCommonBottomSheet( - providedContext, - child: Column(children: [ - - ],), - callBackFunc: () {}, - title: "", - isCloseButtonVisible: false, - isFullScreen: false, height: null, - ); + // showCommonBottomSheet( + // providedContext, + // child: Column(children: [ + // + // ],), + // callBackFunc: () {}, + // title: "", + // isCloseButtonVisible: false, + // isFullScreen: false, height: null, + // ); // return showDialog( // context: providedContext, diff --git a/lib/presentation/prescriptions/prescription_reminder_view.dart b/lib/presentation/prescriptions/prescription_reminder_view.dart index 69758df..8b7df0b 100644 --- a/lib/presentation/prescriptions/prescription_reminder_view.dart +++ b/lib/presentation/prescriptions/prescription_reminder_view.dart @@ -105,7 +105,7 @@ class _PrescriptionReminderViewState extends State { backgroundColor: AppColors.bgGreenColor, borderColor: AppColors.bgGreenColor, textColor: Colors.white, - icon: AppAssets.bell, + icon: AppAssets.reminder_bell, ), ), ], From 7cc12bd1cf8707fba9d901810d87f7790f40b9f0 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Tue, 9 Sep 2025 13:07:51 +0300 Subject: [PATCH 3/3] prescription calender reminder added. --- lib/core/utils/calendar_utils.dart | 236 ++++++++++-------- lib/extensions/widget_extensions.dart | 14 ++ .../prescriptions_view_model.dart | 4 + .../prescription_detail_page.dart | 194 +------------- .../prescriptions/prescription_item_view.dart | 233 +++++++++++++++++ 5 files changed, 394 insertions(+), 287 deletions(-) create mode 100644 lib/presentation/prescriptions/prescription_item_view.dart diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart index 297ae2f..979ce1b 100644 --- a/lib/core/utils/calendar_utils.dart +++ b/lib/core/utils/calendar_utils.dart @@ -1,11 +1,16 @@ 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'; @@ -50,106 +55,6 @@ class CalendarUtils { // return _completer!.future; // } - Future> requestPermissions() async { - var permissionResults = [Permission.calendarFullAccess].request(); - return permissionResults; - } - - showReminderDialog(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 { - // showCommonBottomSheet( - // providedContext, - // child: Column(children: [ - // - // ],), - // callBackFunc: () {}, - // title: "", - // isCloseButtonVisible: false, - // isFullScreen: false, height: null, - // ); - - // return showDialog( - // context: providedContext, - // barrierDismissible: true, // user must tap button! - // builder: (BuildContext context) { - // return Dialog( - // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)), - // insetPadding: EdgeInsets.all(21), - // child: ReminderDialog( - // onClick: (int i) async { - // String text = ""; - // if (i == 0) { - // // Before 30 mints - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(minutes: 30).dateTime; - // text = "30 minutes"; - // // dateTime.add(new Duration(minutes: -30)); - // } else if (i == 1) { - // // Before 1 hour - // // dateTime.add(new Duration(minutes: -60)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1).dateTime; - // text = "1 hours"; - // } else if (i == 2) { - // // Before 1 hour and 30 mints - // // dateTime.add(new Duration(minutes: -90)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1, minutes: 30).dateTime; - // text = "1 hours 30 minutes"; - // } else if (i == 3) { - // // Before 2 hours - // // dateTime.add(new Duration(minutes: -120)); - // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 2).dateTime; - // text = "2 hours"; - // } - // if (!isMultiAllowed!) { - // if (onMultiDateSuccess == null) { - // CalendarUtils calendarUtils = await CalendarUtils.getInstance(); - // await calendarUtils.createOrUpdateEvent( - // title: title ?? "TranslationBase.of(providedContext).reminderTitle".needTranslation + " " + doctorName, - // description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, - // scheduleDateTime: dateTime, - // eventId: eventId, - // location: ''); - // onSuccess(); - // } - // } else { - // onMultiDateSuccess!(i); - // } - // // await _analytics.logEvent( - // // name: name.trim().toLowerCase(), - // // parameters: safeParameters, - // // ); - // // todo @sikander discuss analytics for reminder - // // locator().appointment.appointment_reminder_time(reminde_before: text); - // }, - // ), - // ); - // }, - // ); - } - static Future getInstance() async { tzl.initializeTimeZones(); if (_completer != null) { @@ -278,3 +183,134 @@ class CalendarUtils { 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/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index d1a3db4..f576d0c 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -39,6 +39,20 @@ extension WidgetExtensions on Widget { child: this, ); + Widget toShimmer2({bool isShow = true, double radius = 20}) => isShow + ? Shimmer.fromColors( + baseColor: const Color(0xffe8eff0), + highlightColor: Colors.white, + child: ClipRRect( + borderRadius: BorderRadius.circular(radius), + child: Container( + color: Colors.white, + child: this, + ), + ), + ) + : this; + Widget animatedSwither() => AnimatedSwitcher( duration: const Duration(milliseconds: 500), // transitionBuilder: (Widget child, Animation animation) { diff --git a/lib/features/prescriptions/prescriptions_view_model.dart b/lib/features/prescriptions/prescriptions_view_model.dart index ff93f84..306551d 100644 --- a/lib/features/prescriptions/prescriptions_view_model.dart +++ b/lib/features/prescriptions/prescriptions_view_model.dart @@ -51,6 +51,10 @@ class PrescriptionsViewModel extends ChangeNotifier { } } + notify() { + notifyListeners(); + } + setIsSortByClinic(bool value) { isSortByClinic = value; if (isSortByClinic) { diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index fbc44ba..77fc273 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -4,6 +4,7 @@ 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'; @@ -12,6 +13,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.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/prescriptions_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_item_view.dart'; import 'package:hmg_patient_app_new/presentation/prescriptions/prescription_reminder_view.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; @@ -35,6 +37,9 @@ class _PrescriptionDetailPageState extends State { @override void initState() { + checkAndRemove(false); + // locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context); + // WidgetsBinding.instance.addPostFrameCallback((_) => locationUtils.getCurrentLocation()); scheduleMicrotask(() { prescriptionsViewModel.getPrescriptionDetails(widget.prescriptionsResponseModel); }); @@ -177,199 +182,14 @@ class _PrescriptionDetailPageState extends State { itemCount: prescriptionVM.isPrescriptionsDetailsLoading ? 5 : prescriptionVM.prescriptionDetailsList.length, itemBuilder: (context, index) { return prescriptionVM.isPrescriptionsDetailsLoading - ? const MoviesShimmerWidget() + ? PrescriptionItemView(prescriptionVM: prescriptionVM, index: index, isLoading: true) : AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( - child: AnimatedContainer( - duration: Duration(milliseconds: 300), - curve: Curves.easeInOut, - margin: EdgeInsets.symmetric(vertical: 8.h), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 16.h), - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.network( - prescriptionVM.prescriptionDetailsList[index].imageThumbUrl!, - width: 60.h, - height: 60.h, - fit: BoxFit.fill, - ).circle(100), - SizedBox(width: 8.h), - Expanded( - child: prescriptionVM.prescriptionDetailsList[index].itemDescription!.toText16(isBold: true, maxlines: 2), - ), - ], - ).paddingSymmetrical(16.h, 0.h), - SizedBox(height: 16.h), - Wrap( - direction: Axis.horizontal, - spacing: 6.h, - runSpacing: 6.h, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.route.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].route}", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.w500, - borderRadius: 8, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.frequency.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].frequency}", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.w500, - borderRadius: 8, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.w500, - borderRadius: 8, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - CustomButton( - text: "${LocaleKeys.days.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].days}", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.w500, - borderRadius: 8, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - ], - ).paddingSymmetrical(16.h, 0.h), - SizedBox(height: 8.h), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h), - SizedBox(width: 9.h), - Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)), - ], - ).paddingSymmetrical(16.h, 0.h), - SizedBox(height: 14.h), - Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), - SizedBox(height: 14.h), - Row( - mainAxisSize: MainAxisSize.max, - children: [ - Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h), - SizedBox(width: 8.h), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), - "Notify me before the consumption time".toText10(color: AppColors.textColorLight), - ], - ).expanded, - Switch( - activeColor: AppColors.successColor, - activeTrackColor: AppColors.successColor.withValues(alpha: .15), - value: prescriptionVM.prescriptionDetailsList[index].hasReminder!, - onChanged: (newValue) { - setState(() { - prescriptionVM.setPrescriptionItemReminder(newValue, prescriptionVM.prescriptionDetailsList[index]); - }); - showCommonBottomSheetWithoutHeight(context, title: "Set the timer of reminder".needTranslation, child: PrescriptionReminderView( - setReminder: (int value) { - DateTime startDate = DateTime.now(); - DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt()); - }, - ), callBackFunc: () {}, isFullScreen: false); - }, - ), - ], - ).paddingSymmetrical(16.h, 0.h), - SizedBox(height: 14.h), - Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), - Row( - children: [ - Expanded( - child: CustomButton( - text: LocaleKeys.checkAvailability.tr(context: context), - onPressed: () {}, - backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), - borderColor: AppColors.primaryRedColor.withOpacity(0.0), - textColor: AppColors.primaryRedColor, - fontSize: 13, - fontWeight: FontWeight.w500, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 40.h, - ), - ), - SizedBox(width: 16.h), - Expanded( - child: CustomButton( - text: LocaleKeys.readInstructions.tr(context: context), - onPressed: () {}, - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: AppColors.whiteColor, - fontSize: 13, - fontWeight: FontWeight.w500, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 40.h, - ), - ), - ], - ).paddingSymmetrical(16.h, 16.h), - ], - ) - ], - ), - ), + child: PrescriptionItemView(prescriptionVM: prescriptionVM, index: index), ), ), ); diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart new file mode 100644 index 0000000..8357033 --- /dev/null +++ b/lib/presentation/prescriptions/prescription_item_view.dart @@ -0,0 +1,233 @@ +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/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/features/prescriptions/prescriptions_view_model.dart'; +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'; + +class PrescriptionItemView extends StatelessWidget { + int index; + PrescriptionsViewModel prescriptionVM; + bool isLoading; + + PrescriptionItemView({Key? key, required this.prescriptionVM, required this.index, this.isLoading = false}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + margin: EdgeInsets.symmetric(vertical: 8.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + spacing: 8.h, + children: [ + Image.network( + isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].imageThumbUrl!, + width: 60.h, + height: 60.h, + errorBuilder: (cxt, child, tr) { + return SizedBox(height: 60, width: 60); + }, + fit: BoxFit.fill, + ).toShimmer2(isShow: isLoading).circle(100), + Expanded( + child: (isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].itemDescription!).toText16(isBold: true, maxlines: 2).toShimmer2(isShow: isLoading), + ), + ], + ).paddingSymmetrical(16.h, 0.h), + SizedBox(height: 16.h), + Wrap( + direction: Axis.horizontal, + spacing: 6.h, + runSpacing: 6.h, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + CustomButton( + text: "${LocaleKeys.route.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].route}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ).toShimmer2(isShow: isLoading), + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + CustomButton( + text: "${LocaleKeys.frequency.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].frequency}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ).toShimmer2(isShow: isLoading), + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + CustomButton( + text: "${LocaleKeys.dailyDoses.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].doseDailyQuantity}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ).toShimmer2(isShow: isLoading), + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + CustomButton( + text: "${LocaleKeys.days.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].days}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ).toShimmer2(isShow: isLoading), + ], + ), + ], + ).paddingSymmetrical(16.h, 0.h), + SizedBox(height: 8.h), + if (!isLoading) + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.prescription_remarks_icon, width: 18.h, height: 18.h), + SizedBox(width: 9.h), + Expanded(child: "${LocaleKeys.remarks.tr(context: context)}: ${isLoading ? "" : prescriptionVM.prescriptionDetailsList[index].remarks!}".toText10(isBold: true)), + ], + ).paddingSymmetrical(16.h, 0.h), + SizedBox(height: 14.h), + Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), + SizedBox(height: 14.h), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.prescription_reminder_icon, width: 35.h, height: 35.h).toShimmer2(isShow: isLoading), + SizedBox(width: 8.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), + "Notify me before the consumption time".toText10(color: AppColors.textColorLight), + ], + ).toShimmer2(isShow: isLoading).expanded, + Switch( + activeColor: AppColors.successColor, + activeTrackColor: AppColors.successColor.withValues(alpha: .15), + value: isLoading ? false : prescriptionVM.prescriptionDetailsList[index].hasReminder!, + onChanged: (newValue) async { + if (prescriptionVM.prescriptionDetailsList[index].hasReminder ?? false) { + await checkAndRemove(prescriptionVM.prescriptionDetailsList[index].hasReminder, delete: true); + prescriptionVM.notify(); + return; + } + + DateTime startDate = DateTime.now(); + DateTime endDate = DateTime(startDate.year, startDate.month, startDate.day + prescriptionVM.prescriptionDetailsList[index].days!.toInt()); + showReminderBottomSheet( + context, + endDate, + "", + prescriptionVM.prescriptionDetailsList[index].itemID.toString(), + "", + "", + title: "${prescriptionVM.prescriptionDetailsList[index].itemDescription} Prescription Reminder", + 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, + 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!); + }, + ); + }, + ).toShimmer2(isShow: isLoading), + ], + ).paddingSymmetrical(16.h, 0.h), + SizedBox(height: 14.h), + Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), + Row( + children: [ + Expanded( + child: CustomButton( + text: LocaleKeys.checkAvailability.tr(context: context), + onPressed: () {}, + backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), + borderColor: AppColors.primaryRedColor.withOpacity(0.0), + textColor: AppColors.primaryRedColor, + fontSize: 13, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 40.h, + ).toShimmer2(isShow: isLoading), + ), + SizedBox(width: 16.h), + Expanded( + child: CustomButton( + text: LocaleKeys.readInstructions.tr(context: context), + onPressed: () {}, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: AppColors.whiteColor, + fontSize: 13, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 40.h, + ).toShimmer2(isShow: isLoading), + ), + ], + ).paddingSymmetrical(16.h, 16.h), + ], + ), + ); + } +}