diff --git a/assets/images/svg/livecare_reschedule_icon.svg b/assets/images/svg/livecare_reschedule_icon.svg new file mode 100644 index 00000000..a1e6c21a --- /dev/null +++ b/assets/images/svg/livecare_reschedule_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index d0321ace..cc468e14 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1966,5 +1966,11 @@ "weeklyShift": "الفترات الأسبوعية", "dayOff": "إجازة", "notAvailable": "غير متاح", - "hide": "إخفاء" + "hide": "إخفاء", + "liveCareSupport": "دعم لايف كير", + "liveCareSupportAssistance": "للتواصل والمساعدة", + "liveCareSupportWhatsApp": "ارسال رسالة واتس اب", + "preferredConsultationLanguage": "اللغة المفضلة للاستشارة", + "preferredConsultationLanguageEn": "أرغب أن يتحدث معي الطبيب باللغة العربية", + "preferredConsultationLanguageAr": "أرغب أن يتحدث مع الطبيب باللغة اللانجليزية" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index ae344b01..2c2756f9 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1956,7 +1956,13 @@ "weeklyShift": "Weekly Shift", "dayOff": "Off", "notAvailable": "Not Available", - "hide": "Hide" + "hide": "Hide", + "liveCareSupport": "LiveCare Support", + "liveCareSupportAssistance": "For Support & Assistance", + "liveCareSupportWhatsApp": "Send WhatsApp Message", + "preferredConsultationLanguage": "Preferred Consultation Language", + "preferredConsultationLanguageEn": "I would like to speak with the doctor in Arabic", + "preferredConsultationLanguageAr": "I would like to speak with the doctor in English" } diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 3bfbf6cb..87de3c8d 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -210,8 +210,8 @@ class ApiClientImp implements ApiClient { body['TokenID'] = "@dm!n"; } - // body['TokenID'] = "@dm!n"; - // body['PatientID'] = 2122445; + body['TokenID'] = "@dm!n"; + // body['PatientID'] = 4770714; // body['PatientID'] = 53320; // body['PatientTypeID'] = 1; // body['PatientOutSA'] = 0; diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index aba22eb3..dc61cc66 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -399,6 +399,7 @@ class AppAssets { static const String habibLogoOnly = '$svgBasePath/habib logo_only.svg'; static const String descriptionIcon = '$svgBasePath/description_icon.svg'; static const String selectImageIcon = '$svgBasePath/select_image_icon.svg'; + static const String liveCareRescheduleIcon = '$svgBasePath/livecare_reschedule_icon.svg'; // PNGS // static const String hmgLogo = '$pngBasePath/hmg_logo.png'; diff --git a/lib/features/immediate_livecare/immediate_livecare_view_model.dart b/lib/features/immediate_livecare/immediate_livecare_view_model.dart index 84a79c02..e02b8c61 100644 --- a/lib/features/immediate_livecare/immediate_livecare_view_model.dart +++ b/lib/features/immediate_livecare/immediate_livecare_view_model.dart @@ -52,6 +52,8 @@ class ImmediateLiveCareViewModel extends ChangeNotifier { late AppState _appState; + int selectedConsultationLanguage = 0; + Duration countdownDuration = Duration(minutes: 1, seconds: 0); ValueNotifier durationNotifier = ValueNotifier(Duration(minutes: 1, seconds: 0)); Timer? timer; @@ -65,8 +67,10 @@ class ImmediateLiveCareViewModel extends ChangeNotifier { mainLiveCareClinicList = []; isImmediateLiveCareClinicsLoading = true; liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone + selectedConsultationLanguage = 0; immediateLiveCareSelectedClinic = GetLiveCareClinicListResponseModel(); liveCareImmediateAppointmentFeesList = LiveCareImmediateAppointmentFeesList(); + notifyListeners(); } setLiveCareSelectedCallType(int value) { @@ -79,6 +83,11 @@ class ImmediateLiveCareViewModel extends ChangeNotifier { notifyListeners(); } + setSelectedConsultationLanguage(int selectedLanguageID) { + selectedConsultationLanguage = selectedLanguageID; + notifyListeners(); + } + Future getLiveCareImmediateClinicsList({Function(dynamic)? onSuccess, Function(String)? onError}) async { immediateLiveCareClinicsList.clear(); isImmediateLiveCareClinicsLoading = true; diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 87484e06..0ee8d7e3 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -172,9 +172,9 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { try { final list = response['OnlineCheckInAppointments']; patientShareObj = (list == null || list.isEmpty) ? PatientAppointmentShareResponseModel() : PatientAppointmentShareResponseModel.fromJson(list[0]); - patientShareObj.isCash = response["IsCash"]; - patientShareObj.isEligible = response["IsEligible"]; - patientShareObj.isInsured = response["IsInsured"]; + patientShareObj.isCash = list[0]["IsCash"]; + patientShareObj.isEligible = list[0]["IsEligible"]; + patientShareObj.isInsured = list[0]["IsInsured"]; // if (list == null || list.isEmpty) { // throw Exception("patient share list is empty"); diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 80cea8b4..e76ac013 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1948,5 +1948,11 @@ abstract class LocaleKeys { static const weeklyShift = 'weeklyShift'; static const dayOff = 'dayOff'; static const hide = 'hide'; + static const liveCareSupport = 'liveCareSupport'; + static const liveCareSupportAssistance = 'liveCareSupportAssistance'; + static const liveCareSupportWhatsApp = 'liveCareSupportWhatsApp'; + static const preferredConsultationLanguage = 'preferredConsultationLanguage'; + static const preferredConsultationLanguageEn = 'preferredConsultationLanguageEn'; + static const preferredConsultationLanguageAr = 'preferredConsultationLanguageAr'; } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 4d181230..ea14ebfa 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -551,7 +551,7 @@ class _AppointmentDetailsPageState extends State { widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false ? Row( children: [ - Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 40.h, height: 40.h), + Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 40.h, height: 40.h, applyThemeColor: false), SizedBox(width: 12.w), Expanded( child: Column( diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 55769fbe..159dc7f0 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -27,6 +27,7 @@ import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bot import 'package:hmg_patient_app_new/presentation/book_appointment/doctor_profile_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/livecare_support_widget.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/search_doctor_by_name.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; @@ -96,12 +97,21 @@ class _BookAppointmentPageState extends State { body: Column( children: [ Expanded( - child: CollapsingListView( - title: LocaleKeys.bookAppo.tr(context: context), - isLeading: true, - child: SingleChildScrollView( - child: Consumer(builder: (context, bookAppointmentsVM, child) { - return Column( + child: Consumer(builder: (context, bookAppointmentsVM, child) { + return CollapsingListView( + liveCareSupport: bookAppointmentsViewModel.selectedTabIndex == 1 ? () { + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.liveCareSupport.tr(), + child: LivecareSupportWidget(), + callBackFunc: () {}, + isFullScreen: false, + ); + } : null, + title: LocaleKeys.bookAppo.tr(context: context), + isLeading: true, + child: SingleChildScrollView( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 16.h), @@ -442,10 +452,10 @@ class _BookAppointmentPageState extends State { }), ], ], - ); - }), - ), - ), + ), + ), + ); + }), ), Consumer(builder: (context, bookAppointmentsVM, child) { return _buildSymptomsBottomCard(); diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart index 57fd5e94..8fc45628 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_liveca import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/preferred_consultation_language_select.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart'; import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart'; import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.dart'; @@ -29,12 +30,44 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:smooth_corner/smooth_corner.dart'; +import 'package:video_player/video_player.dart'; -class ImmediateLiveCarePaymentDetails extends StatelessWidget { +class ImmediateLiveCarePaymentDetails extends StatefulWidget { ImmediateLiveCarePaymentDetails({super.key}); + @override + State createState() => _ImmediateLiveCarePaymentDetailsState(); +} + +class _ImmediateLiveCarePaymentDetailsState extends State { // late ImmediateLiveCareViewModel immediateLiveCareViewModel; late AppState appState; + late VideoPlayerController _videoController; + bool _isVideoInitialized = false; + + @override + void initState() { + super.initState(); + _initializeVideoPlayer(); + } + + void _initializeVideoPlayer() { + _videoController = VideoPlayerController.networkUrl( + Uri.parse('https://avtshare01.rz.tu-ilmenau.de/avt-vqdb-uhd-1/test_1/segments/bigbuck_bunny_8bit_15000kbps_1080p_60.0fps_hevc.mp4'), + )..initialize().then((_) { + setState(() { + _isVideoInitialized = true; + }); + }).catchError((error) { + debugPrint('Error initializing video: $error'); + }); + } + + @override + void dispose() { + _videoController.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -141,14 +174,28 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { Utils.buildSvgWithAssets(icon: AppAssets.edit_icon, width: 24.h, height: 24.h, fit: BoxFit.contain), ], ), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.language, width: 32.h, height: 32.h, fit: BoxFit.contain, iconColor: AppColors.textColor, applyThemeColor: false), + SizedBox(width: 8.h), + "${LocaleKeys.preferredLanguage.tr()}: ${immediateLiveCareVM.selectedConsultationLanguage == 1 ? LocaleKeys.arabic.tr() : (immediateLiveCareVM.selectedConsultationLanguage == 2 ? LocaleKeys.english.tr() : "")}" + .toText16(isBold: true), + ], + ), + Utils.buildSvgWithAssets(icon: AppAssets.edit_icon, width: 24.h, height: 24.h, fit: BoxFit.contain), + ], + ), ], ), ), ).onPress(() { - showCommonBottomSheetWithoutHeight(context, child: SelectLiveCareCallType(immediateLiveCareViewModel: immediateLiveCareVM), - callBackFunc: () async { - debugPrint("Selected Call Type: ${immediateLiveCareVM.liveCareSelectedCallType}"); - }, title: LocaleKeys.selectLiveCareCallType.tr(context: context), isCloseButtonVisible: true, isFullScreen: false); + showCommonBottomSheetWithoutHeight(context, child: PreferredConsultationLanguageSelect(immediateLiveCareViewModel: immediateLiveCareVM), callBackFunc: () async { + // debugPrint("Selected Call Type: ${immediateLiveCareVM.liveCareSelectedCallType}"); + }, title: LocaleKeys.preferredConsultationLanguage.tr(context: context), isCloseButtonVisible: true, isFullScreen: false); }); }), SizedBox(height: 24.h) @@ -305,54 +352,108 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { ? CustomButton( text: LocaleKeys.confirmLiveCare.tr(context: context), onPressed: () async { - await askVideoCallPermission(context).then((val) async { - if (val) { - LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingLiveCareRequest.tr(context: context)); + if (immediateLiveCareVM.selectedConsultationLanguage != 0) { + await askVideoCallPermission(context).then((val) async { + if (val) { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingLiveCareRequest.tr(context: context)); - await immediateLiveCareVM.addNewCallRequestForImmediateLiveCare( - "${appState.getAuthenticatedUser()!.patientId}${DateTime.now().millisecondsSinceEpoch}"); - await immediateLiveCareVM.getPatientLiveCareHistory(); - LoaderBottomSheet.hideLoader(); - if (immediateLiveCareVM.patientHasPendingLiveCareRequest) { - Navigator.pushAndRemoveUntil( - context, + await immediateLiveCareVM.addNewCallRequestForImmediateLiveCare("${appState.getAuthenticatedUser()!.patientId}${DateTime.now().millisecondsSinceEpoch}"); + await immediateLiveCareVM.getPatientLiveCareHistory(); + LoaderBottomSheet.hideLoader(); + if (immediateLiveCareVM.patientHasPendingLiveCareRequest) { + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); + Navigator.of(context).push( CustomPageRoute( - page: LandingNavigation(), + page: ImmediateLiveCarePendingRequestPage(), ), - (r) => false); - Navigator.of(context).push( - CustomPageRoute( - page: ImmediateLiveCarePendingRequestPage(), - ), - ); + ); + } else { + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: LocaleKeys.unknownErrorOccurred.tr(context: context)), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } } else { showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), context, - child: Utils.getErrorWidget(loadingText: LocaleKeys.unknownErrorOccurred.tr(context: context)), + child: Utils.getWarningWidget( + loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + openAppSettings(); + }), callBackFunc: () {}, isFullScreen: false, isCloseButtonVisible: true, ); } - } else { - showCommonBottomSheetWithoutHeight( - title: LocaleKeys.notice.tr(context: context), - context, - child: Utils.getWarningWidget( - loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), - isShowActionButtons: true, - onCancelTap: () { - Navigator.pop(context); - }, - onConfirmTap: () async { - openAppSettings(); - }), - callBackFunc: () {}, - isFullScreen: false, - isCloseButtonVisible: true, - ); - } - }); + }); + } else { + showCommonBottomSheetWithoutHeight(context, child: PreferredConsultationLanguageSelect(immediateLiveCareViewModel: immediateLiveCareVM), callBackFunc: () async { + debugPrint("Selected language: ${immediateLiveCareVM.selectedConsultationLanguage}"); + if (immediateLiveCareVM.selectedConsultationLanguage != 0) { + await askVideoCallPermission(context).then((val) async { + if (val) { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.confirmingLiveCareRequest.tr(context: context)); + + await immediateLiveCareVM.addNewCallRequestForImmediateLiveCare("${appState.getAuthenticatedUser()!.patientId}${DateTime.now().millisecondsSinceEpoch}"); + await immediateLiveCareVM.getPatientLiveCareHistory(); + LoaderBottomSheet.hideLoader(); + if (immediateLiveCareVM.patientHasPendingLiveCareRequest) { + Navigator.pushAndRemoveUntil( + context, + CustomPageRoute( + page: LandingNavigation(), + ), + (r) => false); + Navigator.of(context).push( + CustomPageRoute( + page: ImmediateLiveCarePendingRequestPage(), + ), + ); + } else { + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: LocaleKeys.unknownErrorOccurred.tr(context: context)), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + } else { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.pop(context); + }, + onConfirmTap: () async { + openAppSettings(); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } + }); + } + }, title: LocaleKeys.preferredConsultationLanguage.tr(context: context), isCloseButtonVisible: true, isFullScreen: false); + } }, backgroundColor: AppColors.successColor, borderColor: AppColors.successColor, @@ -369,33 +470,68 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { : CustomButton( text: LocaleKeys.payNow.tr(context: context), onPressed: () async { - await askVideoCallPermission(context).then((val) { - if (val) { - Navigator.of(context).push( - CustomPageRoute( - page: ImmediateLiveCarePaymentPage(), - ), - ); - } - // else { - // showCommonBottomSheetWithoutHeight( - // title: LocaleKeys.notice.tr(context: context), - // context, - // child: Utils.getWarningWidget( - // loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), - // isShowActionButtons: true, - // onCancelTap: () { - // Navigator.pop(context); - // }, - // onConfirmTap: () async { - // openAppSettings(); - // }), - // callBackFunc: () {}, - // isFullScreen: false, - // isCloseButtonVisible: true, - // ); - // } - }); + if (immediateLiveCareVM.selectedConsultationLanguage != 0) { + await askVideoCallPermission(context).then((val) { + if (val) { + Navigator.of(context).push( + CustomPageRoute( + page: ImmediateLiveCarePaymentPage(), + ), + ); + } + // else { + // showCommonBottomSheetWithoutHeight( + // title: LocaleKeys.notice.tr(context: context), + // context, + // child: Utils.getWarningWidget( + // loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), + // isShowActionButtons: true, + // onCancelTap: () { + // Navigator.pop(context); + // }, + // onConfirmTap: () async { + // openAppSettings(); + // }), + // callBackFunc: () {}, + // isFullScreen: false, + // isCloseButtonVisible: true, + // ); + // } + }); + } else { + showCommonBottomSheetWithoutHeight(context, child: PreferredConsultationLanguageSelect(immediateLiveCareViewModel: immediateLiveCareVM), callBackFunc: () async { + debugPrint("Selected language: ${immediateLiveCareVM.selectedConsultationLanguage}"); + if (immediateLiveCareVM.selectedConsultationLanguage != 0) { + await askVideoCallPermission(context).then((val) { + if (val) { + Navigator.of(context).push( + CustomPageRoute( + page: ImmediateLiveCarePaymentPage(), + ), + ); + } + // else { + // showCommonBottomSheetWithoutHeight( + // title: LocaleKeys.notice.tr(context: context), + // context, + // child: Utils.getWarningWidget( + // loadingText: LocaleKeys.liveCarePermissionsMessage.tr(context: context), + // isShowActionButtons: true, + // onCancelTap: () { + // Navigator.pop(context); + // }, + // onConfirmTap: () async { + // openAppSettings(); + // }), + // callBackFunc: () {}, + // isFullScreen: false, + // isCloseButtonVisible: true, + // ); + // } + }); + } + }, title: LocaleKeys.preferredConsultationLanguage.tr(context: context), isCloseButtonVisible: true, isFullScreen: false); + } }, backgroundColor: AppColors.infoColor, borderColor: AppColors.infoColor, diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart index 9a1d1fd7..bbb634e8 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart @@ -12,14 +12,17 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/contact_us/contact_us_view_model.dart'; import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/livecare_reschedule_widget.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/countdown_timer.dart'; import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:video_player/video_player.dart'; class ImmediateLiveCarePendingRequestPage extends StatefulWidget { ImmediateLiveCarePendingRequestPage({super.key}); @@ -34,9 +37,35 @@ class _ImmediateLiveCarePendingRequestPageState extends State(); + return Column( + children: [ + checkInOptionCard( + AppAssets.liveCareRescheduleIcon, + "After 30 mins", + "You will be called by the doctor after 30 mins", + // "Call for immediate assistance", + ).onPress(() { + Navigator.of(context).pop(); + }), + SizedBox(height: 16.h), + checkInOptionCard( + AppAssets.liveCareRescheduleIcon, + "After 1 hour", + "You will be called by the doctor after 1 hour", + ).onPress(() async { + Navigator.of(context).pop(); + }), + SizedBox(height: 16.h), + ], + ); + } + + Widget checkInOptionCard(String icon, String title, String subTitle) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + title.toText16(isBold: true, color: AppColors.textColor), + subTitle.toText12(isBold: true, color: AppColors.greyTextColor), + ], + ), + ), + Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.blackColor, + width: 18.h, + height: 13.h, + fit: BoxFit.contain, + ), + ), + ], + ), + ], + ).paddingAll(16.h), + ); + } +} diff --git a/lib/presentation/book_appointment/livecare/widgets/livecare_support_widget.dart b/lib/presentation/book_appointment/livecare/widgets/livecare_support_widget.dart new file mode 100644 index 00000000..bea021a0 --- /dev/null +++ b/lib/presentation/book_appointment/livecare/widgets/livecare_support_widget.dart @@ -0,0 +1,96 @@ +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_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.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'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../../../generated/locale_keys.g.dart'; + +class LivecareSupportWidget extends StatelessWidget { + LivecareSupportWidget({super.key}); + + late AppState appState; + + @override + Widget build(BuildContext context) { + appState = getIt.get(); + return Column( + children: [ + checkInOptionCard( + AppAssets.call_fill, + LocaleKeys.liveCareSupportAssistance.tr(), + LocaleKeys.callForAssistance.tr(), + // "Call for immediate assistance", + ).onPress(() { + launchUrl(Uri.parse("tel://" + "+966 11 525 9553")); + }), + SizedBox(height: 16.h), + checkInOptionCard( + AppAssets.whatsapp, + LocaleKeys.liveCareSupportWhatsApp.tr(), + LocaleKeys.viewNearestHMGLocations.tr(), + ).onPress(() async { + final String url = "https://wa.me/+966553034949"; // Replace with your WhatsApp number + final Uri whatsappUri = Uri.parse(url); + + if (await canLaunchUrl(whatsappUri)) { + await launchUrl( + whatsappUri, + mode: LaunchMode.externalApplication, // Forces the OS to open the WhatsApp app + ); + } else { + // throw 'Could not launch WhatsApp. Ensure the app is installed.'; + } + }), + SizedBox(height: 16.h), + ], + ); + } + + Widget checkInOptionCard(String icon, String title, String subTitle) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Utils.buildSvgWithAssets(icon: icon, width: 24.h, height: 24.h, fit: BoxFit.fill, applyThemeColor: false), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + title.toText16(isBold: true, color: AppColors.textColor), + // subTitle.toText12(isBold: true, color: AppColors.greyTextColor), + ], + ), + ), + Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.blackColor, + width: 18.h, + height: 13.h, + fit: BoxFit.contain, + ), + ), + ], + ), + ], + ).paddingAll(16.h), + ); + } +} diff --git a/lib/presentation/book_appointment/livecare/widgets/preferred_consultation_language_select.dart b/lib/presentation/book_appointment/livecare/widgets/preferred_consultation_language_select.dart new file mode 100644 index 00000000..559ca159 --- /dev/null +++ b/lib/presentation/book_appointment/livecare/widgets/preferred_consultation_language_select.dart @@ -0,0 +1,89 @@ +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_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.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'; +import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; + +import '../../../../generated/locale_keys.g.dart'; + +class PreferredConsultationLanguageSelect extends StatelessWidget { + PreferredConsultationLanguageSelect({super.key, required this.immediateLiveCareViewModel}); + + late AppState appState; + ImmediateLiveCareViewModel immediateLiveCareViewModel; + + @override + Widget build(BuildContext context) { + appState = getIt.get(); + return Column( + children: [ + checkInOptionCard( + AppAssets.call_fill, + LocaleKeys.preferredConsultationLanguageAr.tr(), + LocaleKeys.callForAssistance.tr(), + // "Call for immediate assistance", + ).onPress(() { + immediateLiveCareViewModel.setSelectedConsultationLanguage(1); + Navigator.of(context).pop(); + }), + SizedBox(height: 16.h), + checkInOptionCard( + AppAssets.whatsapp, + LocaleKeys.preferredConsultationLanguageEn.tr(), + LocaleKeys.viewNearestHMGLocations.tr(), + ).onPress(() async { + immediateLiveCareViewModel.setSelectedConsultationLanguage(2); + Navigator.of(context).pop(); + }), + SizedBox(height: 16.h), + ], + ); + } + + Widget checkInOptionCard(String icon, String title, String subTitle) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Utils.buildSvgWithAssets(icon: icon, width: 24.h, height: 24.h, fit: BoxFit.fill, applyThemeColor: false), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + title.toText16(isBold: true, color: AppColors.textColor), + // subTitle.toText12(isBold: true, color: AppColors.greyTextColor), + ], + ), + ), + Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon_small, + iconColor: AppColors.blackColor, + width: 18.h, + height: 13.h, + fit: BoxFit.contain, + ), + ), + ], + ), + ], + ).paddingAll(16.h), + ); + } +} diff --git a/lib/widgets/appbar/collapsing_list_view.dart b/lib/widgets/appbar/collapsing_list_view.dart index c3ebe4ba..9b8110fe 100644 --- a/lib/widgets/appbar/collapsing_list_view.dart +++ b/lib/widgets/appbar/collapsing_list_view.dart @@ -29,6 +29,7 @@ class CollapsingListView extends StatelessWidget { VoidCallback? viewImage; VoidCallback? location; VoidCallback? downloadInvoice; + VoidCallback? liveCareSupport; Widget? bottomChild; Widget? trailing; bool isClose; @@ -55,6 +56,7 @@ class CollapsingListView extends StatelessWidget { this.viewImage, this.location, this.downloadInvoice, + this.liveCareSupport, this.isLeading = true, this.trailing, this.leadingCallback, @@ -101,6 +103,7 @@ class CollapsingListView extends StatelessWidget { viewImage: viewImage, location: location, downloadInvoice: downloadInvoice, + liveCareSupport: liveCareSupport, bottomChild: bottomChild, trailing: trailing, aiOverview: aiOverview, @@ -212,6 +215,7 @@ class ScrollAnimatedTitle extends StatefulWidget implements PreferredSizeWidget VoidCallback? sendEmail; VoidCallback? doctorResponse; VoidCallback? downloadReport; + VoidCallback? liveCareSupport; VoidCallback? viewImage; VoidCallback? location; VoidCallback? downloadInvoice; @@ -236,6 +240,7 @@ class ScrollAnimatedTitle extends StatefulWidget implements PreferredSizeWidget this.viewImage, this.location, this.downloadInvoice, + this.liveCareSupport, this.bottomChild, this.trailing, }); @@ -338,6 +343,7 @@ class _ScrollAnimatedTitleState extends State { if (widget.downloadInvoice != null) actionButton(context, t, title: LocaleKeys.downloadInvoice.tr(context: context), icon: AppAssets.download) .onPress(widget.downloadInvoice!), + if (widget.liveCareSupport != null) Utils.buildSvgWithAssets(icon: AppAssets.contact_icon).onPress(widget.liveCareSupport!), if (widget.trailing != null) widget.trailing!, ] ], diff --git a/pubspec.yaml b/pubspec.yaml index bdce8130..7da65440 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -110,6 +110,7 @@ dependencies: screen_brightness: ^1.0.1 flutter_screenshot_blocker: ^1.0.4 cloudflare_turnstile: ^3.7.2 + video_player: 2.10.1 dev_dependencies: flutter_test: