diff --git a/assets/images/png/home_health_care.png b/assets/images/png/home_health_care.png new file mode 100644 index 0000000..21378c4 Binary files /dev/null and b/assets/images/png/home_health_care.png differ diff --git a/assets/images/png/pharmacy_service.png b/assets/images/png/pharmacy_service.png new file mode 100644 index 0000000..7093d41 Binary files /dev/null and b/assets/images/png/pharmacy_service.png differ diff --git a/assets/images/svg/phramacy_icon.svg b/assets/images/svg/phramacy_icon.svg new file mode 100644 index 0000000..a9c5d1c --- /dev/null +++ b/assets/images/svg/phramacy_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index acfbbc0..9bab873 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -454,8 +454,6 @@ var GET_ANCILLARY_ORDERS_DETAILS = 'Services/Doctors.svc/REST/GetOnlineAncillary //Pharmacy wishlist // var GET_WISHLIST = "http://swd-pharapp-01:7200/api/shopping_cart_items/"; -var GET_DOCTOR_LIST_BY_TIME = "Services/Doctors.svc/REST/SearchDoctorsByTime"; - // pharmacy var PHARMACY_AUTORZIE_CUSTOMER = "AutorizeCustomer"; var PHARMACY_VERIFY_CUSTOMER = "VerifyCustomer"; @@ -553,7 +551,6 @@ var GET_FINAL_PRODUCTS = 'products?fields=id,reviews,discount_ids,name,namen,localized_names,display_order,short_description,full_description,full_descriptionn,sku,order_minimum_quantity,order_maximum_quantity,price,old_price,images,is_rx,rx_message,rx_messagen,discount_name,discount_namen,approved_rating_sum,approved_total_reviews,allow_back_in_stock_subscriptions,stock_quantity,stock_availability,stock_availabilityn,discount_percentage&CategoryId='; var GET_CLINIC_CATEGORY = 'Services/Doctors.svc/REST/DP_GetClinicCategory'; var GET_DISEASE_BY_CLINIC_ID = 'Services/Doctors.svc/REST/DP_GetDiseasesByClinicID'; -var SEARCH_DOCTOR_BY_TIME = 'Services/Doctors.svc/REST/SearchDoctorsByTime'; var TIMER_MIN = 10; @@ -703,7 +700,7 @@ var GET_PRESCRIPTION_INSTRUCTIONS_PDF = 'Services/ChatBot_Service.svc/REST/Chatb class ApiConsts { static const maxSmallScreen = 660; - static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; + static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat; // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index 49d14a4..bbe7d75 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -221,6 +221,7 @@ class AppAssets { static const String trade_down_yellow = '$svgBasePath/trade_down_yellow.svg'; static const String trade_down_red = '$svgBasePath/trade_down_red.svg'; + static const String pharmacy_icon = '$svgBasePath/phramacy_icon.svg'; //bottom navigation// static const String homeBottom = '$svgBasePath/home_bottom.svg'; @@ -249,6 +250,10 @@ class AppAssets { // PNGS // static const String hmgLogo = '$pngBasePath/hmg_logo.png'; static const String liveCareService = '$pngBasePath/livecare_service.png'; + + static const String homeHealthCareService = '$pngBasePath/home_health_care.png'; + static const String pharmacyService = '$pngBasePath/pharmacy_service.png'; + static const String maleImg = '$pngBasePath/male_img.png'; static const String femaleImg = '$pngBasePath/female_img.png'; static const String babyGirlImg = '$pngBasePath/baby_girl_img.png'; diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 397adad..38d04b9 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -925,4 +925,11 @@ class Utils { return ""; } + static bool isDateToday(DateTime dateToCheck) { + final DateTime now = DateTime.now(); + final DateTime today = DateTime(now.year, now.month, now.day); + final DateTime checkDate = DateTime(dateToCheck.year, dateToCheck.month, dateToCheck.day); + + return checkDate == today; + } } diff --git a/lib/features/hmg_services/hmg_services_view_model.dart b/lib/features/hmg_services/hmg_services_view_model.dart index 81cd060..b1a7757 100644 --- a/lib/features/hmg_services/hmg_services_view_model.dart +++ b/lib/features/hmg_services/hmg_services_view_model.dart @@ -3,8 +3,8 @@ import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart'; import 'package:hmg_patient_app_new/features/hmg_services/hmg_services_repo.dart'; -import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/create_e_referral_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/cmc_create_new_order_req_model.dart'; +import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/create_e_referral_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/order_update_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/search_e_referral_req_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/req_models/send_activation_code_ereferral_req_model.dart'; @@ -24,8 +24,9 @@ class HmgServicesViewModel extends ChangeNotifier { final BookAppointmentsRepo bookAppointmentsRepo; final ErrorHandlerService errorHandlerService; final NavigationService navigationService; - HmgServicesViewModel({required this.bookAppointmentsRepo, required this.hmgServicesRepo, required this.errorHandlerService, required this.navigationService}); + HmgServicesViewModel( + {required this.bookAppointmentsRepo, required this.hmgServicesRepo, required this.errorHandlerService, required this.navigationService}); bool isCmcOrdersLoading = false; bool isCmcServicesLoading = false; @@ -53,12 +54,12 @@ class HmgServicesViewModel extends ChangeNotifier { // HHC order creation state (no hospital selection needed for home healthcare) GetCMCServicesResponseModel? selectedServiceForHhcOrder; - - List relationTypes =[]; - List getAllCitiesList =[]; - List searchReferralList =[]; + List relationTypes = []; + List getAllCitiesList = []; + List searchReferralList = []; Future getOrdersList() async {} + // HHC multiple services selection List selectedHhcServices = []; @@ -332,10 +333,7 @@ class HmgServicesViewModel extends ChangeNotifier { await getAllHhcOrders(); } - Future getAllHhcOrders({ - Function(dynamic)? onSuccess, - Function(String)? onError, - }) async { + Future getAllHhcOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async { isHhcOrdersLoading = true; notifyListeners(); @@ -541,16 +539,14 @@ class HmgServicesViewModel extends ChangeNotifier { final result = await hmgServicesRepo.getRelationshipTypes(); result.fold( - (failure) async { - + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { - + (apiResponse) { if (apiResponse.messageStatus == 1) { relationTypes = apiResponse.data ?? []; notifyListeners(); @@ -567,7 +563,6 @@ class HmgServicesViewModel extends ChangeNotifier { ); } - Future getAllCities({ Function(dynamic)? onSuccess, Function(String)? onError, @@ -576,16 +571,14 @@ class HmgServicesViewModel extends ChangeNotifier { final result = await hmgServicesRepo.getAllCities(); result.fold( - (failure) async { - + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { - + (apiResponse) { if (apiResponse.messageStatus == 1) { getAllCitiesList = apiResponse.data ?? []; notifyListeners(); @@ -607,22 +600,20 @@ class HmgServicesViewModel extends ChangeNotifier { Function(GenericApiModel)? onSuccess, Function(String)? onError, }) async { - notifyListeners(); final result = await hmgServicesRepo.sendEReferralActivationCode(requestModel); result.fold( - (failure) async { + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { + (apiResponse) { if (apiResponse.messageStatus == 1) { - notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -642,22 +633,20 @@ class HmgServicesViewModel extends ChangeNotifier { Function(GenericApiModel)? onSuccess, Function(String)? onError, }) async { - notifyListeners(); final result = await hmgServicesRepo.checkEReferralActivationCode(requestModel); result.fold( - (failure) async { + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { + (apiResponse) { if (apiResponse.messageStatus == 1) { - notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -672,28 +661,25 @@ class HmgServicesViewModel extends ChangeNotifier { ); } - Future createEReferral({ required CreateEReferralRequestModel requestModel, Function(GenericApiModel)? onSuccess, Function(String)? onError, }) async { - notifyListeners(); final result = await hmgServicesRepo.createEReferral(requestModel); result.fold( - (failure) async { + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { + (apiResponse) { if (apiResponse.messageStatus == 1) { - notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); @@ -708,29 +694,24 @@ class HmgServicesViewModel extends ChangeNotifier { ); } - - Future searchEReferral({ required SearchEReferralRequestModel requestModel, Function(dynamic)? onSuccess, Function(String)? onError, }) async { - notifyListeners(); final result = await hmgServicesRepo.searchEReferral(requestModel); result.fold( - (failure) async { - + (failure) async { notifyListeners(); await errorHandlerService.handleError(failure: failure); if (onError != null) { onError(failure.toString()); } }, - (apiResponse) { - + (apiResponse) { if (apiResponse.messageStatus == 1) { searchReferralList = apiResponse.data ?? []; notifyListeners(); @@ -747,28 +728,26 @@ class HmgServicesViewModel extends ChangeNotifier { ); } - Future navigateToOTPScreen( - {required OTPTypeEnum otpTypeEnum, - required String phoneNumber, - required String loginToken, - required Function onSuccess, - }) async { - + Future navigateToOTPScreen({ + required OTPTypeEnum otpTypeEnum, + required String phoneNumber, + required String loginToken, + required Function onSuccess, + }) async { navigationService.pushToOtpScreen( phoneNumber: phoneNumber, isFormFamilyFile: false, checkActivationCode: (int activationCode) async { - checkEReferralActivationCode( requestModel: CheckActivationCodeForEReferralRequestModel( logInTokenID: loginToken, activationCode: activationCode.toString(), ), onSuccess: (GenericApiModel response) { - onSuccess(); + onSuccess(); }, onError: (String errorMessage) { - print(errorMessage); + print(errorMessage); }, ); }, @@ -787,5 +766,4 @@ class HmgServicesViewModel extends ChangeNotifier { }, ); } - } diff --git a/lib/features/location/location_view_model.dart b/lib/features/location/location_view_model.dart index c6ea34e..76d7c2c 100644 --- a/lib/features/location/location_view_model.dart +++ b/lib/features/location/location_view_model.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart' show ChangeNotifier; import 'package:flutter/material.dart'; -import 'package:google_maps_flutter_platform_interface/src/types/camera.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices; 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/features/location/GeocodeResponse.dart'; @@ -10,9 +10,6 @@ import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart'; import 'package:hmg_patient_app_new/features/location/location_repo.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; import 'package:huawei_map/huawei_map.dart' as HMSCameraServices; -import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices; - - import 'PlacePrediction.dart'; @@ -20,12 +17,12 @@ class LocationViewModel extends ChangeNotifier { final LocationRepo locationRepo; final ErrorHandlerService errorHandlerService; - LocationViewModel({required this.locationRepo, required this.errorHandlerService}){ + LocationViewModel({required this.locationRepo, required this.errorHandlerService}) { placeValueInController(); } - List predictions = []; - PlacePrediction? selectedPrediction; + List predictions = []; + PlacePrediction? selectedPrediction; bool isPredictionLoading = false; GeocodeResponse? geocodeResponse; PlaceDetails? placeDetails; @@ -39,12 +36,11 @@ class LocationViewModel extends ChangeNotifier { return HMSCameraServices.CameraPosition(target: HMSCameraServices.LatLng(getIt().userLat, getIt().userLong), zoom: 18); } - GMSMapServices.CameraPosition getGMSLocation() { return GMSMapServices.CameraPosition(target: GMSMapServices.LatLng(getIt().userLat, getIt().userLong), zoom: 18); } - void placeValueInController() async{ + void placeValueInController() async { if (await getIt().isGMSAvailable) { gmsController = Completer(); } else { @@ -54,14 +50,14 @@ class LocationViewModel extends ChangeNotifier { FutureOr getPlacesPrediction(String input) async { predictions = []; - isPredictionLoading= true; + isPredictionLoading = true; final result = await locationRepo.getPlacePredictionsAsInput(input); result.fold( (failure) { errorHandlerService.handleError(failure: failure); }, (apiModel) { - predictions = apiModel.data??[]; + predictions = apiModel.data ?? []; }, ); isPredictionLoading = false; @@ -99,21 +95,20 @@ class LocationViewModel extends ChangeNotifier { handleGMSMapCameraMoved(GMSMapServices.CameraPosition value) { mapCapturedLocation = Location(lat: value.target.latitude, lng: value.target.longitude); - } handleHMSMapCameraMoved(HMSCameraServices.CameraPosition value) { mapCapturedLocation = Location(lat: value.target.lat, lng: value.target.lng); } - handleOnCameraIdle(){ - if(mapCapturedLocation != null) { + handleOnCameraIdle() { + if (mapCapturedLocation != null) { getPlaceEncodedData(mapCapturedLocation!.lat, mapCapturedLocation!.lng); } } void updateSearchQuery(String? value) { - if(value == null || value.isEmpty){ + if (value == null || value.isEmpty) { predictions = []; return; } @@ -123,16 +118,16 @@ class LocationViewModel extends ChangeNotifier { void flushSearchPredictions() { predictions = []; - mapCapturedLocation= null; - placeDetails= null; - geocodeResponse= null; - selectedPrediction= null; + mapCapturedLocation = null; + placeDetails = null; + geocodeResponse = null; + selectedPrediction = null; notifyListeners(); } - FutureOr selectPlacePrediction(PlacePrediction placePrediction) async{ - selectedPrediction= placePrediction; + FutureOr selectPlacePrediction(PlacePrediction placePrediction) async { + selectedPrediction = placePrediction; await getPlaceDetails(placePrediction.placeID); } @@ -141,8 +136,6 @@ class LocationViewModel extends ChangeNotifier { } void moveController(Location location) { - print("moving to location"); - print("gmsController is null or not $gmsController"); if (getIt().isGMSAvailable) { gmsController?.future.then((controller) { controller.animateCamera( @@ -169,4 +162,4 @@ class LocationViewModel extends ChangeNotifier { }); } } -} \ No newline at end of file +} diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index 0653495..d077970 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/appointemnet_filters.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/ask_doctor_request_type_response_model.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/get_tamara_installments_details_response_model.dart'; @@ -226,7 +227,10 @@ class MyAppointmentsViewModel extends ChangeNotifier { filteredAppointmentList.addAll(patientAppointmentsHistoryList); if (patientArrivedAppointmentsHistoryList.isNotEmpty) { - getPatientAppointmentQueueDetails(appointmentNo: patientArrivedAppointmentsHistoryList.first.appointmentNo, patientID: patientArrivedAppointmentsHistoryList.first.patientID); + if (Utils.isDateToday(DateUtil.convertStringToDate(patientArrivedAppointmentsHistoryList.first.appointmentDate))) { + // getPatientAppointmentQueueDetails(appointmentNo: patientArrivedAppointmentsHistoryList.first.appointmentNo, patientID: patientArrivedAppointmentsHistoryList.first.patientID); + getPatientAppointmentQueueDetails(); + } } print('Upcoming Appointments: ${patientUpcomingAppointmentsHistoryList.length}'); @@ -670,10 +674,11 @@ class MyAppointmentsViewModel extends ChangeNotifier { ); } - Future getPatientAppointmentQueueDetails({required int appointmentNo, required int patientID, Function(dynamic)? onSuccess, Function(String)? onError}) async { + Future getPatientAppointmentQueueDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { isAppointmentQueueDetailsLoading = true; notifyListeners(); - final result = await myAppointmentsRepo.getPatientAppointmentQueueDetails(appointmentNo: appointmentNo, patientID: patientID); + final result = await myAppointmentsRepo.getPatientAppointmentQueueDetails( + appointmentNo: patientArrivedAppointmentsHistoryList.first.appointmentNo, patientID: patientArrivedAppointmentsHistoryList.first.patientID); isAppointmentQueueDetailsLoading = false; @@ -692,7 +697,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { isPatientHasQueueAppointment = true; patientQueueDetailsList = apiResponse.data!; for (var element in patientQueueDetailsList) { - if (element.patientID == patientID) { + if (element.patientID == patientArrivedAppointmentsHistoryList.first.patientID) { currentPatientQueueDetails = element; currentQueueStatus = element.callType!; // currentQueueStatus = 2; @@ -701,7 +706,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { } // patientQueueDetailsList.first.callType = 1; - patientQueueDetailsList.removeWhere((element) => element.patientID == patientID); + patientQueueDetailsList.removeWhere((element) => element.patientID == patientArrivedAppointmentsHistoryList.first.patientID); } else { isPatientHasQueueAppointment = false; } diff --git a/lib/presentation/appointments/appointment_queue_page.dart b/lib/presentation/appointments/appointment_queue_page.dart index d8acac6..4554873 100644 --- a/lib/presentation/appointments/appointment_queue_page.dart +++ b/lib/presentation/appointments/appointment_queue_page.dart @@ -114,7 +114,7 @@ class AppointmentQueuePage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - "IMD W-A-2".needTranslation.toText17(isBold: true), + myAppointmentsVM.patientQueueDetailsList[index].queueNo!.toText17(isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index cd1cec8..a35c1ca 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -188,13 +188,14 @@ class AppointmentCard extends StatelessWidget { ? 'Cardiology' : "${DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)} ${DateUtil.formatDateToTimeLang(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate), false)}", ).toShimmer2(isShow: isLoading), - AppCustomChipWidget( - labelPadding: EdgeInsetsDirectional.only(start: -2.w, end: 6.w), - isIconPNG: true, - icon: getIt.get().getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, - iconSize: 18.h, - labelText: isLoading ? 'Cardiology' : "Patient: ${getIt.get().getAuthenticatedUser()!.firstName!}", - ).toShimmer2(isShow: isLoading), + + // AppCustomChipWidget( + // labelPadding: EdgeInsetsDirectional.only(start: -2.w, end: 6.w), + // isIconPNG: true, + // icon: getIt.get().getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, + // iconSize: 18.h, + // labelText: isLoading ? 'Cardiology' : "Patient: ${getIt.get().getAuthenticatedUser()!.firstName!}", + // ).toShimmer2(isShow: isLoading), // if (!isFromMedicalReport) // AppCustomChipWidget( // icon: AppAssets.appointment_time_icon, diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index 1fbd22e..5b1d1cd 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -149,7 +149,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { onSuccess: (apiResponse) { LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () async { - await myAppointmentsViewModel.getPatientAppointmentQueueDetails(appointmentNo: patientAppointmentHistoryResponseModel.appointmentNo, patientID: patientAppointmentHistoryResponseModel.patientID); + await myAppointmentsViewModel.getPatientAppointmentQueueDetails(); Navigator.of(context).pop(); Navigator.pushAndRemoveUntil( context, diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 4d24da7..5aa1b7c 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -54,7 +54,7 @@ class _BookAppointmentPageState extends State { void initState() { authVM = context.read(); scheduleMicrotask(() { - bookAppointmentsViewModel.selectedTabIndex = 0; + // bookAppointmentsViewModel.selectedTabIndex = 0; bookAppointmentsViewModel.initBookAppointmentViewModel(); bookAppointmentsViewModel.getLocation(); immediateLiveCareViewModel.initImmediateLiveCare(); @@ -68,6 +68,7 @@ class _BookAppointmentPageState extends State { immediateLiveCareViewModel = Provider.of(context, listen: false); appState = getIt.get(); regionalViewModel = Provider.of(context, listen: true); + getSelectedTabData(bookAppointmentsViewModel.selectedTabIndex); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: Column( @@ -85,6 +86,7 @@ class _BookAppointmentPageState extends State { CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), + initialIndex: bookAppointmentsVM.selectedTabIndex, tabs: [ CustomTabBarModel(null, "General".needTranslation), CustomTabBarModel(null, "LiveCare".needTranslation), @@ -323,10 +325,12 @@ class _BookAppointmentPageState extends State { ).paddingSymmetrical(24.h, 0.h); case 1: //TODO: Get LiveCare type Select UI from Hussain - return appState.isAuthenticated - ? Column( - children: [ - Container( + return + // appState.isAuthenticated + // ? + Column( + children: [ + Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor, borderRadius: 24.h, @@ -445,7 +449,8 @@ class _BookAppointmentPageState extends State { ), ], ).paddingSymmetrical(24.h, 0.h) - : getLiveCareNotLoggedInUI(); + // : getLiveCareNotLoggedInUI() + ; default: SizedBox.shrink(); } diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index d0bd740..df2f85a 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -212,7 +212,9 @@ class _SelectClinicPageState extends State { CustomPageRoute( page: SelectLivecareClinicPage(onNegativeClicked: (){ handleDoctorScreen(clinic); - },), + }, + selectedClinic: clinic, + ), ), ); } else { diff --git a/lib/presentation/book_appointment/select_livecare_clinic_page.dart b/lib/presentation/book_appointment/select_livecare_clinic_page.dart index 719452d..2362617 100644 --- a/lib/presentation/book_appointment/select_livecare_clinic_page.dart +++ b/lib/presentation/book_appointment/select_livecare_clinic_page.dart @@ -1,22 +1,37 @@ 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/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/book_appointments/models/resp_models/get_clinic_list_response_model.dart'; +import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart'; +import 'package:hmg_patient_app_new/features/immediate_livecare/models/resp_models/get_livecare_immediate_clinics_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_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/loader/bottomsheet_loader.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:provider/provider.dart'; class SelectLivecareClinicPage extends StatelessWidget { final VoidCallback? onNegativeClicked; - const SelectLivecareClinicPage({super.key, this.onNegativeClicked}); + late GetClinicsListResponseModel selectedClinic; + + SelectLivecareClinicPage({super.key, this.onNegativeClicked, required this.selectedClinic}); + + late ImmediateLiveCareViewModel immediateLiveCareViewModel; @override Widget build(BuildContext context) { + immediateLiveCareViewModel = Provider.of(context, listen: false); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: Column( @@ -103,7 +118,36 @@ class SelectLivecareClinicPage extends StatelessWidget { children: [ CustomButton( text: "Yes please, I am in a hurry".needTranslation, - onPressed: () {}, + onPressed: () async { + Navigator.pop(context); + GetLiveCareClinicListResponseModel liveCareClinic = GetLiveCareClinicListResponseModel( + iD: selectedClinic.liveCareClinicID, + serviceID: selectedClinic.liveCareServiceID, + serviceName: selectedClinic.clinicDescription, + serviceNameN: selectedClinic.clinicDescriptionN, + ); + + immediateLiveCareViewModel.setLiveCareSelectedCallType(1); + immediateLiveCareViewModel.setImmediateLiveCareSelectedClinic(liveCareClinic); + LoaderBottomSheet.showLoader(loadingText: "Fetching fees, Please wait...".needTranslation); + await immediateLiveCareViewModel.getLiveCareImmediateAppointmentFees(onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + Navigator.of(getIt.get().navigatorKey.currentContext!).push( + CustomPageRoute( + page: ImmediateLiveCarePaymentDetails(), + ), + ); + }, onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor, diff --git a/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart b/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart index 3be209b..18b656c 100644 --- a/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart +++ b/lib/presentation/comprehensive_checkup/cmc_selection_review_page.dart @@ -170,8 +170,6 @@ class _CmcSelectionReviewPageState extends State { latitude: double.parse(lat), longitude: double.parse(lng), address: hospitalName, - title: "Hospital Location".needTranslation, - showTitle: false, showAddress: false, padding: EdgeInsets.zero, onDirectionsTap: () => _launchDirections(selectedHospital), diff --git a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart index 5529b93..8b9ad89 100644 --- a/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart +++ b/lib/presentation/comprehensive_checkup/comprehensive_checkup_page.dart @@ -366,7 +366,12 @@ class _ComprehensiveCheckupPageState extends State { if (pendingOrder == null && _selectedServiceId != null) { return SafeArea( top: false, - child: Padding( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 12.h), child: CustomButton( borderWidth: 0, diff --git a/lib/presentation/health_calculators/health_calculator_result.dart b/lib/presentation/health_calculators/health_calculator_result.dart index 5abe410..a0a46ae 100644 --- a/lib/presentation/health_calculators/health_calculator_result.dart +++ b/lib/presentation/health_calculators/health_calculator_result.dart @@ -1,15 +1,23 @@ 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/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.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/book_appointments/book_appointments_view_model.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_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:provider/provider.dart'; + +import '../../widgets/common_bottom_sheet.dart'; class HealthCalculatorResultPage extends StatelessWidget { HealthCalculatorsTypeEnum calculatorType; @@ -26,7 +34,15 @@ class HealthCalculatorResultPage extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 20.h), child: CustomButton( text: LocaleKeys.bookAppo.tr(), - onPressed: () {}, + onPressed: () { + // Navigate to booking page + var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; + openRegionListBottomSheet(context, bottomSheetType); + getIt.get().setSelectedClinic( + GetClinicsListResponseModel(clinicID: 108, clinicDescription: "Bariatics", clinicDescriptionN: "Bariatics"), + ); + getIt.get().setIsDoctorsListLoading(true); + }, icon: null, fontSize: 16.f, backgroundColor: AppColors.primaryRedColor, @@ -38,6 +54,19 @@ class HealthCalculatorResultPage extends StatelessWidget { ); } + void openRegionListBottomSheet(BuildContext context, RegionBottomSheetType type) { + getIt.get().setProjectID(null); + + getIt.get().flush(); + getIt.get().setBottomSheetType(type); + showCommonBottomSheetWithoutHeight(context, + title: "", + titleWidget: Consumer(builder: (_, data, __) => LocaleKeys.selectRegion.tr().toText20(weight: FontWeight.w600)), + isDismissible: false, child: Consumer(builder: (_, data, __) { + return RegionBottomSheetBody(); + }), callBackFunc: () {}); + } + Widget getCalculatorResultWidget({required HealthCalculatorsTypeEnum type, dynamic calculatedResult}) { switch (calculatorType) { case HealthCalculatorsTypeEnum.bmi: diff --git a/lib/presentation/hmg_services/services_page.dart b/lib/presentation/hmg_services/services_page.dart index 001af4c..b321ff3 100644 --- a/lib/presentation/hmg_services/services_page.dart +++ b/lib/presentation/hmg_services/services_page.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:get_it/get_it.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; @@ -17,6 +18,8 @@ import 'package:hmg_patient_app_new/presentation/contact_us/contact_us.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/habib_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/recharge_wallet_page.dart'; import 'package:hmg_patient_app_new/presentation/hmg_services/services_view.dart'; +import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart'; +import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -95,15 +98,15 @@ class ServicesPage extends StatelessWidget { LoaderBottomSheet.hideLoader(); }); }), - HmgServicesComponentModel( - 3, - "Home Health Care".needTranslation, - "".needTranslation, - AppAssets.homeBottom, - bgColor: AppColors.primaryRedColor, - true, - route: AppRoutes.homeHealthCarePage, - ), + // HmgServicesComponentModel( + // 3, + // "Home Health Care".needTranslation, + // "".needTranslation, + // AppAssets.homeBottom, + // bgColor: AppColors.primaryRedColor, + // true, + // route: AppRoutes.homeHealthCarePage, + // ), // HmgServicesComponentModel( // 11, // "Virtual Tour".needTranslation, @@ -155,8 +158,8 @@ class ServicesPage extends StatelessWidget { AppAssets.smartwatch_icon, bgColor: AppColors.whiteColor, true, - // route: AppRoutes.smartWatches, - route: AppRoutes.huaweiHealthExample, + route: AppRoutes.smartWatches, + // route: AppRoutes.huaweiHealthExample, ), ]; @@ -169,331 +172,359 @@ class ServicesPage extends StatelessWidget { body: CollapsingListView( title: "Explore Services".needTranslation, isLeading: false, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 16.h), - "Medical & Care Services".needTranslation.toText18(isBold: true), - SizedBox(height: 16.h), - GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: (isFoldable || isTablet) ? 6 : 4, // 4 icons per row - crossAxisSpacing: 12.w, - mainAxisSpacing: 18.h, - childAspectRatio: 0.8, - ), - physics: NeverScrollableScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + "Medical & Care Services".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0), + SizedBox(height: 16.h), + GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: (isFoldable || isTablet) ? 6 : 4, // 4 icons per row + crossAxisSpacing: 12.w, + mainAxisSpacing: 18.h, + childAspectRatio: 0.8, + ), + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: hmgServices.length, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext context, int index) { + return ServiceGridViewItem(hmgServices[index], index, false, isHealthToolIcon: false); + }, + ).paddingSymmetrical(24.w, 0), + SizedBox(height: 24.h), + "HMG Services".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0), + SizedBox(height: 16.h), + SizedBox( + height: 350.h, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: LandingPageData.getServiceCardsList.length, shrinkWrap: true, - itemCount: hmgServices.length, - padding: EdgeInsets.zero, - itemBuilder: (BuildContext context, int index) { - return ServiceGridViewItem(hmgServices[index], index, false, isHealthToolIcon: false); + padding: EdgeInsets.symmetric(horizontal: 24.w), + itemBuilder: (context, index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + horizontalOffset: 100.0, + child: FadeInAnimation( + child: LargeServiceCard( + serviceCardData: LandingPageData.getServiceCardsList[index], + image: LandingPageData.getServiceCardsList[index].icon, + title: LandingPageData.getServiceCardsList[index].title, + subtitle: LandingPageData.getServiceCardsList[index].subtitle, + icon: LandingPageData.getServiceCardsList[index].largeCardIcon, + ), + ), + ), + ); }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 16.w), ), - SizedBox(height: 24.h), - "Personal Services".needTranslation.toText18(isBold: true), - SizedBox(height: 16.h), - Row( - children: [ - Expanded( - child: Container( - height: 170.h, - padding: EdgeInsets.all(16.w), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 20.r, - hasShadow: false, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - spacing: 8.w, - crossAxisAlignment: CrossAxisAlignment.center, + ), + SizedBox(height: 24.h), + "Personal Services".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0), + SizedBox(height: 16.h), + Row( + children: [ + Expanded( + child: Container( + height: 170.h, + padding: EdgeInsets.all(16.w), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + spacing: 8.w, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 30.w, height: 30.h), + "Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, + Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), + ], + ), + Spacer(), + Consumer(builder: (context, habibWalletVM, child) { + return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false) + .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h); + }), + Spacer(), + CustomButton( + height: 40.h, + icon: AppAssets.recharge_icon, + iconSize: 16.w, + iconColor: AppColors.infoColor, + textColor: AppColors.infoColor, + text: "Recharge".needTranslation, + borderWidth: 0.w, + fontWeight: FontWeight.w500, + borderColor: Colors.transparent, + backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), + padding: EdgeInsets.all(8.w), + fontSize: 12.f, + onPressed: () { + Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); + }, + ), + ], + ).onPress(() { + Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage())); + }), + ), + ), + SizedBox(width: 16.w), + Expanded( + child: Container( + height: 170.h, + padding: EdgeInsets.all(16.w), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.r, + hasShadow: false, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + spacing: 8.w, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.services_medical_file_icon, width: 30.w, height: 30.h), + "Medical Files".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, + Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), + ], + ), + Spacer(), + Wrap( + spacing: -8.h, + // runSpacing: 0.h, + children: [ + Utils.buildImgWithAssets( + icon: AppAssets.babyGirlImg, + height: 28.h, + width: 28.w, + border: 1, + fit: BoxFit.contain, + borderRadius: 50.r, + ), + Utils.buildImgWithAssets( + icon: AppAssets.femaleImg, + height: 28.h, + width: 28.w, + border: 1, + borderRadius: 50.r, + fit: BoxFit.contain, + ), + Utils.buildImgWithAssets( + icon: AppAssets.maleImg, + height: 28.h, + width: 28.w, + border: 1, + borderRadius: 50.r, + fit: BoxFit.contain, + ), + ], + ), + Spacer(), + CustomButton( + height: 40.h, + icon: AppAssets.add_icon, + iconSize: 16.w, + iconColor: AppColors.primaryRedColor, + textColor: AppColors.primaryRedColor, + text: "Add Member".needTranslation, + borderWidth: 0.w, + fontWeight: FontWeight.w500, + borderColor: Colors.transparent, + backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08), + padding: EdgeInsets.all(8.w), + fontSize: 12.f, + onPressed: () { + DialogService dialogService = getIt.get(); + medicalFileViewModel.clearAuthValues(); + dialogService.showAddFamilyFileSheet( + label: "Add Family Member".needTranslation, + message: "Please fill the below field to add a new family member to your profile".needTranslation, + onVerificationPress: () { + medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); + }); + }, + ), + ], + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: MedicalFilePage(), + ), + ); + }), + ), + ), + ], + ).paddingSymmetrical(24.w, 0), + SizedBox(height: 24.h), + "Health Tools".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0), + SizedBox(height: 16.h), + GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount:(isFoldable || isTablet) ? 6 : 4, // 4 icons per row + crossAxisSpacing: 12.w, + mainAxisSpacing: 18.h, + childAspectRatio: 0.8, + ), + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: hmgHealthToolServices.length, + padding: EdgeInsets.zero, + itemBuilder: (BuildContext context, int index) { + return ServiceGridViewItem( + hmgHealthToolServices[index], + index, + false, + isHealthToolIcon: true, + ); + }, + ).paddingSymmetrical(24.w, 0), + SizedBox(height: 24.h), + "Support Services".needTranslation.toText18(isBold: true).paddingSymmetrical(24.w, 0), + SizedBox(height: 16.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( children: [ - Utils.buildSvgWithAssets(icon: AppAssets.wallet, width: 30.w, height: 30.h), - "Habib Wallet".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, - Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), + Utils.buildSvgWithAssets( + icon: AppAssets.virtual_tour_icon, + width: 32.w, + height: 32.h, + fit: BoxFit.contain, + ), + SizedBox(width: 8.w), + "Virtual Tour".needTranslation.toText12(fontWeight: FontWeight.w500) ], ), - Spacer(), - Consumer(builder: (context, habibWalletVM, child) { - return Utils.getPaymentAmountWithSymbol2(habibWalletVM.habibWalletAmount, isExpanded: false) - .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h); - }), - Spacer(), - CustomButton( - height: 40.h, - icon: AppAssets.recharge_icon, - iconSize: 16.w, - iconColor: AppColors.infoColor, - textColor: AppColors.infoColor, - text: "Recharge".needTranslation, - borderWidth: 0.w, - fontWeight: FontWeight.w500, - borderColor: Colors.transparent, - backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08), - padding: EdgeInsets.all(8.w), - fontSize: 12.f, - onPressed: () { - Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); - }, - ), - ], + ), ).onPress(() { - Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage())); + Utils.openWebView( + url: 'https://hmgwebservices.com/vt_mobile/html/index.html', + ); }), ), - ), - SizedBox(width: 16.w), - Expanded( - child: Container( - height: 170.h, - padding: EdgeInsets.all(16.w), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 20.r, - hasShadow: false, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - spacing: 8.w, - crossAxisAlignment: CrossAxisAlignment.center, + SizedBox(width: 16.w), + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( children: [ - Utils.buildSvgWithAssets(icon: AppAssets.services_medical_file_icon, width: 30.w, height: 30.h), - "Medical Files".needTranslation.toText14(weight: FontWeight.w600, maxlines: 2).expanded, - Utils.buildSvgWithAssets(icon: AppAssets.arrow_forward), + Utils.buildSvgWithAssets( + icon: AppAssets.car_parking_icon, + width: 32.w, + height: 32.h, + fit: BoxFit.contain, + ), + SizedBox(width: 8.w), + "Car Parking".needTranslation.toText12(fontWeight: FontWeight.w500) ], ), - Spacer(), - Wrap( - spacing: -8.h, - // runSpacing: 0.h, + ), + ), + ), + ], + ), + SizedBox(height: 16.h), + Row( + children: [ + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( children: [ - Utils.buildImgWithAssets( - icon: AppAssets.babyGirlImg, - height: 28.h, - width: 28.w, - border: 1, - fit: BoxFit.contain, - borderRadius: 50.r, - ), - Utils.buildImgWithAssets( - icon: AppAssets.femaleImg, - height: 28.h, - width: 28.w, - border: 1, - borderRadius: 50.r, - fit: BoxFit.contain, - ), - Utils.buildImgWithAssets( - icon: AppAssets.maleImg, - height: 28.h, - width: 28.w, - border: 1, - borderRadius: 50.r, + Utils.buildSvgWithAssets( + icon: AppAssets.latest_news_icon, + width: 32.w, + height: 32.h, fit: BoxFit.contain, ), + SizedBox(width: 8.w), + "Latest News".needTranslation.toText12(fontWeight: FontWeight.w500) ], ), - Spacer(), - CustomButton( - height: 40.h, - icon: AppAssets.add_icon, - iconSize: 16.w, - iconColor: AppColors.primaryRedColor, - textColor: AppColors.primaryRedColor, - text: "Add Member".needTranslation, - borderWidth: 0.w, - fontWeight: FontWeight.w500, - borderColor: Colors.transparent, - backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.08), - padding: EdgeInsets.all(8.w), - fontSize: 12.f, - onPressed: () { - DialogService dialogService = getIt.get(); - medicalFileViewModel.clearAuthValues(); - dialogService.showAddFamilyFileSheet( - label: "Add Family Member".needTranslation, - message: "Please fill the below field to add a new family member to your profile".needTranslation, - onVerificationPress: () { - medicalFileViewModel.addFamilyFile(otpTypeEnum: OTPTypeEnum.sms); - }); - }, - ), - ], + ), ).onPress(() { - Navigator.of(context).push( - CustomPageRoute( - page: MedicalFilePage(), - ), + Utils.openWebView( + url: 'https://x.com/HMG', ); }), ), - ), - ], - ), - SizedBox(height: 24.h), - "Health Tools".needTranslation.toText18(isBold: true), - SizedBox(height: 16.h), - GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount:(isFoldable || isTablet) ? 6 : 4, // 4 icons per row - crossAxisSpacing: 12.w, - mainAxisSpacing: 18.h, - childAspectRatio: 0.8, - ), - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: hmgHealthToolServices.length, - padding: EdgeInsets.zero, - itemBuilder: (BuildContext context, int index) { - return ServiceGridViewItem( - hmgHealthToolServices[index], - index, - false, - isHealthToolIcon: true, - ); - }, - ), - SizedBox(height: 24.h), - "Support Services".needTranslation.toText18(isBold: true), - SizedBox(height: 16.h), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 12.h, - hasShadow: false, - ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Row( - children: [ - Utils.buildSvgWithAssets( - icon: AppAssets.virtual_tour_icon, - width: 32.w, - height: 32.h, - fit: BoxFit.contain, - ), - SizedBox(width: 8.w), - "Virtual Tour".needTranslation.toText12(fontWeight: FontWeight.w500) - ], - ), - ), - ).onPress(() { - Utils.openWebView( - url: 'https://hmgwebservices.com/vt_mobile/html/index.html', - ); - }), - ), - SizedBox(width: 16.w), - Expanded( - child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 12.h, - hasShadow: false, - ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Row( - children: [ - Utils.buildSvgWithAssets( - icon: AppAssets.car_parking_icon, - width: 32.w, - height: 32.h, - fit: BoxFit.contain, - ), - SizedBox(width: 8.w), - "Car Parking".needTranslation.toText12(fontWeight: FontWeight.w500) - ], - ), - ), + SizedBox(width: 16.w), + Expanded( + child: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 12.h, + hasShadow: false, ), - ), - ], - ), - SizedBox(height: 16.h), - Row( - children: [ - Expanded( - child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 12.h, - hasShadow: false, - ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Row( - children: [ - Utils.buildSvgWithAssets( - icon: AppAssets.latest_news_icon, - width: 32.w, - height: 32.h, - fit: BoxFit.contain, - ), - SizedBox(width: 8.w), - "Latest News".needTranslation.toText12(fontWeight: FontWeight.w500) - ], - ), - ), - ).onPress(() { - Utils.openWebView( - url: 'https://x.com/HMG', - ); - }), - ), - SizedBox(width: 16.w), - Expanded( - child: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 12.h, - hasShadow: false, - ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Row( - children: [ - Utils.buildSvgWithAssets( - icon: AppAssets.hmg_contact_icon, - width: 32.w, - height: 32.h, - fit: BoxFit.contain, - ), - SizedBox(width: 8.w), - "HMG Contact".needTranslation.toText12(fontWeight: FontWeight.w500) - ], - ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Row( + children: [ + Utils.buildSvgWithAssets( + icon: AppAssets.hmg_contact_icon, + width: 32.w, + height: 32.h, + fit: BoxFit.contain, + ), + SizedBox(width: 8.w), + "HMG Contact".needTranslation.toText12(fontWeight: FontWeight.w500) + ], ), - ).onPress(() { - showCommonBottomSheetWithoutHeight( - context, - title: LocaleKeys.contactUs.tr(), - child: ContactUs(), - callBackFunc: () {}, - isFullScreen: false, - ); - }), - ) - ], - ) - ], - ), - SizedBox(height: 24.h), - ], - ), + ), + ).onPress(() { + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.contactUs.tr(), + child: ContactUs(), + callBackFunc: () {}, + isFullScreen: false, + ); + }), + ) + ], + ) + ], + ).paddingSymmetrical(24.w, 0), + SizedBox(height: 24.h), + ], ), ), ); diff --git a/lib/presentation/home/data/landing_page_data.dart b/lib/presentation/home/data/landing_page_data.dart index 3e34a92..8e452ff 100644 --- a/lib/presentation/home/data/landing_page_data.dart +++ b/lib/presentation/home/data/landing_page_data.dart @@ -142,44 +142,42 @@ class LandingPageData { static List getServiceCardsList = [ ServiceCardData( - icon: AppAssets.liveCareService, + serviceName: "livecare", + icon: AppAssets.small_livecare_icon, title: "LiveCare", subtitle: "Explore our app, View our services and offers", - largeCardIcon: AppAssets.livecare_icon, - backgroundColor: Colors.transparent, - iconColor: Colors.transparent, - textColor: Colors.transparent, - isBold: true, - ), - ServiceCardData( - icon: AppAssets.lab_result_icon, - title: "Dermatology", - subtitle: "Explore our app, View our services and offers", - largeCardIcon: AppAssets.livecare_icon, - backgroundColor: AppColors.whiteColor, - iconColor: AppColors.blackColor, - textColor: AppColors.blackColor, + largeCardIcon: AppAssets.liveCareService, + backgroundColor: AppColors.successColor, + iconColor: AppColors.whiteColor, isBold: false, ), - ServiceCardData( - icon: AppAssets.my_prescription_icon, + // ServiceCardData( + // icon: AppAssets.homeBottom, + // title: "Dermatology", + // subtitle: "Explore our app, View our services and offers", + // largeCardIcon: AppAssets.homeBottom, + // backgroundColor: AppColors.primaryRedColor, + // isBold: false, + // ), + ServiceCardData( + serviceName: "home_health_care", + icon: AppAssets.homeBottom, title: "Home Health Care", subtitle: "Explore our app, View our services and offers", - largeCardIcon: AppAssets.livecare_icon, - backgroundColor: AppColors.whiteColor, - iconColor: AppColors.blackColor, - textColor: AppColors.blackColor, + largeCardIcon: AppAssets.homeHealthCareService, + backgroundColor: AppColors.primaryRedColor, + iconColor: AppColors.whiteColor, isBold: false, ), ServiceCardData( - icon: AppAssets.insurance_update_icon, + serviceName: "pharmacy", + icon: AppAssets.pharmacy_icon, //359846 title: "Pharmacy", subtitle: "Explore our app, View our services and offers", - largeCardIcon: AppAssets.livecare_icon, - backgroundColor: AppColors.whiteColor, - iconColor: AppColors.blackColor, - textColor: AppColors.blackColor, - isBold: false, + largeCardIcon: AppAssets.pharmacyService, + backgroundColor: AppColors.pharmacyBGColor, + iconColor: null, + isBold: true, ), ]; } diff --git a/lib/presentation/home/data/service_card_data.dart b/lib/presentation/home/data/service_card_data.dart index 49e7e3d..3bc22d7 100644 --- a/lib/presentation/home/data/service_card_data.dart +++ b/lib/presentation/home/data/service_card_data.dart @@ -7,7 +7,7 @@ class ServiceCardData { final String icon; final String title; final String subtitle; - final Color iconColor; + final Color? iconColor; final Color textColor; final Color backgroundColor; final bool isBold; @@ -22,6 +22,6 @@ class ServiceCardData { this.backgroundColor = AppColors.whiteColor, this.iconColor = AppColors.blackColor, this.textColor = AppColors.blackColor, - this.isBold = false, + this.isBold = false }); } diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 0bb4ab2..fc50d02 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -107,6 +107,7 @@ class _LandingPageState extends State { prescriptionsViewModel.initPrescriptionsViewModel(); insuranceViewModel.initInsuranceProvider(); emergencyServicesViewModel.checkPatientERAdvanceBalance(); + myAppointmentsViewModel.getPatientAppointmentQueueDetails(); appointmentRatingViewModel.getLastRatingAppointment(onSuccess: (response) { if (appointmentRatingViewModel.appointmentRatedList.isNotEmpty) { appointmentRatingViewModel.getAppointmentDetails(appointmentRatingViewModel.appointmentRatedList.last.appointmentNo!, appointmentRatingViewModel.appointmentRatedList.last.projectID!, @@ -305,15 +306,15 @@ class _LandingPageState extends State { Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), ], ), - SizedBox(height: 10.h), - "Hala ${appState.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true), SizedBox(height: 8.h), + "Hala ${appState.getAuthenticatedUser()!.firstName}!!!".needTranslation.toText16(isBold: true), + SizedBox(height: 2.h), "Thank you for your patience, here is your queue number." .needTranslation .toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), SizedBox(height: 8.h), myAppointmentsVM.currentPatientQueueDetails.queueNo!.toText28(isBold: true), - SizedBox(height: 12.h), + SizedBox(height: 6.h), myAppointmentsVM.patientQueueDetailsList.isNotEmpty ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, @@ -337,7 +338,7 @@ class _LandingPageState extends State { ), ], ) : SizedBox(height: 12.h), - SizedBox(height: 8.h), + SizedBox(height: 5.h), CustomButton( text: Utils.getCardButtonText(myAppointmentsVM.currentQueueStatus, myAppointmentsVM.currentPatientQueueDetails.roomNo ?? ""), onPressed: () {}, @@ -479,6 +480,7 @@ class _LandingPageState extends State { CustomButton( text: LocaleKeys.bookAppo.tr(context: context), onPressed: () { + getIt.get().onTabChanged(0); Navigator.of(context).push(CustomPageRoute(page: BookAppointmentPage())); }, backgroundColor: Color(0xffFEE9EA), @@ -595,7 +597,7 @@ class _LandingPageState extends State { icon: LandingPageData.getLoggedInServiceCardsList[index].icon, title: LandingPageData.getLoggedInServiceCardsList[index].title, subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle, - iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor, + iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor!, textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor, backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor, isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold, @@ -636,7 +638,7 @@ class _LandingPageState extends State { icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon, title: LandingPageData.getNotLoggedInServiceCardsList[index].title, subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle, - iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor, + iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor!, textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor, backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor, isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold, @@ -681,6 +683,7 @@ class _LandingPageState extends State { horizontalOffset: 100.0, child: FadeInAnimation( child: LargeServiceCard( + serviceCardData: LandingPageData.getServiceCardsList[index], image: LandingPageData.getServiceCardsList[index].icon, title: LandingPageData.getServiceCardsList[index].title, subtitle: LandingPageData.getServiceCardsList[index].subtitle, @@ -690,7 +693,7 @@ class _LandingPageState extends State { ), ); }, - separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 8.w), + separatorBuilder: (BuildContext cxt, int index) => SizedBox(width: 16.w), ), ), appState.isAuthenticated ? HabibWalletCard() : SizedBox(), diff --git a/lib/presentation/home/navigation_screen.dart b/lib/presentation/home/navigation_screen.dart index 7fbcdb3..6ec8c3a 100644 --- a/lib/presentation/home/navigation_screen.dart +++ b/lib/presentation/home/navigation_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.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/extensions/route_extensions.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/presentation/contact_us/feedback_page.dart'; import 'package:hmg_patient_app_new/presentation/hmg_services/services_page.dart'; import 'package:hmg_patient_app_new/presentation/home/landing_page.dart'; @@ -41,6 +42,7 @@ class _LandingNavigationState extends State { onTap: (index) { setState(() => _currentIndex = index); if (_currentIndex == 2) { + getIt.get().onTabChanged(0); context.navigateWithName(AppRoutes.bookAppointmentPage); return; } diff --git a/lib/presentation/home/widgets/large_service_card.dart b/lib/presentation/home/widgets/large_service_card.dart index 7a155df..0e02a5e 100644 --- a/lib/presentation/home/widgets/large_service_card.dart +++ b/lib/presentation/home/widgets/large_service_card.dart @@ -1,16 +1,26 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/app_assets.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/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; +import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; +import 'package:hmg_patient_app_new/presentation/home/data/service_card_data.dart'; +import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../../../core/utils/utils.dart'; import '../../../theme/colors.dart'; class LargeServiceCard extends StatelessWidget { + final ServiceCardData serviceCardData; final String image; final String icon; final String title; @@ -18,6 +28,7 @@ class LargeServiceCard extends StatelessWidget { const LargeServiceCard({ super.key, + required this.serviceCardData, this.image = "", this.icon = "", this.title = "", @@ -27,37 +38,112 @@ class LargeServiceCard extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - width: 150.w, - padding: EdgeInsets.symmetric(horizontal: 3.w), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: Colors.transparent, borderRadius: 16.r), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, + height: 350.h, + width: 230.w, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.transparent, borderRadius: 24.r), + child: Stack( children: [ - Image.asset(AppAssets.liveCareService, width: 220.w, fit: BoxFit.contain), - SizedBox(height: 10.h), - Row( - children: [ - Utils.buildSvgWithAssets(icon: icon, width: 24.w, height: 24.h), - Flexible(child: title.toText14(color: AppColors.blackColor, isBold: true, textOverflow: TextOverflow.clip, maxlines: 1)), - ], + ClipRRect( + borderRadius: BorderRadius.circular(24.r), + child: Image.asset( + serviceCardData.largeCardIcon, + fit: BoxFit.cover, + ), ), - subtitle.toText11(color: AppColors.blackColor), - SizedBox(height: 10.h), - CustomButton( - text: LocaleKeys.bookNow.tr(context: context), - onPressed: () {}, - backgroundColor: AppColors.borderOnlyColor, - borderColor: AppColors.borderOnlyColor, - textColor: AppColors.whiteColor, - fontSize: 14.f, - fontWeight: FontWeight.bold, - borderRadius: 12.r, - padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), - height: 40.h, + Positioned( + bottom: 0.0, // Positions the child 0 logical pixels from the bottom + left: 0.0, + right: 0.0, + child: Container( + height: 180.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + customBorder: BorderRadius.only( + bottomLeft: Radius.circular(24.r), + bottomRight: Radius.circular(24.r), + ), + ), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 48.h, + width: 48.w, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: serviceCardData.backgroundColor, + borderRadius: 12.r, + hasShadow: false, + ), + child: Padding( + padding: EdgeInsets.all(12.h), + child: Utils.buildSvgWithAssets( + icon: serviceCardData.icon, + iconColor: serviceCardData.iconColor, + fit: BoxFit.contain, + ), + ), + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + serviceCardData.title.toText14(isBold: true, color: AppColors.textColor), + SizedBox(width: 6.h), + serviceCardData.subtitle.toText14(weight: FontWeight.w500, color: AppColors.textColorLight), + ], + ), + ), + ], + ).paddingSymmetrical(16.w, 20.h), + CustomButton( + text: serviceCardData.isBold ? "Visit Pharmacy Online".needTranslation : LocaleKeys.bookNow.tr(context: context), + onPressed: () { + handleOnTap(); + }, + backgroundColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.2) : AppColors.bgRedLightColor, + borderColor: serviceCardData.isBold ? AppColors.successLightColor.withValues(alpha: 0.01) : AppColors.bgRedLightColor, + textColor: serviceCardData.isBold ? AppColors.successColor : AppColors.primaryRedColor, + fontSize: 14.f, + fontWeight: FontWeight.w500, + borderRadius: 10.r, + height: 40.h, + ).paddingSymmetrical(16.w, 0.h), + ], + ), + ), ), ], ), ); } + + void handleOnTap() { + switch (serviceCardData.serviceName) { + case "livecare": + { + getIt.get().onTabChanged(1); + Navigator.of(getIt.get().navigatorKey.currentContext!).push( + CustomPageRoute( + page: BookAppointmentPage(), + ), + ); + } + case "home_health_care": + { + Navigator.of(getIt().navigatorKey.currentContext!).push( + CustomPageRoute( + page: HhcProceduresPage(), + ), + ); + } + case "pharmacy": + { + Uri uri = Uri.parse(PHARMACY_REDIRECT_URL); + launchUrl(uri, mode: LaunchMode.externalApplication); + } + } + } } diff --git a/lib/presentation/home_health_care/hhc_order_detail_page.dart b/lib/presentation/home_health_care/hhc_order_detail_page.dart index 21b0def..92c93d1 100644 --- a/lib/presentation/home_health_care/hhc_order_detail_page.dart +++ b/lib/presentation/home_health_care/hhc_order_detail_page.dart @@ -10,10 +10,8 @@ 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/hmg_services/hmg_services_view_model.dart'; import 'package:hmg_patient_app_new/features/hmg_services/models/resq_models/get_cmc_all_orders_resp_model.dart'; -import 'package:hmg_patient_app_new/presentation/home_health_care/widgets/hhc_ui_selection_helper.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:provider/provider.dart'; @@ -75,7 +73,6 @@ class _HhcOrderDetailPageState extends State { Widget _buildOrderCard(GetCMCAllOrdersResponseModel order, {bool isLoading = false}) { final statusColor = _getStatusColor(order.statusId); - final canCancel = order.statusId == 1 || order.statusId == 2; return AnimatedContainer( duration: Duration(milliseconds: 300), @@ -150,27 +147,27 @@ class _HhcOrderDetailPageState extends State { ], ), - // Cancel Button - if (canCancel || isLoading) ...[ - SizedBox(height: 16.h), - Row( - children: [ - Expanded( - child: CustomButton( - text: "Cancel Order".needTranslation, - onPressed: isLoading ? () {} : () => HhcUiSelectionHelper.showCancelConfirmationDialog(context: context, order: order), - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: AppColors.whiteColor, - fontSize: 14.f, - fontWeight: FontWeight.w600, - borderRadius: 10.r, - height: 44.h, - ).toShimmer2(isShow: isLoading), - ), - ], - ), - ] + // // Cancel Button + // if (canCancel || isLoading) ...[ + // SizedBox(height: 16.h), + // Row( + // children: [ + // Expanded( + // child: CustomButton( + // text: "Cancel Order".needTranslation, + // onPressed: isLoading ? () {} : () => HhcUiSelectionHelper.showCancelConfirmationDialog(context: context, order: order), + // backgroundColor: AppColors.primaryRedColor, + // borderColor: AppColors.primaryRedColor, + // textColor: AppColors.whiteColor, + // fontSize: 14.f, + // fontWeight: FontWeight.w600, + // borderRadius: 10.r, + // height: 44.h, + // ).toShimmer2(isShow: isLoading), + // ), + // ], + // ), + // ] ], ), ), @@ -219,6 +216,7 @@ class _HhcOrderDetailPageState extends State { } return ListView.separated( + padding: EdgeInsets.only(top: 24.h), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: viewModel.hhcOrdersList.length, diff --git a/lib/presentation/home_health_care/hhc_procedures_page.dart b/lib/presentation/home_health_care/hhc_procedures_page.dart index bdc2e45..41d8a2f 100644 --- a/lib/presentation/home_health_care/hhc_procedures_page.dart +++ b/lib/presentation/home_health_care/hhc_procedures_page.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.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/hmg_services/hmg_services_view_model.dart'; @@ -17,6 +18,7 @@ import 'package:hmg_patient_app_new/services/navigation_service.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/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; @@ -61,28 +63,9 @@ class _HhcProceduresPageState extends State { } Widget _buildPendingOrderCard(GetCMCAllOrdersResponseModel order) { - int status = order.statusId ?? 0; - String statusDisp = order.statusText ?? ""; - Color statusColor; - - if (status == 1) { - // pending - statusColor = AppColors.statusPendingColor; - } else if (status == 2) { - // processing - statusColor = AppColors.statusProcessingColor; - } else if (status == 3) { - // completed - statusColor = AppColors.statusCompletedColor; - } else { - // cancel / rejected - statusColor = AppColors.statusRejectedColor; - } - final canCancel = order.statusId == 1 || order.statusId == 2; final isArabic = getIt.get().isArabic(); - // Extract services from orderselectedservice List selectedServices = []; if (order.orderselectedservice != null) { if (order.orderselectedservice is List) { @@ -108,16 +91,12 @@ class _HhcProceduresPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), - decoration: BoxDecoration( - color: statusColor.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8.r), - ), - child: statusDisp.toText12( - color: statusColor, - fontWeight: FontWeight.w600, - ), + Row( + children: [ + "Request ID:".needTranslation.toText14(color: AppColors.textColorLight, weight: FontWeight.w500), + SizedBox(width: 4.w), + "${order.iD ?? '-'}".toText16(isBold: true), + ], ), SizedBox(width: 8.w), if (order.created != null) @@ -127,17 +106,7 @@ class _HhcProceduresPageState extends State { ), ], ), - - SizedBox(height: 16.h), - - // Request ID - Row( - children: [ - "Request ID:".needTranslation.toText14(color: AppColors.textColorLight, weight: FontWeight.w500), - SizedBox(width: 4.w), - "${order.iD ?? '-'}".toText16(isBold: true), - ], - ), + SizedBox(height: 8.h), // Services List if (selectedServices.isNotEmpty) ...[ @@ -212,13 +181,13 @@ class _HhcProceduresPageState extends State { ], ), ); - }).toList(), + }), ], ), ), ], - SizedBox(height: 12.h), + SizedBox(height: 8.h), // Info message Container( @@ -274,99 +243,148 @@ class _HhcProceduresPageState extends State { ); } - Widget _buildServiceSelectionList(List services) { - if (services.isEmpty) { - return Center( - child: Padding( - padding: EdgeInsets.all(24.h), - child: Text( - 'No services available'.needTranslation, - style: TextStyle( - fontSize: 16.h, - color: AppColors.greyTextColor, - ), - ), - ), - ); - } - - return Consumer( - builder: (context, viewModel, child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 8.h), - SizedBox(height: 16.h), - Text( - 'Select Services'.needTranslation, - style: TextStyle( - fontSize: 20.h, - fontWeight: FontWeight.w700, - color: AppColors.blackColor, - letterSpacing: -0.8, + _buildServicesListBottomsSheet(List services) { + showCommonBottomSheetWithoutHeight( + hasBottomPadding: false, + padding: EdgeInsets.only(top: 24.h), + context, + title: 'Select Services'.needTranslation, + isCloseButtonVisible: true, + isDismissible: true, + callBackFunc: () {}, + child: services.isEmpty + ? Center( + child: Padding( + padding: EdgeInsets.all(24.h), + child: Text( + 'No services available'.needTranslation, + style: TextStyle( + fontSize: 16.h, + color: AppColors.greyTextColor, + ), + ), ), - ).paddingOnly(left: 16.w, right: 16.w), - SizedBox(height: 12.h), - ListView.builder( - padding: EdgeInsets.symmetric(horizontal: 16.w), - itemCount: services.length, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - final service = services[index]; - final isSelected = viewModel.isHhcServiceSelected(service); - final isArabic = getIt.get().isArabic(); - final serviceName = isArabic ? (service.textN ?? service.text ?? '') : (service.text ?? ''); + ) + : Consumer( + builder: (context, hmgServicesViewModel, child) { + final pendingOrder = _getPendingOrder(hmgServicesViewModel.hhcOrdersList); + final hasSelectedServices = pendingOrder == null && hmgServicesViewModel.selectedHhcServices.isNotEmpty; - return AnimatedContainer( - duration: Duration(milliseconds: 300), - curve: Curves.easeInOut, - margin: EdgeInsets.only(bottom: 12.h), - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 16.r, - hasShadow: true, - ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => viewModel.toggleHhcServiceSelection(service), - borderRadius: BorderRadius.circular(16.r), - child: Container( - padding: EdgeInsets.all(16.w), - child: Row( - children: [ - Checkbox( - value: isSelected, - onChanged: (v) => viewModel.toggleHhcServiceSelection(service), - activeColor: AppColors.primaryRedColor, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - visualDensity: VisualDensity.compact, + return Stack( + children: [ + // Services List + ConstrainedBox( + constraints: BoxConstraints(maxHeight: SizeUtils.height * 0.7), + child: ListView.separated( + separatorBuilder: (context, index) => Divider(color: AppColors.dividerColor).paddingSymmetrical(16.w, 0), + padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: hasSelectedServices ? 160.h : 8.h), + shrinkWrap: true, + itemCount: services.length, + itemBuilder: (context, index) { + final service = services[index]; + final isSelected = hmgServicesViewModel.isHhcServiceSelected(service); + final isArabic = getIt.get().isArabic(); + final serviceName = isArabic ? (service.textN ?? service.text ?? '') : (service.text ?? ''); + + return AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + child: InkWell( + onTap: () => hmgServicesViewModel.toggleHhcServiceSelection(service), + borderRadius: BorderRadius.circular(16.r), + child: Container( + padding: EdgeInsets.all(8.w), + child: Row( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + width: 24.w, + height: 24.w, + decoration: BoxDecoration( + color: isSelected ? AppColors.primaryRedColor : Colors.transparent, + borderRadius: BorderRadius.circular(5.r), + border: Border.all( + color: isSelected ? AppColors.primaryRedColor : AppColors.borderGrayColor, + width: 1.w, + ), + ), + child: isSelected ? Icon(Icons.check, size: 18.f, color: AppColors.whiteColor) : null, + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + serviceName.toText16( + weight: FontWeight.w500, + color: AppColors.blackColor, + maxlines: 2, + ), + ], + ), + ), + ], + ), + ), ), - SizedBox(width: 12.w), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + ); + }, + ), + ), + + if (hasSelectedServices) + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 24.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - serviceName.toText16( - weight: FontWeight.w400, - color: AppColors.blackColor, - maxlines: 2, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Selected Services".needTranslation.toText12( + color: AppColors.textColorLight, + fontWeight: FontWeight.w600, + ), + "${hmgServicesViewModel.selectedHhcServices.length} service(s) selected".toText14( + isBold: true, + weight: FontWeight.bold, + ), + ], ), ], ), - ), - ], + SizedBox(height: 16.h), + CustomButton( + borderWidth: 0, + text: "Next".needTranslation, + onPressed: () { + Navigator.pop(context); + _proceedWithSelectedService(); + }, + textColor: AppColors.whiteColor, + borderRadius: 12.r, + borderColor: Colors.transparent, + ), + ], + ), ), ), - ), - ), + ], ); }, ), - ], - ); - }, ); } @@ -426,77 +444,70 @@ class _HhcProceduresPageState extends State { @override Widget build(BuildContext context) { - return CollapsingListView( - title: "Home Health Care".needTranslation, - history: () => Navigator.of(context).push(CustomPageRoute(page: HhcOrderDetailPage(), direction: AxisDirection.up)), - bottomChild: Consumer( - builder: (context, hmgServicesViewModel, child) { - if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) return SizedBox.shrink(); - final pendingOrder = _getPendingOrder(hmgServicesViewModel.hhcOrdersList); - if (pendingOrder == null && hmgServicesViewModel.selectedHhcServices.isNotEmpty) { - return SafeArea( - top: false, - child: Container( - color: AppColors.whiteColor, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Selected Services Summary Widget - Container( - margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 4.h), - padding: EdgeInsets.all(16.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Selected Services".needTranslation.toText12( - color: AppColors.textColorLight, - fontWeight: FontWeight.w600, - ), - "${hmgServicesViewModel.selectedHhcServices.length} service(s) selected".toText14( - isBold: true, - weight: FontWeight.bold, - ), - ], + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: Column( + children: [ + Expanded( + child: CollapsingListView( + title: "Home Health Care".needTranslation, + history: () => Navigator.of(context).push(CustomPageRoute(page: HhcOrderDetailPage(), direction: AxisDirection.up)), + child: Consumer( + builder: (context, hmgServicesViewModel, child) { + if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) { + return _buildLoadingShimmer(); + } + final pendingOrder = _getPendingOrder(hmgServicesViewModel.hhcOrdersList); + if (pendingOrder != null) { + return _buildPendingOrderCard(pendingOrder); + } else { + return Column( + children: [ + Center( + child: Utils.getNoDataWidget( + context, + noDataText: "You have no pending requests.".needTranslation, ), - ], - ), - ), - // Next Button - Padding( - padding: EdgeInsets.only(left: 16.w, right: 16.w), - child: CustomButton( - borderWidth: 0, - text: "Next".needTranslation, - onPressed: _proceedWithSelectedService, - textColor: AppColors.whiteColor, - borderRadius: 12.r, - borderColor: Colors.transparent, - padding: EdgeInsets.symmetric(vertical: 14.h), - ), - ), - ], - ), + ), + ], + ); + } + }, ), - ); - } - return SizedBox.shrink(); - }, - ), - child: Consumer( - builder: (context, hmgServicesViewModel, child) { - if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) { - return _buildLoadingShimmer(); - } - final pendingOrder = _getPendingOrder(hmgServicesViewModel.hhcOrdersList); - if (pendingOrder != null) { - return _buildPendingOrderCard(pendingOrder); - } else { - return _buildServiceSelectionList(hmgServicesViewModel.hhcServicesList); - } - }, + ), + ), + Consumer( + builder: (BuildContext context, HmgServicesViewModel hmgServicesViewModel, Widget? child) { + if (hmgServicesViewModel.isHhcOrdersLoading || hmgServicesViewModel.isHhcServicesLoading) { + return SizedBox.shrink(); + } + final pendingOrder = _getPendingOrder(hmgServicesViewModel.hhcOrdersList); + if (pendingOrder == null) { + return Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), + child: Padding( + padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 24.h, top: 24.h), + child: CustomButton( + borderWidth: 0, + text: "Create new request".needTranslation, + onPressed: () => _buildServicesListBottomsSheet(hmgServicesViewModel.hhcServicesList), + textColor: AppColors.whiteColor, + borderRadius: 12.r, + borderColor: Colors.transparent, + padding: EdgeInsets.symmetric(vertical: 14.h), + ), + ), + ); + } + + return SizedBox.shrink(); + }, + ), + ], ), ); } diff --git a/lib/presentation/home_health_care/hhc_selection_review_page.dart b/lib/presentation/home_health_care/hhc_selection_review_page.dart index 8e9ba90..37410e2 100644 --- a/lib/presentation/home_health_care/hhc_selection_review_page.dart +++ b/lib/presentation/home_health_care/hhc_selection_review_page.dart @@ -15,6 +15,7 @@ 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/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/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/map/location_map_widget.dart'; @@ -68,40 +69,26 @@ class _HhcSelectionReviewPageState extends State { Widget _buildSelectedServicesCard(bool isArabic) { return Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 16.r, - ), + width: double.infinity, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), padding: EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Selected Services".needTranslation.toText14( weight: FontWeight.w600, - color: AppColors.greyTextColor, + color: AppColors.textColor, letterSpacing: -0.4, ), SizedBox(height: 12.h), - ...widget.selectedServices.map((service) { - final serviceName = isArabic ? (service.textN ?? service.text ?? '') : (service.text ?? ''); - final price = service.priceTotal ?? 0.0; - return Padding( - padding: EdgeInsets.only(bottom: 4.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: serviceName.toText14( - weight: FontWeight.w600, - color: AppColors.blackColor, - letterSpacing: -0.5, - maxlines: 2, - ), - ), - ], - ), - ); - }), + Wrap( + spacing: 8.w, + runSpacing: 12.w, + children: widget.selectedServices.map((service) { + final serviceName = isArabic ? (service.textN ?? service.text ?? '') : (service.text ?? ''); + return AppCustomChipWidget(labelText: serviceName.needTranslation); + }).toList(), + ), ], ), ); @@ -117,8 +104,8 @@ class _HhcSelectionReviewPageState extends State { return SizedBox.shrink(); } - final double lat = mapCapturedLocation.lat ?? 0.0; - final double lng = mapCapturedLocation.lng ?? 0.0; + final double lat = mapCapturedLocation?.lat ?? 0.0; + final double lng = mapCapturedLocation?.lng ?? 0.0; if (lat == 0.0 || lng == 0.0) return SizedBox.shrink(); @@ -132,36 +119,25 @@ class _HhcSelectionReviewPageState extends State { latitude: lat, longitude: lng, address: address, - title: "Service Location".needTranslation, onDirectionsTap: () => _launchDirectionsToLocation(lat, lng, address), ); } Widget _buildBottomButton() { - return SafeArea( - top: false, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), - decoration: BoxDecoration( - color: AppColors.whiteColor, - boxShadow: [ - BoxShadow( - color: Color.fromARGB(13, 0, 0, 0), - blurRadius: 8, - offset: Offset(0, -2), - ), - ], - ), - child: CustomButton( - text: "Confirm".needTranslation, - onPressed: _handleConfirm, - textColor: AppColors.whiteColor, - backgroundColor: AppColors.successColor, - borderRadius: 12.r, - borderColor: Colors.transparent, - borderWidth: 0, - padding: EdgeInsets.symmetric(vertical: 14.h), - ), + return Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 24.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + hasShadow: true, + ), + child: CustomButton( + borderWidth: 0, + text: "Confirm".needTranslation, + onPressed: () => _handleConfirm(), + textColor: AppColors.whiteColor, + borderRadius: 12.r, + borderColor: Colors.transparent, ), ); } diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart index cdd9a2e..bacf5e9 100644 --- a/lib/presentation/insurance/insurance_home_page.dart +++ b/lib/presentation/insurance/insurance_home_page.dart @@ -74,7 +74,7 @@ class _InsuranceHomePageState extends State { padding: EdgeInsets.only(top: 24.h), child: PatientInsuranceCard( insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, - isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))), + isInsuranceExpired: DateTime.now().isAfter(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))).paddingSymmetrical(24.w, 0.h), ) : Padding( padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.12), diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 7d149ed..f55488d 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -27,6 +27,7 @@ import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/allergies/allergies_list_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart'; import 'package:hmg_patient_app_new/presentation/appointments/my_doctors_page.dart'; +import 'package:hmg_patient_app_new/presentation/appointments/widgets/ask_doctor_request_type_select.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/doctor_profile_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; @@ -452,6 +453,7 @@ class _MedicalFilePageState extends State { CustomButton( text: LocaleKeys.bookAppo.tr(context: context), onPressed: () { + getIt.get().onTabChanged(0); Navigator.of(context).push( CustomPageRoute( page: BookAppointmentPage(), @@ -492,8 +494,36 @@ class _MedicalFilePageState extends State { onRescheduleTap: () { openDoctorScheduleCalendar(myAppointmentsVM.patientAppointmentsHistoryList[index]); }, - onAskDoctorTap: () {}, - )), + onAskDoctorTap: () async { + LoaderBottomSheet.showLoader(loadingText: "Checking doctor availability...".needTranslation); + await myAppointmentsViewModel.isDoctorAvailable( + projectID: myAppointmentsVM.patientAppointmentsHistoryList[index].projectID, + doctorId: myAppointmentsVM.patientAppointmentsHistoryList[index].doctorID, + clinicId: myAppointmentsVM.patientAppointmentsHistoryList[index].clinicID, + onSuccess: (value) async { + if (value) { + await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.askDoctor.tr(context: context), + child: AskDoctorRequestTypeSelect( + askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList, + myAppointmentsViewModel: myAppointmentsViewModel, + patientAppointmentHistoryResponseModel: myAppointmentsVM.patientAppointmentsHistoryList[index], + ), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + } else { + print("Doctor is not available"); + } + }); + }, + ), + ), ), ), ); diff --git a/lib/presentation/medical_file/widgets/lab_rad_card.dart b/lib/presentation/medical_file/widgets/lab_rad_card.dart index eef73eb..f31c90b 100644 --- a/lib/presentation/medical_file/widgets/lab_rad_card.dart +++ b/lib/presentation/medical_file/widgets/lab_rad_card.dart @@ -28,59 +28,24 @@ class LabRadCard extends StatelessWidget { AppState appState = getIt.get(); return Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 18.r, hasShadow: false), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Utils.buildSvgWithAssets( - icon: icon, - width: 40.w, - height: 40.h, - fit: BoxFit.cover, - ).toShimmer2(isShow: false, radius: 12.r), - SizedBox(width: 8.w), - Flexible( - child: labelText.toText12(isBold: true, maxLine: 2), - ), - Transform.flip( - flipX: appState.isArabic(), - child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 10.w, height: 10.h, fit: BoxFit.contain, iconColor: AppColors.textColor), - ), - ], + Utils.buildSvgWithAssets( + icon: icon, + width: 40.w, + height: 40.h, + fit: BoxFit.cover, + ).toShimmer2(isShow: false, radius: 12.r), + SizedBox(width: 8.w), + Flexible( + child: labelText.toText12(isBold: true, maxLine: 2), + ), + SizedBox(width: 12.w), + Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets(icon: AppAssets.forward_arrow_icon_small, width: 10.w, height: 10.h, fit: BoxFit.contain, iconColor: AppColors.textColor), ), - // SizedBox(height: 16.h), - // labOrderTests.isNotEmpty - // ? ListView.separated( - // scrollDirection: Axis.vertical, - // padding: EdgeInsets.zero, - // physics: NeverScrollableScrollPhysics(), - // shrinkWrap: true, - // itemBuilder: (cxt, index) { - // return labOrderTests[index] - // .toText12(isBold: true, maxLine: 1) - // .toShimmer2(isShow: false, radius: 6.r, height: 24.h, width: 120.w) - // .toShimmer2(isShow: isLoading); - // }, - // separatorBuilder: (cxt, index) => SizedBox(height: 8.h), - // itemCount: 3, - // ) - // : "You don't have any records yet".needTranslation.toText13( - // color: AppColors.greyTextColor, isCenter: true), - // SizedBox(height: 16.h), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // SizedBox.shrink(), - // Transform.flip( - // flipX: appState.isArabic(), - // child: Utils.buildSvgWithAssets( - // icon: AppAssets.forward_arrow_icon_small, width: 15.w, height: 15.h, fit: BoxFit.contain, iconColor: AppColors.textColor) - // .toShimmer2(isShow: false, radius: 12.r), - // ), - // ], - // ) ], ).paddingAll(12.w), ); diff --git a/lib/presentation/medical_report/medical_reports_page.dart b/lib/presentation/medical_report/medical_reports_page.dart index 71abcb7..4047a53 100644 --- a/lib/presentation/medical_report/medical_reports_page.dart +++ b/lib/presentation/medical_report/medical_reports_page.dart @@ -10,12 +10,11 @@ import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_mode import 'package:hmg_patient_app_new/features/medical_file/models/patient_medical_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/medical_report/medical_report_request_page.dart'; -import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/presentation/medical_report/widgets/patient_medical_report_card.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/common_bottom_sheet.dart'; -import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; @@ -53,7 +52,8 @@ class _MedicalReportsPageState extends State { medicalFileViewModel.onMedicalReportTabChange(0); }, backgroundColor: medicalFileVM.selectedMedicalReportsTabIndex == 0 ? AppColors.bgRedLightColor : AppColors.whiteColor, - borderColor: medicalFileVM.selectedMedicalReportsTabIndex == 0 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), + borderColor: + medicalFileVM.selectedMedicalReportsTabIndex == 0 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), textColor: medicalFileVM.selectedMedicalReportsTabIndex == 0 ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12, fontWeight: FontWeight.w500, @@ -68,7 +68,8 @@ class _MedicalReportsPageState extends State { medicalFileViewModel.onMedicalReportTabChange(1); }, backgroundColor: medicalFileVM.selectedMedicalReportsTabIndex == 1 ? AppColors.bgRedLightColor : AppColors.whiteColor, - borderColor: medicalFileVM.selectedMedicalReportsTabIndex == 1 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), + borderColor: + medicalFileVM.selectedMedicalReportsTabIndex == 1 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), textColor: medicalFileVM.selectedMedicalReportsTabIndex == 1 ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12, fontWeight: FontWeight.w500, @@ -83,7 +84,8 @@ class _MedicalReportsPageState extends State { medicalFileViewModel.onMedicalReportTabChange(2); }, backgroundColor: medicalFileVM.selectedMedicalReportsTabIndex == 2 ? AppColors.bgRedLightColor : AppColors.whiteColor, - borderColor: medicalFileVM.selectedMedicalReportsTabIndex == 2 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), + borderColor: + medicalFileVM.selectedMedicalReportsTabIndex == 2 ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), textColor: medicalFileVM.selectedMedicalReportsTabIndex == 2 ? AppColors.primaryRedColor : AppColors.blackColor, fontSize: 12, fontWeight: FontWeight.w500, @@ -131,7 +133,8 @@ class _MedicalReportsPageState extends State { child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + decoration: RoundedRectangleBorder() + .toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), child: PatientMedicalReportCard( patientMedicalReportResponseModel: medicalFileVM.patientMedicalReportList[index], medicalFileViewModel: medicalFileVM, @@ -141,7 +144,8 @@ class _MedicalReportsPageState extends State { ), ), ) - : Utils.getNoDataWidget(context, noDataText: "You don't have any medical reports yet.".needTranslation).paddingSymmetrical(24.h, 24.h); + : Utils.getNoDataWidget(context, noDataText: "You don't have any medical reports yet.".needTranslation) + .paddingSymmetrical(24.h, 24.h); }, separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), ), @@ -188,11 +192,10 @@ class _MedicalReportsPageState extends State { backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor, textColor: AppColors.whiteColor, - fontSize: 16, + fontSize: 16.f, fontWeight: FontWeight.w500, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 45.h, + borderRadius: 12.r, + height: 46.h, icon: AppAssets.requests, iconColor: AppColors.whiteColor, iconSize: 20.h, @@ -218,7 +221,9 @@ class _MedicalReportsPageState extends State { LoaderBottomSheet.showLoader(); await medicalFileViewModel.insertRequestForMedicalReport(onSuccess: (val) { LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight(context, child: Utils.getSuccessWidget(loadingText: "Your medical report request has been successfully submitted.".needTranslation), callBackFunc: () { + showCommonBottomSheetWithoutHeight(context, + child: Utils.getSuccessWidget(loadingText: "Your medical report request has been successfully submitted.".needTranslation), + callBackFunc: () { medicalFileViewModel.setIsPatientMedicalReportsLoading(true); medicalFileViewModel.onMedicalReportTabChange(0); medicalFileViewModel.getPatientMedicalReportList(); diff --git a/lib/presentation/smartwatches/smartwatch_instructions_page.dart b/lib/presentation/smartwatches/smartwatch_instructions_page.dart index 357f5f5..1c3644b 100644 --- a/lib/presentation/smartwatches/smartwatch_instructions_page.dart +++ b/lib/presentation/smartwatches/smartwatch_instructions_page.dart @@ -4,15 +4,18 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:health/health.dart'; import 'package:hmg_patient_app_new/core/app_assets.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/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/presentation/smartwatches/health_dashboard/health_dashboard.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.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/routes/custom_page_route.dart'; +import 'package:url_launcher/url_launcher.dart'; class SmartwatchInstructionsPage extends StatelessWidget { const SmartwatchInstructionsPage({super.key}); @@ -178,19 +181,20 @@ class SmartwatchInstructionsPage extends StatelessWidget { await Health().getHealthConnectSdkStatus().then((val) { print('Health Connect SDK Status: $val'); if (val == HealthConnectSdkStatus.sdkAvailable) { - // Navigator.of(context).push( - // FadePage( - // page: HealthDashboard(), // Replace with the actual vital signs page - // // page: HealthApp(), // Replace with the actual vital signs page - // ), - // ); + Navigator.of(context).push( + CustomPageRoute( + page: HealthDashboard(), + ), + ); } else { - // Utils.showAppDialog(context, LocaleKeys.error.tr(context: context), LocaleKeys.healthConnectNotInstalled.tr(), () { - // Navigator.pop(context); - // Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata"); - // launchUrl(uri, mode: LaunchMode.externalApplication); - // }); - // return; + getIt.get().showErrorBottomSheet( + message: "Seems like you do not have Health Connect App installed. Please install it from the Play Store to sync your health data.".needTranslation, + onOkPressed: () { + Navigator.pop(context); + Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata"); + launchUrl(uri, mode: LaunchMode.externalApplication); + }); + return; } }); }, diff --git a/lib/theme/colors.dart b/lib/theme/colors.dart index 630cf02..d0db6a5 100644 --- a/lib/theme/colors.dart +++ b/lib/theme/colors.dart @@ -33,6 +33,8 @@ class AppColors { static const Color greyTextColor = Color(0xFF8F9AA3); static const Color lightGrayBGColor = Color(0x142E3039); + static const Color pharmacyBGColor = Color(0xFF359846); + static const lightGreenColor = Color(0xFF0ccedde); static const textGreenColor = Color(0xFF18C273); static const Color ratingColorYellow = Color(0xFFFFAF15); diff --git a/lib/widgets/custom_tab_bar.dart b/lib/widgets/custom_tab_bar.dart index 35aafa4..c30c070 100644 --- a/lib/widgets/custom_tab_bar.dart +++ b/lib/widgets/custom_tab_bar.dart @@ -14,7 +14,7 @@ class CustomTabBarModel { } class CustomTabBar extends StatefulWidget { - final int initialIndex = 0; + final int initialIndex; final List tabs; final Color activeTextColor; final Color activeBackgroundColor; @@ -25,6 +25,7 @@ class CustomTabBar extends StatefulWidget { const CustomTabBar({ super.key, required this.tabs, + this.initialIndex = 0, this.activeTextColor = const Color(0xff2E3039), this.inActiveTextColor = const Color(0xff898A8D), this.activeBackgroundColor = const Color(0x142E3039), @@ -41,6 +42,7 @@ class CustomTabBarState extends State { @override void initState() { + selectedIndex = widget.initialIndex; super.initState(); } diff --git a/lib/widgets/map/location_map_widget.dart b/lib/widgets/map/location_map_widget.dart index 4cf5eae..c0eb431 100644 --- a/lib/widgets/map/location_map_widget.dart +++ b/lib/widgets/map/location_map_widget.dart @@ -21,7 +21,7 @@ class LocationMapWidget extends StatelessWidget { final String address; /// The title to show above the map (e.g., "Service Location", "Hospital Location") - final String title; + final String? title; /// The zoom level for the map (default: 14) final int zoomLevel; @@ -36,9 +36,6 @@ class LocationMapWidget extends StatelessWidget { /// Whether to show the address container (default: true) final bool showAddress; - /// Whether to show the title (default: true) - final bool showTitle; - /// Custom map type (default: roadmap) final String mapType; final EdgeInsets? padding; @@ -48,12 +45,11 @@ class LocationMapWidget extends StatelessWidget { required this.latitude, required this.longitude, required this.address, - required this.title, + this.title, this.zoomLevel = 14, this.mapSize = '350x165', this.onDirectionsTap, this.showAddress = true, - this.showTitle = true, this.mapType = 'roadmap', this.padding, }); @@ -70,18 +66,15 @@ class LocationMapWidget extends StatelessWidget { "https://maps.googleapis.com/maps/api/staticmap?center=$latitude,$longitude&zoom=$zoomLevel&size=$mapSize&maptype=$mapType&markers=color:red%7C$latitude,$longitude&key=${ApiKeyConstants.googleMapsApiKey}"; return Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 16.r, - ), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), padding: padding ?? EdgeInsets.all(16.w), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title - if (showTitle) ...[ + if (title != null) ...[ Text( - title, + title ?? "", style: TextStyle( fontSize: 16.f, fontWeight: FontWeight.w700, @@ -94,35 +87,22 @@ class LocationMapWidget extends StatelessWidget { // Address display if (showAddress) ...[ - Container( - padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 14.h), - decoration: BoxDecoration( - color: AppColors.bgScaffoldColor, - borderRadius: BorderRadius.circular(12.r), - border: Border.all( - color: AppColors.greyColor.withAlpha(51), - width: 1, - ), - ), - child: Row( - children: [ - Icon(Icons.location_on, color: AppColors.primaryRedColor, size: 20.h), - SizedBox(width: 8.w), - Expanded( - child: Text( - address, - style: TextStyle( - fontSize: 14.f, - fontWeight: FontWeight.w500, - color: AppColors.blackColor, - letterSpacing: -0.4, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, + Row( + children: [ + Expanded( + child: Text( + address, + style: TextStyle( + fontSize: 14.f, + fontWeight: FontWeight.w500, + color: AppColors.blackColor, + letterSpacing: -0.4, ), + maxLines: 2, + overflow: TextOverflow.ellipsis, ), - ], - ), + ), + ], ), SizedBox(height: 16.h), ],