diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 958b717a..ff0d3e0e 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1658,5 +1658,16 @@ "doctorAddedToFavourite": "تمت إضافة إلى قائمة المفضلة", "doctorRemovedFromFavourite": "تمت إزالة من قائمة الأطباء المفضلين", "addNewFavorite": "إضافة مفضلة جديدة", - "favourites": "المفضلة" + "favourites": "المفضلة", + "pendingAncillaryOrders": "مدفوعات طلبات الاضافية", + "liveCarePermissions": "يتطلب لايف كير أذونات الكاميرا والميكروفون وإشعارات، يرجى السماح لها بالمتابعة.", + "containsImage": "يحتوي على صورة", + "servicesSelected": "الخدمة (الخدمات) المختارة", + "selectMedicalFileFromFamily": "اختر ملف طبي من عائلتك", + "anyFileFromHMG": "أي ملف طبي نشط من مجموعة حبيب الطبية", + "noDistance": "المسافة غير متوفرة", + "enterAmount": "يرجى إدخال المبلغ للمتابعة.", + "selectHospitalContinue": "يرجى اختيار المستشفى للمتابعة.", + "year": "سنة", + "notifyPrescription": "أبلغني قبل وقت الاستهلاك" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 385dbdbf..9623b34e 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1309,7 +1309,7 @@ "rejectedYourFamilyMemberRequest": "{status} your family member request", "notAvailable": "N/A", "selectAProfile": "Please select a profile", - "switchFamilyFile": "Switch from the below list of medical file", + "switchFamilyFile": "Switch from the below list of medical files", "medicalFiles": "Medical Files", "addANewFamilyMember": "Add a new family member", "viewInvoiceDetails": "View invoice details", @@ -1650,5 +1650,16 @@ "doctorAddedToFavourite": "Added to favorites list", "doctorRemovedFromFavourite": "Removed from favorites list", "favourites": "Favourites", - "addNewFavorite": "Add new favourite" + "addNewFavorite": "Add new favourite", + "pendingAncillaryOrders": "Pending ancillary orders", + "liveCarePermissions": "LiveCare requires Camera, Microphone & Notifications permissions to enable virtual consultation between patient & doctor, Open app settings to allow them.", + "containsImage": "Contains Image", + "servicesSelected": "Service(s) Selected", + "selectMedicalFileFromFamily": "Select a medical file from your family", + "anyFileFromHMG": "Any active medical file from HMG", + "noDistance": "Distance not available", + "enterAmount": "Please enter amount to continue.", + "selectHospitalContinue": "Please select hospital to continue.", + "year": "Year", + "notifyPrescription": "Notify me before the consumption time" } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index a68bdcf1..a04685da 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -24,7 +24,7 @@ extension CapExtension on String { extension EmailValidator on String { Widget get toWidget => Text(this); - Widget toText8({Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text( + Widget toText8({bool isEnglishOnly = false, Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text( this, maxLines: maxlines, overflow: textOverflow, @@ -34,6 +34,7 @@ extension EmailValidator on String { fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: 0, + fontFamily: isEnglishOnly ? "Poppins" : getIt.get().getLanguageCode() == "ar" ? 'GESSTwo' : 'Poppins', ), ); diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart index cd8ad70d..27529ebf 100644 --- a/lib/features/authentication/authentication_repo.dart +++ b/lib/features/authentication/authentication_repo.dart @@ -692,6 +692,7 @@ class AuthenticationRepoImp implements AuthenticationRepo { @override Future>> getPatientBloodType() async { + // Map requestBody = {"PatientType": 1, "PatientTypeID": 1, "TokenID": "@dm!n", "PatientID": 5957754}; Map requestBody = {}; try { GenericApiModel? apiResponse; diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 8116b2a0..b221853f 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -101,7 +101,10 @@ class AuthenticationViewModel extends ChangeNotifier { var healthId; int getDeviceLastLogin = 1; + bool isInitialLoginNavigated = false; + Future onLoginPressed() async { + setIsInitialLoginNavigated(false); try { LoaderBottomSheet.showLoader(); //TODO: We will remove this delay @@ -111,7 +114,7 @@ class AuthenticationViewModel extends ChangeNotifier { if (data != null) { await _handleExistingImeiData(data); } else { - await _handleNewImeiRegistration(); + await handleNewImeiRegistration(); } } catch (e) { log("Error in onLoginPressed: $e"); @@ -199,6 +202,11 @@ class AuthenticationViewModel extends ChangeNotifier { } } + setIsInitialLoginNavigated(bool isInitialLoginNavigated) { + this.isInitialLoginNavigated = isInitialLoginNavigated; + notifyListeners(); + } + void onTermAccepted() { isTermsAccepted = !isTermsAccepted; notifyListeners(); @@ -216,7 +224,7 @@ class AuthenticationViewModel extends ChangeNotifier { _appState.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken); } - Future selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async { + Future selectDeviceImei({bool isNavigate = true, required Function(dynamic data) onSuccess, Function(String)? onError}) async { // LoadingUtils.showFullScreenLoading(); // String firebaseToken = _appState.deviceToken; String firebaseToken = await Utils.getStringFromPrefs(CacheConst.pushToken); @@ -231,7 +239,9 @@ class AuthenticationViewModel extends ChangeNotifier { // LoadingUtils.hideFullScreenLoader(); // await _errorHandlerService.handleError(failure: failure); LoaderBottomSheet.hideLoader(); - _navigationService.pushPage(page: LoginScreen()); + if (isNavigate) { + _navigationService.pushPage(page: LoginScreen()); + } }, (apiResponse) { // LoadingUtils.hideFullScreenLoader(); @@ -263,10 +273,13 @@ class AuthenticationViewModel extends ChangeNotifier { } } - Future _handleNewImeiRegistration() async { - await selectDeviceImei(onSuccess: (dynamic respData) async { - try { - if (respData != null) { + Future handleNewImeiRegistration({bool isNavigate = true}) async { + print("handleNewImeiRegistration called"); + await selectDeviceImei( + isNavigate: isNavigate, + onSuccess: (dynamic respData) async { + try { + if (respData != null) { dynamic data = await SelectDeviceByImeiRespModelElement.fromJson(respData.toJson()); _appState.setSelectDeviceByImeiRespModelElement(data); LoaderBottomSheet.hideLoader(); @@ -274,19 +287,24 @@ class AuthenticationViewModel extends ChangeNotifier { // TODO: Navigate to SavedLogin when available // SelectDeviceByImeiRespModelElement savedData = // SelectDeviceByImeiRespModelElement.fromJson(respData); - _navigationService.pushPage(page: SavedLogin()); - // _navigationService.pushPage(page: LoginScreen()); - } else { - print("print login........"); - LoaderBottomSheet.hideLoader(); - _navigationService.pushPage(page: LoginScreen()); - } - } catch (e) { - log("Error processing IMEI registration response: $e"); - LoaderBottomSheet.hideLoader(); - _navigationService.pushPage(page: LoginScreen()); - } - }, onError: (String error) { + if (!isInitialLoginNavigated) { + _navigationService.pushPage(page: SavedLogin()); + } + // _navigationService.pushPage(page: LoginScreen()); + } else { + if (isNavigate) { + LoaderBottomSheet.hideLoader(); + _navigationService.pushPage(page: LoginScreen()); + } + } + } catch (e) { + if (isNavigate) { + log("Error processing IMEI registration response: $e"); + LoaderBottomSheet.hideLoader(); + _navigationService.pushPage(page: LoginScreen()); + } + } + }, onError: (String error) { LoaderBottomSheet.hideLoader(); _dialogService.showErrorBottomSheet(message: error, onOkPressed: () {}); }); @@ -722,6 +740,7 @@ class AuthenticationViewModel extends ChangeNotifier { } Future navigateToHomeScreen() async { + setIsInitialLoginNavigated(true); getPatientBloodTypeNew(); Navigator.pushAndRemoveUntil( _navigationService.navigatorKey.currentContext!, @@ -1174,7 +1193,7 @@ class AuthenticationViewModel extends ChangeNotifier { (apiResponse) { if (apiResponse.messageStatus == 1 && apiResponse.data != null) { // Extract blood type from response - String? bloodType = apiResponse.data['GetPatientBloodType']; + String? bloodType = apiResponse.data['GetPatientBloodType'][0]["BloodType"]; if (bloodType != null && bloodType.isNotEmpty) { _appState.setUserBloodGroup = bloodType; log("Blood type updated from new API: $bloodType"); diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 88c9b21c..e43a49d5 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -334,7 +334,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { void filterDoctors(String query) { if (query.isEmpty) { filteredDoctorList = List.from(doctorsList); - // _groupDoctorsList(); + _groupDoctorsList(); setIsNearestAppointmentSelected(isNearestAppointmentSelected); notifyListeners(); return; diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart index fb80ca00..6835badb 100644 --- a/lib/features/lab/lab_view_model.dart +++ b/lib/features/lab/lab_view_model.dart @@ -848,6 +848,9 @@ class LabViewModel extends ChangeNotifier { Future getAiOverviewLabOrders({required PatientLabOrdersResponseModel labOrder, required String loadingText}) async { // LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time."); // LoadingUtils.showFullScreenLoader(loadingText: loadingText); + isLabAIAnalysisNeedsToBeShown = true; + notifyListeners(); + LoaderBottomSheet.showLoader( loadingText: loadingText, showCloseButton: true, @@ -875,26 +878,29 @@ class LabViewModel extends ChangeNotifier { final result = await labRepo.getPatientAiOverViewLabOrders(results); result.fold( (failure) async { - LoadingUtils.hideFullScreenLoader(); + LoaderBottomSheet.hideLoader(); if (isLabAIAnalysisNeedsToBeShown) { await errorHandlerService.handleError(failure: failure); } }, (apiResponse) { - LoadingUtils.hideFullScreenLoader(); + LoaderBottomSheet.hideLoader(); if (apiResponse.messageStatus == 2) { } else if (apiResponse.messageStatus == 1) { if (isLabAIAnalysisNeedsToBeShown) { labOrdersResponseByAi = apiResponse.data; navigationService.push( - MaterialPageRoute(builder: (_) => LabAiAnalysisDetailedPage()), + CustomPageRoute( + direction: AxisDirection.down, + page: LabAiAnalysisDetailedPage(), + ), ); } } }, ); - LoadingUtils.hideFullScreenLoader(); + // LoadingUtils.hideFullScreenLoader(); } Future getAiOverviewSingleLabResult({required String langId, required LabResult recentLabResult, required String loadingText}) async { diff --git a/lib/features/todo_section/todo_section_view_model.dart b/lib/features/todo_section/todo_section_view_model.dart index 0f6cc873..b14e4ead 100644 --- a/lib/features/todo_section/todo_section_view_model.dart +++ b/lib/features/todo_section/todo_section_view_model.dart @@ -13,13 +13,13 @@ class TodoSectionViewModel extends ChangeNotifier { String? notificationsCount = "0"; initializeTodoSectionViewModel() async { - if (isAncillaryOrdersNeedReloading) { - patientAncillaryOrdersList.clear(); - isAncillaryOrdersLoading = true; + // if (isAncillaryOrdersNeedReloading) { + patientAncillaryOrdersList.clear(); + isAncillaryOrdersLoading = true; isAncillaryDetailsProceduresLoading = true; notificationsCount = "0"; getPatientOnlineAncillaryOrderList(); - } + // } getPatientDashboard(); } @@ -63,13 +63,14 @@ class TodoSectionViewModel extends ChangeNotifier { } Future getPatientOnlineAncillaryOrderList({Function(dynamic)? onSuccess, Function(String)? onError}) async { - if (!isAncillaryOrdersNeedReloading) { - return; - } + // if (!isAncillaryOrdersNeedReloading) { + // return; + // } patientAncillaryOrdersList.clear(); isAncillaryOrdersLoading = true; notifyListeners(); + final result = await todoSectionRepo.getOnlineAncillaryOrderList(); result.fold( diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 56d71e33..82bc2ff8 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1651,5 +1651,16 @@ abstract class LocaleKeys { static const doctorRemovedFromFavourite = 'doctorRemovedFromFavourite'; static const addNewFavorite = 'addNewFavorite'; static const favourites = 'favourites'; + static const pendingAncillaryOrders = 'pendingAncillaryOrders'; + static const liveCarePermissions = 'liveCarePermissions'; + static const containsImage = 'containsImage'; + static const servicesSelected = 'servicesSelected'; + static const selectMedicalFileFromFamily = 'selectMedicalFileFromFamily'; + static const anyFileFromHMG = 'anyFileFromHMG'; + static const noDistance = 'noDistance'; + static const enterAmount = 'enterAmount'; + static const selectHospitalContinue = 'selectHospitalContinue'; + static const year = 'year'; + static const notifyPrescription = 'notifyPrescription'; } diff --git a/lib/main.dart b/lib/main.dart index 38dc539b..5f5ae201 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -130,7 +130,7 @@ void main() async { Locale('ar', 'SA'), ], path: 'assets/langs', - assetLoader: RemoteFileLoader(), + // assetLoader: RemoteFileLoader(), fallbackLocale: Locale('en', 'US'), child: MultiProvider(providers: [ ChangeNotifierProvider( diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index dde08085..165caacd 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -874,8 +874,9 @@ class _AppointmentDetailsPageState extends State { ? (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! || widget.patientAppointmentHistoryResponseModel.isExecludeDoctor! || - Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)) - ? CustomButton( + !Utils.isClinicAllowedForRebook(widget.patientAppointmentHistoryResponseModel.clinicID)) + ? SizedBox.shrink() + : CustomButton( text: LocaleKeys.rebookAppointment.tr(context: context), onPressed: () { openDoctorScheduleCalendar(); @@ -892,7 +893,6 @@ class _AppointmentDetailsPageState extends State { iconColor: Colors.white, iconSize: 18.h, ).paddingSymmetrical(16.h, 24.h) - : SizedBox.shrink() : CustomButton( text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction), onPressed: () { diff --git a/lib/presentation/appointments/my_appointments_page.dart b/lib/presentation/appointments/my_appointments_page.dart index 71bf30bf..2359a34b 100644 --- a/lib/presentation/appointments/my_appointments_page.dart +++ b/lib/presentation/appointments/my_appointments_page.dart @@ -191,7 +191,7 @@ class _MyAppointmentsPageState extends State { children: [ AppCustomChipWidget( labelText: - "${myAppointmentsVM.patientAppointmentsViewList[index].patientDoctorAppointmentList!.length} Appointments"), + "${myAppointmentsVM.patientAppointmentsViewList[index].patientDoctorAppointmentList!.length} ${LocaleKeys.appointments.tr(context: context)}", isEnglishOnly: true,), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart index 26b4526f..8b395e7b 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; @@ -7,6 +8,7 @@ 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/my_appointments/models/resp_models/doctor_list_api_response.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; @@ -95,7 +97,7 @@ class HospitalListItem extends StatelessWidget { child: Row( children: [ AppCustomChipWidget( - labelText: "Distance not available", + labelText: LocaleKeys.noDistance.tr(), textColor: AppColors.blackColor, ), // SizedBox( diff --git a/lib/presentation/authentication/saved_login_screen.dart b/lib/presentation/authentication/saved_login_screen.dart index dcb2c765..9ae9174e 100644 --- a/lib/presentation/authentication/saved_login_screen.dart +++ b/lib/presentation/authentication/saved_login_screen.dart @@ -66,6 +66,7 @@ class _SavedLogin extends State { appBar: CustomAppBar( onBackPressed: () { Navigator.of(context).pop(); + authVm.setIsInitialLoginNavigated(true); }, onLanguageChanged: (value) { context.setLocale(value == 'en' ? Locale('en', 'US') : Locale('ar', 'SA')); diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart index 12b09041..917f334a 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart @@ -75,14 +75,20 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true), + "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true, isEnglishOnly: true), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 3.h, runSpacing: 4.h, children: [ - AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} ${LocaleKeys.yearsOld.tr(context: context)}"), + AppCustomChipWidget( + richText: Row( + children: [ + "${appState.getAuthenticatedUser()!.age} ".toText10(color: AppColors.blackColor, isEnglishOnly: true), + LocaleKeys.yearsOld.tr(context: context).toText10(color: AppColors.blackColor), + ], + ),), AppCustomChipWidget(labelText: "${LocaleKeys.gender.tr(context: context)}: ${appState.getAuthenticatedUser()?.gender == 1 ? LocaleKeys.malE.tr(context: context) : LocaleKeys.femaleGender.tr(context: context)}"), ], ), @@ -208,7 +214,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true), - Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount!.toText16(isBold: true), AppColors.blackColor, 13, + Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount!.toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, isSaudiCurrency: immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال"), ], @@ -218,7 +224,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor), Utils.getPaymentAmountWithSymbol( - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13, + immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), ], @@ -228,7 +234,7 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox(width: 200.h, child: Utils.getPaymentMethods()), - Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true), AppColors.blackColor, 17, + Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), ], @@ -374,10 +380,11 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { final permanent = missing.where((p) => (statuses[p]?.isPermanentlyDenied ?? false) || (statuses[p]?.isRestricted ?? false)).toList(); if (permanent.isNotEmpty) { final names = permanent.map((p) => LiveCarePermissionService.instance.friendlyName(p)).join(' and '); - final message = permanent.length == 1 ? '$names permission is permanently denied. Open app settings to allow it.' : '$names permissions are permanently denied. Open app settings to allow them.'; + // final message = permanent.length == 1 ? '$names permission is permanently denied. Open app settings to allow it.' : '$names permissions are permanently denied. Open app settings to allow them.'; + final message = LocaleKeys.liveCarePermissions.tr(); await LiveCarePermissionService.instance.showOpenSettingsDialog( context, - title: "Permissions Required", + title: LocaleKeys.permissionsProfile.tr(), message: message, ); return false; diff --git a/lib/presentation/book_appointment/livecare/widgets/livecare_clinic_card.dart b/lib/presentation/book_appointment/livecare/widgets/livecare_clinic_card.dart index 291c2245..5ce3b177 100644 --- a/lib/presentation/book_appointment/livecare/widgets/livecare_clinic_card.dart +++ b/lib/presentation/book_appointment/livecare/widgets/livecare_clinic_card.dart @@ -27,10 +27,11 @@ class LiveCareClinicCard extends StatelessWidget { GetLiveCareClinicListResponseModel liveCareClinicListResponseModel; bool isLoading; ImmediateLiveCareViewModel immediateLiveCareViewModel; + late AppState appState; @override Widget build(BuildContext context) { - AppState appState = getIt.get(); + appState = getIt.get(); return Container( padding: EdgeInsets.all(16.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration( @@ -219,19 +220,24 @@ class LiveCareClinicCard extends StatelessWidget { icon: AppAssets.appointment_time_icon, iconColor: AppColors.textColor, labelText: subTitle.split("to").first.trim(), + isEnglishOnly: true, ), SizedBox(width: 8.w), - Utils.buildSvgWithAssets( - icon: AppAssets.arrow_forward, - height: 24.h, - width: 24.h, - iconColor: AppColors.textColor, + Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.arrow_forward, + height: 24.h, + width: 24.h, + iconColor: AppColors.textColor, + ), ), SizedBox(width: 8.w), AppCustomChipWidget( icon: AppAssets.appointment_time_icon, iconColor: AppColors.textColor, labelText: subTitle.split("to")[1].trim(), + isEnglishOnly: true, ), ], ), diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index 6812a349..0db1fb38 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -1064,24 +1064,27 @@ class _SelectClinicPageState extends State { ); } } else { - if (clinic.clinicID == 253) { - LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context)); - await bookAppointmentsViewModel.getLaserHospitals( - onSuccess: (_) { - LoaderBottomSheet.hideLoader(); - _showLaserHospitalBottomSheet(); - }, - onError: (err) { - LoaderBottomSheet.hideLoader(); - }, - ); - return; - } + // if (clinic.clinicID == 253) { + // LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context)); + // await bookAppointmentsViewModel.getLaserHospitals( + // onSuccess: (_) { + // LoaderBottomSheet.hideLoader(); + // _showLaserHospitalBottomSheet(); + // }, + // onError: (err) { + // LoaderBottomSheet.hideLoader(); + // }, + // ); + // return; + // } var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; if (clinic.clinicID == 17) { regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; } + // if (clinic.clinicID == 253) { + // bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; + // } openRegionListBottomSheet(context, bottomSheetType); } } @@ -1122,10 +1125,19 @@ class _SelectClinicPageState extends State { regionalViewModel.handleLastStepForRegion(); } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); - regionalViewModel.handleLastStepForClinic(); + var appointmentsViewModel = Provider.of(context, listen: false); + if (appointmentsViewModel.selectedClinic.clinicID == 253) { + appointmentsViewModel.setProjectID(regionalViewModel.selectedHospital?.patientDoctorAppointmentList!.first.iD?.toString() ?? ""); + appointmentsViewModel.resetLaserData(); + appointmentsViewModel.getLaserClinic(); + regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); + } else { + regionalViewModel.handleLastStepForClinic(); + } } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { var appointmentsViewModel = Provider.of(context, listen: false); regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + appointmentsViewModel.setProjectID(regionalViewModel.selectedHospital?.hospitalList.first.iD?.toString() ?? ""); regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); } }, @@ -1157,12 +1169,18 @@ class _SelectClinicPageState extends State { } } - if (bookAppointmentsViewModel.selectedClinic.clinicID == 253) { - { - bookAppointmentsViewModel.resetLaserData(); - bookAppointmentsViewModel.getLaserClinic(); - } - } + // if (bookAppointmentsViewModel.selectedClinic.clinicID == 253) { + // // { + // // bookAppointmentsViewModel.resetLaserData(); + // // bookAppointmentsViewModel.getLaserClinic(); + // // Navigator.push( + // // context, + // // CustomPageRoute( + // // page: LaserAppointment(), + // // ), + // // ); + // // } + // } bookAppointmentsViewModel.setProjectID(id); return SizedBox.shrink(); } else { diff --git a/lib/presentation/book_appointment/widgets/doctor_card.dart b/lib/presentation/book_appointment/widgets/doctor_card.dart index 19d52a92..25458b74 100644 --- a/lib/presentation/book_appointment/widgets/doctor_card.dart +++ b/lib/presentation/book_appointment/widgets/doctor_card.dart @@ -105,16 +105,17 @@ class DoctorCard extends StatelessWidget { SizedBox( child: (isLoading ? "Consultant Cardiologist" - : getIt.get().isArabic() + : (getIt.get().isArabic() && doctorsListResponseModel.specialityN != null) ? doctorsListResponseModel.specialityN!.isNotEmpty ? (doctorsListResponseModel.specialityN!.first.length > 32 ? '${doctorsListResponseModel.specialityN!.first.substring(0, 32)}...' : doctorsListResponseModel.specialityN!.first) : "" - : doctorsListResponseModel.speciality!.isNotEmpty + : doctorsListResponseModel.speciality != null ? + doctorsListResponseModel.speciality!.isNotEmpty ? (doctorsListResponseModel.speciality!.first.length > 32 ? '${doctorsListResponseModel.speciality!.first.substring(0, 32)}...' - : doctorsListResponseModel.speciality!.first) + : doctorsListResponseModel.speciality!.first) : "" : "") .toString() .toText12(fontWeight: FontWeight.w500, color: AppColors.textColor, maxLine: 2, isEnglishOnly: true) diff --git a/lib/presentation/book_appointment/widgets/doctor_rating_details.dart b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart index c146820d..10c35072 100644 --- a/lib/presentation/book_appointment/widgets/doctor_rating_details.dart +++ b/lib/presentation/book_appointment/widgets/doctor_rating_details.dart @@ -131,6 +131,7 @@ class DoctorRatingDialog extends StatelessWidget { Text( averageRating.toString(), style: TextStyle( + fontFamily: "Poppins", fontSize: 48.f, fontWeight: FontWeight.w700, color: averageRating == 0 || averageRating == 0.0 ? AppColors.textColor : AppColors.whiteColor, @@ -168,7 +169,7 @@ class DoctorRatingDialog extends StatelessWidget { // color: averageRating == 0 || averageRating == 0.0 ? AppColors.textColor : AppColors.whiteColor, // ), // ), - ), + ).paddingSymmetrical(12.h, 0.h), ], ), ), @@ -236,6 +237,7 @@ class DoctorRatingDialog extends StatelessWidget { '$percent%', textAlign: TextAlign.right, style: TextStyle( + fontFamily: "Poppins", fontSize: 14, fontWeight: FontWeight.w600, color: AppColors.ratingPercentageTextColor, diff --git a/lib/presentation/comprehensive_checkup/widgets/cmc_hospital_list_item.dart b/lib/presentation/comprehensive_checkup/widgets/cmc_hospital_list_item.dart index 25cd5068..b8ac54cc 100644 --- a/lib/presentation/comprehensive_checkup/widgets/cmc_hospital_list_item.dart +++ b/lib/presentation/comprehensive_checkup/widgets/cmc_hospital_list_item.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; @@ -9,6 +10,7 @@ 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/my_appointments/models/resp_models/hospital_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; @@ -107,7 +109,7 @@ class CmcHospitalListItem extends StatelessWidget { Visibility( visible: (hospital.distanceInKilometers == null || hospital.distanceInKilometers == 0), child: AppCustomChipWidget( - labelText: " Distance not available", + labelText: LocaleKeys.noDistance.tr(), textColor: AppColors.blackColor, ), ), diff --git a/lib/presentation/contact_us/feedback_page.dart b/lib/presentation/contact_us/feedback_page.dart index 93954af9..2c216cc1 100644 --- a/lib/presentation/contact_us/feedback_page.dart +++ b/lib/presentation/contact_us/feedback_page.dart @@ -286,10 +286,13 @@ class FeedbackPage extends StatelessWidget { children: [ AppCustomChipWidget(labelText: contactUsViewModel.patientFeedbackSelectedAppointment!.clinicName!).toShimmer2(isShow: false), AppCustomChipWidget(labelText: contactUsViewModel.patientFeedbackSelectedAppointment!.projectName!).toShimmer2(isShow: false), - AppCustomChipWidget( - icon: AppAssets.appointment_calendar_icon, - labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(contactUsViewModel.patientFeedbackSelectedAppointment!.appointmentDate), false), - ).toShimmer2(isShow: false), + Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + icon: AppAssets.appointment_calendar_icon, + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(contactUsViewModel.patientFeedbackSelectedAppointment!.appointmentDate), false), + isEnglishOnly: true).toShimmer2(isShow: false), + ), ], ), ], diff --git a/lib/presentation/habib_wallet/recharge_wallet_page.dart b/lib/presentation/habib_wallet/recharge_wallet_page.dart index 74c0a69d..ba58f9fd 100644 --- a/lib/presentation/habib_wallet/recharge_wallet_page.dart +++ b/lib/presentation/habib_wallet/recharge_wallet_page.dart @@ -23,6 +23,8 @@ import 'package:provider/provider.dart'; import 'widgets/select-medical_file.dart'; +import 'dart:ui' as ui; + class RechargeWalletPage extends StatefulWidget { const RechargeWalletPage({super.key}); @@ -153,7 +155,7 @@ class _RechargeWalletPageState extends State { titleWidget: Consumer(builder: (context, habibWalletVM, child) { return habibWalletVM.currentIndex != 0 ? IconButton( - icon: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 24.h, height: 24.h), + icon: Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.arrow_back, width: 24.h, height: 24.h)), padding: EdgeInsets.zero, onPressed: () => habibWalletVM.setCurrentIndex(0), highlightColor: Colors.transparent, @@ -250,7 +252,7 @@ class _RechargeWalletPageState extends State { if (amountTextController.text.isEmpty) { showCommonBottomSheetWithoutHeight( context, - child: Utils.getErrorWidget(loadingText: "Please enter amount to continue."), + child: Utils.getErrorWidget(loadingText: LocaleKeys.enterAmount.tr(context: context)), callBackFunc: () { textFocusNode.requestFocus(); }, @@ -260,7 +262,7 @@ class _RechargeWalletPageState extends State { } else if (habibWalletVM.selectedHospital == null) { showCommonBottomSheetWithoutHeight( context, - child: Utils.getErrorWidget(loadingText: "Please select hospital to continue."), + child: Utils.getErrorWidget(loadingText: LocaleKeys.selectHospitalForAdvancePayment.tr(context: context)), callBackFunc: () { textFocusNode.requestFocus(); }, diff --git a/lib/presentation/habib_wallet/widgets/hospital_list_item.dart b/lib/presentation/habib_wallet/widgets/hospital_list_item.dart index 67e174a3..fe5172e6 100644 --- a/lib/presentation/habib_wallet/widgets/hospital_list_item.dart +++ b/lib/presentation/habib_wallet/widgets/hospital_list_item.dart @@ -1,12 +1,18 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.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/my_appointments/models/resp_models/hospital_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; + +import 'dart:ui' as ui; class HospitalListItemAdvancePayment extends StatelessWidget { final HospitalsModel hospitalModel; @@ -32,7 +38,7 @@ class HospitalListItemAdvancePayment extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, spacing: 8.h, - children: [hospitalName], + children: [hospitalName, distanceInfo], ), ), Transform.flip( @@ -68,4 +74,45 @@ class HospitalListItemAdvancePayment extends StatelessWidget { ) ], ); + + Widget get distanceInfo => Row( + spacing: 4.w, + children: [ + Visibility( + visible: (hospitalModel.distanceInKilometers != 0), + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + labelText: "${hospitalModel.distanceInKilometers ?? ""} KMs", + deleteIcon: AppAssets.location_red, + deleteIconSize: Size(9, 12), + backgroundColor: AppColors.secondaryLightRedColor, + textColor: AppColors.errorColor, + isEnglishOnly: true, + ), + ), + ), + Visibility( + visible: (hospitalModel.distanceInKilometers == 0), + child: Row( + children: [ + AppCustomChipWidget( + labelText: LocaleKeys.noDistance.tr(), + textColor: AppColors.blackColor, + ), + // SizedBox( + // width: 8.h, + // ) + ], + )), + // Visibility( + // visible: !isLocationEnabled, + // child: AppCustomChipWidget( + // labelText: "Location turned off", + // deleteIcon: AppAssets.location_unavailable, + // deleteIconSize: Size(9.w, 12.h), + // textColor: AppColors.blackColor, + // )), + ], + ); } diff --git a/lib/presentation/habib_wallet/widgets/select-medical_file.dart b/lib/presentation/habib_wallet/widgets/select-medical_file.dart index 6fed6522..4a9e4c0a 100644 --- a/lib/presentation/habib_wallet/widgets/select-medical_file.dart +++ b/lib/presentation/habib_wallet/widgets/select-medical_file.dart @@ -78,9 +78,10 @@ class _MultiPageBottomSheetState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Enter File Number".toText20(weight: FontWeight.w600), + LocaleKeys.pleaseEnterAFileNumber.tr(context: context).toText20(weight: FontWeight.w600), SizedBox(height: 12.h), TextInputWidget( + fontFamily: "Poppins", labelText: LocaleKeys.fileNumber.tr(), hintText: "xxxxxxxxx", controller: fileNumberEditingController, @@ -140,10 +141,15 @@ class _MultiPageBottomSheetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.myMedicalFile.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), - "${LocaleKeys.fileno.tr(context: context)}: ${appState.getAuthenticatedUser()!.patientId}".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), + Row( + children: [ + "${LocaleKeys.fileno.tr(context: context)}: ".toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500), + appState.getAuthenticatedUser()!.patientId.toString().toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500, isEnglishOnly: true), + ], + ), ], ), - Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), + Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), ], ).paddingAll(16.h), ).onPress(() { @@ -167,10 +173,10 @@ class _MultiPageBottomSheetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.familyTitle.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), - "Select a medical file from your family".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), + LocaleKeys.selectMedicalFileFromFamily.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), ], ), - Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), + Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), ], ).paddingAll(16.h), ).onPress(() { @@ -205,10 +211,10 @@ class _MultiPageBottomSheetState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.otherAccount.tr(context: context).toText16(color: AppColors.textColor, weight: FontWeight.w500), - "Any active medical file from HMG".toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), + LocaleKeys.anyFileFromHMG.tr(context: context).toText14(color: AppColors.greyTextColor, weight: FontWeight.w500), ], ), - Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h), + Transform.flip(flipX: appState.isArabic(), child: Utils.buildSvgWithAssets(icon: AppAssets.forward_chevron_icon, iconColor: AppColors.textColor, width: 15.h, height: 15.h)), ], ).paddingAll(16.h), ).onPress(() { diff --git a/lib/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart b/lib/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart index da374a04..5486b43f 100644 --- a/lib/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart +++ b/lib/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart @@ -1,34 +1,157 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/location_util.dart'; +import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.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/habib_wallet/habib_wallet_view_model.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/hospital_list_item.dart'; import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; -class SelectHospitalBottomSheet extends StatelessWidget { +class SelectHospitalBottomSheet extends StatefulWidget { + const SelectHospitalBottomSheet({super.key}); + + @override + State createState() => _SelectHospitalBottomSheetState(); +} + +class _SelectHospitalBottomSheetState extends State { late HabibWalletViewModel habibWalletVM; final TextEditingController searchText = TextEditingController(); + bool sortByLocation = false; + bool isLoading = false; + List displayList = []; - SelectHospitalBottomSheet({super.key}); + @override + void initState() { + super.initState(); + final appState = getIt.get(); + sortByLocation = (appState.userLat != 0.0) && (appState.userLong != 0.0); + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateDisplayList(); + }); + } + + void _updateDisplayList() { + final appState = getIt.get(); + final hospitals = List.from(habibWalletVM.advancePaymentHospitals); + + if (sortByLocation && appState.userLat != 0.0 && appState.userLong != 0.0) { + hospitals.sort((a, b) { + final distA = (a.latitude != null && a.longitude != null) + ? DoctorMapper.calculateDistance(appState.userLat, appState.userLong, double.parse(a.latitude!), double.parse(a.longitude!)) + : double.infinity; + final distB = (b.latitude != null && b.longitude != null) + ? DoctorMapper.calculateDistance(appState.userLat, appState.userLong, double.parse(b.latitude!), double.parse(b.longitude!)) + : double.infinity; + return distA.compareTo(distB); + }); + } + + setState(() { + displayList = hospitals; + isLoading = false; + }); + } + + void _refreshHospitalListAfterApi() { + void listener() { + if (habibWalletVM.advancePaymentHospitals.isNotEmpty) { + habibWalletVM.removeListener(listener); + _updateDisplayList(); + } + } + habibWalletVM.addListener(listener); + habibWalletVM.getProjectsList(); + } + + void _handleSortByLocationToggle(bool value) { + if (value) { + final locationUtils = getIt.get(); + locationUtils.getLocation( + isShowConfirmDialog: true, + onSuccess: (latLng) { + setState(() { + sortByLocation = true; + isLoading = true; + }); + _refreshHospitalListAfterApi(); + }, + onFailure: () { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.of(context).pop(); + }, + onConfirmTap: () async { + Navigator.of(context).pop(); + openAppSettings(); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + setState(() { + sortByLocation = false; + }); + }, + onLocationDeniedForever: () { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.notice.tr(context: context), + context, + child: Utils.getWarningWidget( + loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context), + isShowActionButtons: true, + onCancelTap: () { + Navigator.of(context).pop(); + }, + onConfirmTap: () async { + Navigator.of(context).pop(); + openAppSettings(); + }), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + setState(() { + sortByLocation = false; + }); + }, + ); + } else { + final appState = getIt.get(); + appState.resetLocation(); + setState(() { + sortByLocation = false; + isLoading = true; + }); + _refreshHospitalListAfterApi(); + } + } @override Widget build(BuildContext context) { habibWalletVM = Provider.of(context, listen: false); + if (displayList.isEmpty && habibWalletVM.advancePaymentHospitals.isNotEmpty) { + displayList = List.from(habibWalletVM.advancePaymentHospitals); + } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Text( - // LocaleKeys.selectHospital.tr(), - // style: TextStyle( - // fontSize: 21, - // fontWeight: FontWeight.w600, - // color: AppColors.blackColor, - // ), - // ), Text( LocaleKeys.selectHospitalForAdvancePayment.tr(context: context), style: TextStyle( @@ -38,48 +161,55 @@ class SelectHospitalBottomSheet extends StatelessWidget { ), ), SizedBox(height: 16.h), - // TextInputWidget( - // labelText: LocaleKeys.search.tr(), - // hintText: "Search Hospital".tr(), - // controller: searchText, - // onChange: (value) { - // // appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType == - // // FacilitySelection.HMG.name); - // }, - // isEnable: true, - // prefix: null, - // autoFocus: false, - // isBorderAllowed: false, - // keyboardType: TextInputType.text, - // isAllowLeadingIcon: true, - // selectionType: SelectionTypeEnum.search, - // padding: EdgeInsets.symmetric( - // vertical: ResponsiveExtension(10).h, - // horizontal: ResponsiveExtension(15).h, - // ), - // ), - // SizedBox(height: 24.h), - // TypeSelectionWidget( - // hmcCount: "0", - // hmgCount: "0", - // ), - // SizedBox(height: 21.h), - SizedBox( + Padding( + padding: EdgeInsets.symmetric(horizontal: 4.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.location, iconColor: AppColors.greyTextColor, width: 18.h, height: 18.h), + SizedBox(width: 8.w), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.sortByLocation.tr(context: context).toText14(isBold: true), + LocaleKeys.sortByNearestLocation.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500), + ], + ), + ], + ), + Switch( + value: sortByLocation, + onChanged: _handleSortByLocationToggle, + activeThumbColor: AppColors.successColor, + activeTrackColor: AppColors.successColor.withValues(alpha: 0.15), + ), + ], + ), + ), + SizedBox(height: 8.h), + isLoading + ? SizedBox( + height: MediaQuery.sizeOf(context).height * .4, + child: Center(child: Utils.getLoadingWidget()), + ) + : SizedBox( height: MediaQuery.sizeOf(context).height * .4, child: ListView.separated( itemBuilder: (_, index) { return HospitalListItemAdvancePayment( - hospitalModel: habibWalletVM.advancePaymentHospitals[index], - isLocationEnabled: false, + hospitalModel: displayList[index], + isLocationEnabled: sortByLocation, ).onPress(() { - habibWalletVM.setSelectedHospital(habibWalletVM.advancePaymentHospitals[index]); + habibWalletVM.setSelectedHospital(displayList[index]); Navigator.of(context).pop(); }); }, separatorBuilder: (_, __) => SizedBox( height: 16.h, ), - itemCount: habibWalletVM.advancePaymentHospitals.length), + itemCount: displayList.length), ) ], ); diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index eae47675..498d24c4 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -55,6 +55,7 @@ import 'package:hmg_patient_app_new/presentation/notifications/notifications_lis import 'package:hmg_patient_app_new/presentation/profile_settings/profile_settings.dart'; import 'package:hmg_patient_app_new/presentation/rate_appointment/rate_appointment_doctor.dart'; import 'package:hmg_patient_app_new/presentation/todo_section/ancillary_procedures_details_page.dart'; +import 'package:hmg_patient_app_new/presentation/todo_section/todo_page.dart'; import 'package:hmg_patient_app_new/presentation/todo_section/widgets/ancillary_orders_list.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/cache_service.dart'; @@ -65,6 +66,7 @@ import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/countdown_timer.dart'; +import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; import 'package:provider/provider.dart'; @@ -117,7 +119,12 @@ class _LandingPageState extends State { showQuickLogin(context); }); } - scheduleMicrotask(() { + scheduleMicrotask(() async { + if (!appState.isAuthenticated) { + // LoaderBottomSheet.showLoader(); + await authVM.handleNewImeiRegistration(isNavigate: false); + } + if (appState.isAuthenticated) { habibWalletVM.initHabibWalletProvider(); habibWalletVM.getPatientBalanceAmount(); @@ -205,13 +212,15 @@ class _LandingPageState extends State { ); }, name: ('${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}'), - imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, + // imageUrl: appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.maleImg : AppAssets.femaleImg, + imageUrl: appState.getAuthenticatedUser()?.gender == 1 + ? ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyBoyImg : AppAssets.maleImg) + : ((appState.getAuthenticatedUser()?.age ?? 0) < 7 ? AppAssets.babyGirlImg : AppAssets.femaleImg), ).expanded : CustomButton( text: LocaleKeys.loginOrRegister.tr(context: context), onPressed: () async { await authVM.onLoginPressed(); - // Navigator.pushReplacementNamed( // // context, // context, @@ -449,7 +458,8 @@ class _LandingPageState extends State { loop: false, itemWidth: MediaQuery.of(context).size.width - 48.h, indicatorLayout: PageIndicatorLayout.COLOR, - axisDirection: getIt.get().isArabic() ? AxisDirection.left : AxisDirection.right, + // axisDirection: getIt.get().isArabic() ? AxisDirection.left : AxisDirection.right, + axisDirection: appState.isArabic() ? AxisDirection.left : AxisDirection.right, controller: _controller, itemHeight: 255.h + 20, // extra space for shadow @@ -583,6 +593,46 @@ class _LandingPageState extends State { decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), child: Column( children: [ + todoSectionViewModel.patientAncillaryOrdersList.isNotEmpty + ? Container( + height: 50.h, + decoration: ShapeDecoration( + color: AppColors.eReferralCardColor.withAlpha(50), + shape: SmoothRectangleBorder( + borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)), + smoothness: 1, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.pendingAncillaryOrders + .tr(context: context) + .toText14(color: AppColors.eReferralCardColor, weight: FontWeight.w500) + .paddingSymmetrical(24.h, 0.h), + CustomButton( + text: LocaleKeys.view.tr(context: context), + onPressed: () { + getIt.get().setIsAncillaryOrdersNeedReloading(true); + Navigator.of(context).push( + CustomPageRoute( + page: ToDoPage(), + ), + ); + }, + backgroundColor: AppColors.eReferralCardColor, + borderColor: AppColors.eReferralCardColor, + textColor: AppColors.whiteColor, + fontSize: 10.f, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(15, 0, 15, 0), + height: 30.h, + ).paddingSymmetrical(24.h, 0.h), + ], + ), + ) + : SizedBox.shrink(), SizedBox( height: 92.h + 32.h - 4.h, child: RawScrollbar( @@ -837,11 +887,11 @@ class _LandingPageState extends State { ); } - if (todoSectionViewModel.patientAncillaryOrdersList.isNotEmpty) { - return _buildAncillaryOrderCardWrapper( - todoSectionViewModel.patientAncillaryOrdersList.first, - ); - } + // if (todoSectionViewModel.patientAncillaryOrdersList.isNotEmpty) { + // return _buildAncillaryOrderCardWrapper( + // todoSectionViewModel.patientAncillaryOrdersList.first, + // ); + // } return _buildAppointmentCardWrapper( myAppointmentsViewModel.patientAppointmentsHistoryList[1], @@ -854,9 +904,9 @@ class _LandingPageState extends State { final hasAncillaryOrders = todoSectionViewModel.patientAncillaryOrdersList.isNotEmpty; if (hasQueueOrLiveCare && hasAncillaryOrders) { - return _buildAncillaryOrderCardWrapper( - todoSectionViewModel.patientAncillaryOrdersList.first, - ); + // return _buildAncillaryOrderCardWrapper( + // todoSectionViewModel.patientAncillaryOrdersList.first, + // ); } return _buildAppointmentCardWrapper( diff --git a/lib/presentation/home/widgets/large_service_card.dart b/lib/presentation/home/widgets/large_service_card.dart index 5428e21d..76785f08 100644 --- a/lib/presentation/home/widgets/large_service_card.dart +++ b/lib/presentation/home/widgets/large_service_card.dart @@ -8,6 +8,7 @@ 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/features/my_appointments/my_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'; @@ -128,6 +129,7 @@ class LargeServiceCard extends StatelessWidget { switch (serviceCardData.serviceName) { case "livecare": { + getIt.get().getPatientFavouriteDoctors(); getIt.get().onTabChanged(1); Navigator.of(getIt.get().navigatorKey.currentContext!).push( CustomPageRoute( diff --git a/lib/presentation/home_health_care/hhc_procedures_page.dart b/lib/presentation/home_health_care/hhc_procedures_page.dart index 88766ea0..6bb40a9c 100644 --- a/lib/presentation/home_health_care/hhc_procedures_page.dart +++ b/lib/presentation/home_health_care/hhc_procedures_page.dart @@ -357,13 +357,12 @@ class _HhcProceduresPageState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - LocaleKeys.selectedServices.tr(context: context).toText12( - color: AppColors.textColorLight, - fontWeight: FontWeight.w600, - ), - "${hmgServicesViewModel.selectedHhcServices.length} service(s) selected".toText14( - isBold: true, - weight: FontWeight.bold, + LocaleKeys.selectedServices.tr(context: context).toText12(color: AppColors.textColorLight, fontWeight: FontWeight.w600), + Row( + children: [ + ("${hmgServicesViewModel.selectedHhcServices.length} ").toText14(isBold: true, weight: FontWeight.bold, isEnglishOnly: true), + LocaleKeys.servicesSelected.tr(context: context).toText14(isBold: true, weight: FontWeight.bold), + ], ), ], ), diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart index 16cbac20..bfd5d53f 100644 --- a/lib/presentation/insurance/widgets/patient_insurance_card.dart +++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart @@ -135,10 +135,10 @@ class PatientInsuranceCard extends StatelessWidget { ], ), SizedBox(height: 12.h), - insuranceCardDetailsModel.groupName!.toText12(isBold: true), + insuranceCardDetailsModel.groupName!.toText12(isBold: true, isEnglishOnly: true), Row( children: [ - (insuranceCardDetailsModel.companyName!.length > 40 ? "${insuranceCardDetailsModel.companyName!.substring(0, 40)}..." : insuranceCardDetailsModel.companyName!).toText12(isBold: true), + (insuranceCardDetailsModel.companyName!.length > 40 ? "${insuranceCardDetailsModel.companyName!.substring(0, 40)}..." : insuranceCardDetailsModel.companyName!).toText12(isBold: true, isEnglishOnly: true), SizedBox( width: 6.h, ), @@ -149,7 +149,7 @@ class PatientInsuranceCard extends StatelessWidget { borderRadius: 50.r, ), child: ((insuranceCardDetailsModel.subCategoryDesc ?? "").length > 10 ? (insuranceCardDetailsModel.subCategoryDesc ?? "").substring(0, 10) : (insuranceCardDetailsModel.subCategoryDesc ?? "")) - .toText8(isBold: true, color: AppColors.whiteColor), + .toText8(isBold: true, color: AppColors.whiteColor, isEnglishOnly: true), ), ], ), diff --git a/lib/presentation/lab/lab_orders_page.dart b/lib/presentation/lab/lab_orders_page.dart index b3ef6cde..9f491de2 100644 --- a/lib/presentation/lab/lab_orders_page.dart +++ b/lib/presentation/lab/lab_orders_page.dart @@ -1 +1 @@ -import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.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/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.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/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ // CustomButton( // text: LocaleKeys.byClinic.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(true); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // fontSize: 12.f, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: LocaleKeys.byHospital.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(false); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // fontSize: 12, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, isEnglishOnly: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrders.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.filteredLabOrders.length, itemBuilder: (context, index) { final group = labViewModel.filteredLabOrders[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( labelText: "${group.testDetails!.length} ${LocaleKeys.tests.tr(context: context)}", backgroundColor: AppColors.successColor.withOpacity(0.1), textColor: AppColors.successColor, ), AppCustomChipWidget( labelText: "${_appState.isArabic() ? group.isInOutPatientDescriptionN : group.isInOutPatientDescription}", backgroundColor: AppColors.warningColorYellow.withOpacity(0.1), textColor: AppColors.warningColorYellow, ) ], ), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (group.doctorName ?? group.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(group.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: (group.projectName ?? ""), ), AppCustomChipWidget( labelText: (group.clinicDescription ?? ""), ), ], ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: Column( children: [ ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "• ${order.testDetails![index].description!}".toText14(weight: FontWeight.w500), SizedBox(height: 4.h), order.testDetails![index].testDescriptionEn!.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Image.network( // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // width: 24.w, // height: 24.h, // fit: BoxFit.cover, // ).circle(100), // SizedBox(width: 8.h), // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), // ], // ), // SizedBox(height: 8.h), // Wrap( // direction: Axis.horizontal, // spacing: 4.h, // runSpacing: 4.h, // children: [ // AppCustomChipWidget( // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, // ), // Directionality( // textDirection: ui.TextDirection.ltr, // child: AppCustomChipWidget( // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // isEnglishOnly: true, // )), // AppCustomChipWidget( // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), // ), // ], // ), // // Row( // // children: [ // // CustomButton( // // text: ("Order No: ".needTranslation + order.orderNo!), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // SizedBox(width: 8.h), // // CustomButton( // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // // SizedBox(height: 8.h), // // Row( // // children: [ // // CustomButton( // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // SizedBox(height: 12.h), // Row( // children: [ // Expanded(flex: 2, child: SizedBox()), // // Expanded( // // flex: 1, // // child: Container( // // height: 40.h, // // width: 40.w, // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // // color: AppColors.textColor, // // borderRadius: 12, // // ), // // child: Padding( // // padding: EdgeInsets.all(12.h), // // child: Transform.flip( // // flipX: _appState.isArabic(), // // child: Utils.buildSvgWithAssets( // // icon: AppAssets.forward_arrow_icon_small, // // iconColor: AppColors.whiteColor, // // fit: BoxFit.contain, // // ), // // ), // // ), // // ).onPress(() { // // model.currentlySelectedPatientOrder = order; // // labProvider.getPatientLabResultByHospital(order); // // labProvider.getPatientSpecialResult(order); // // Navigator.of(context).push( // // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // // ); // // }), // // ) // // Expanded( // flex: 2, // child: CustomButton( // icon: AppAssets.view_report_icon, // iconColor: AppColors.primaryRedColor, // iconSize: 16.h, // text: LocaleKeys.viewResults.tr(context: context), // onPressed: () { // labViewModel.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }, // backgroundColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor, // textColor: AppColors.primaryRedColor, // fontSize: 14, // fontWeight: FontWeight.w500, // borderRadius: 12, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // ) // ], // ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.testDetails!.length > 3 ? 3 : group.testDetails!.length), SizedBox(height: 16.h), CustomButton( text: "${LocaleKeys.viewResults.tr()} (${group.testDetails!.length})", onPressed: () { labProvider.currentlySelectedPatientOrder = group; labProvider.getPatientLabResultByHospital(group); labProvider.getPatientSpecialResult(group); Navigator.of(context).push( CustomPageRoute( page: LabResultByClinic(labOrder: group), ), ); }, backgroundColor: AppColors.infoColor.withAlpha(20), borderColor: AppColors.infoColor.withAlpha(0), textColor: AppColors.infoColor, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, fontWeight: FontWeight.w500, borderRadius: 12.r, padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), height: 40.h, iconSize: 14.h, icon: AppAssets.view_report_icon, iconColor: AppColors.infoColor, ), SizedBox(height: 16.h), ], ), ) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.filteredIndexedCharacterForUniqueTest, details: labViewModel.filteredUniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file +import 'dart:async'; import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_state.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/lab/lab_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart'; import 'package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart'; import 'package:hmg_patient_app_new/presentation/lab/search_lab_report.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.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/appbar/collapsing_toolbar.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import 'alphabeticScroll.dart'; import 'dart:ui' as ui; class LabOrdersPage extends StatefulWidget { const LabOrdersPage({super.key}); @override State createState() => _LabOrdersPageState(); } class _LabOrdersPageState extends State { late LabViewModel labProvider; late DateRangeSelectorRangeViewModel rangeViewModel; late AppState _appState; List?> labSuggestions = []; int? expandedIndex; String? selectedFilterText = ''; int activeIndex = 0; @override void initState() { scheduleMicrotask(() { labProvider.initLabProvider(); }); super.initState(); } @override Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); rangeViewModel = Provider.of(context); _appState = getIt(); return CollapsingListView( title: LocaleKeys.labResults.tr(context: context), search: () async { if (labProvider.isLabOrdersLoading) { return; } else { String? value = await Navigator.of(context).push( CustomPageRoute( page: SearchLabResultsContent(labSuggestionsList: labProvider.labSuggestions), fullScreenDialog: true, direction: AxisDirection.down, ), ); if (value != null) { selectedFilterText = value; labProvider.filterLabReports(value); } } }, child: Consumer( builder: (context, labViewModel, child) { return SingleChildScrollView( physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.all(24.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, LocaleKeys.byVisit.tr()), CustomTabBarModel(null, LocaleKeys.byTest.tr()), // CustomTabBarModel(null, "Completed".needTranslation), ], onTabChange: (index) { activeIndex = index; setState(() {}); }, ), ), ], ), if (activeIndex == 0) Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Row( children: [ // CustomButton( // text: LocaleKeys.byClinic.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(true); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // borderColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2), // textColor: labViewModel.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // fontSize: 12.f, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // SizedBox(width: 8.h), // CustomButton( // text: LocaleKeys.byHospital.tr(context: context), // onPressed: () { // labViewModel.setIsSortByClinic(false); // }, // backgroundColor: labViewModel.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // borderColor: labViewModel.isSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor, // textColor: labViewModel.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // fontSize: 12, // fontWeight: FontWeight.w500, // borderRadius: 10, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), ], ), ), SizedBox(height: 8.h), selectedFilterText!.isNotEmpty ? Column( children: [ AppCustomChipWidget( labelText: selectedFilterText!, backgroundColor: AppColors.alertColor, textColor: AppColors.whiteColor, deleteIcon: AppAssets.close_bottom_sheet_icon, deleteIconColor: AppColors.whiteColor, deleteIconHasColor: true, isEnglishOnly: true, onDeleteTap: () { selectedFilterText = ""; labProvider.filterLabReports(""); }, ), SizedBox(height: 8.h), ], ) : SizedBox(), activeIndex == 0 ? // By Visit - show grouped view when available labViewModel.isLabOrdersLoading ? ListView.builder( shrinkWrap: true, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: 5, itemBuilder: (context, index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, ), ) : (labViewModel.patientLabOrders.isNotEmpty ? ListView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: labViewModel.filteredLabOrders.length, itemBuilder: (context, index) { final group = labViewModel.filteredLabOrders[index]; final isExpanded = expandedIndex == index; return AnimationConfiguration.staggeredList( position: index, duration: const Duration(milliseconds: 500), child: SlideAnimation( verticalOffset: 100.0, child: FadeInAnimation( child: AnimatedContainer( duration: Duration(milliseconds: 300), curve: Curves.easeInOut, margin: EdgeInsets.symmetric(vertical: 8.h), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), child: InkWell( onTap: () { setState(() { expandedIndex = isExpanded ? null : index; }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ AppCustomChipWidget( richText: Row( children: [ "${group.testDetails!.length} ".toText10(color: AppColors.successColor, isEnglishOnly: true), LocaleKeys.tests.tr(context: context).toText10(color: AppColors.successColor), ], ), labelText: "${group.testDetails!.length} ${LocaleKeys.tests.tr(context: context)}", backgroundColor: AppColors.successColor.withOpacity(0.1), textColor: AppColors.successColor, ), AppCustomChipWidget( labelText: "${_appState.isArabic() ? group.isInOutPatientDescriptionN : group.isInOutPatientDescription}", backgroundColor: AppColors.warningColorYellow.withOpacity(0.1), textColor: AppColors.warningColorYellow, ) ], ), Icon(isExpanded ? Icons.expand_less : Icons.expand_more), ], ), SizedBox(height: 8.h), Row( mainAxisSize: MainAxisSize.min, children: [ Image.network( group.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", width: 24.w, height: 24.h, fit: BoxFit.cover, ).circle(100), SizedBox(width: 8.h), Expanded(child: (group.doctorName ?? group.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), ], ), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [ Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(group.orderDate ?? ""), false), isEnglishOnly: true, )), AppCustomChipWidget( labelText: (group.projectName ?? ""), ), AppCustomChipWidget( labelText: (group.clinicDescription ?? ""), ), ], ), ], ), ), AnimatedSwitcher( duration: Duration(milliseconds: 500), switchInCurve: Curves.easeIn, switchOutCurve: Curves.easeOut, transitionBuilder: (Widget child, Animation animation) { return FadeTransition( opacity: animation, child: SizeTransition( sizeFactor: animation, axisAlignment: 0.0, child: child, ), ); }, child: isExpanded ? Container( key: ValueKey(index), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 0.h), child: Column( children: [ ListView.separated( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemBuilder: (cxt, index) { PatientLabOrdersResponseModel order = group; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "• ${order.testDetails![index].description!}".toText14(weight: FontWeight.w500, isEnglishOnly: true), SizedBox(height: 4.h), order.testDetails![index].testDescriptionEn!.toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight, isEnglishOnly: true), // Row( // mainAxisSize: MainAxisSize.min, // children: [ // Image.network( // order.doctorImageURL ?? "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown_female.png", // width: 24.w, // height: 24.h, // fit: BoxFit.cover, // ).circle(100), // SizedBox(width: 8.h), // Expanded(child: (order.doctorName ?? order.doctorNameEnglish ?? "").toString().toText14(weight: FontWeight.w500)), // ], // ), // SizedBox(height: 8.h), // Wrap( // direction: Axis.horizontal, // spacing: 4.h, // runSpacing: 4.h, // children: [ // AppCustomChipWidget( // labelText: ("${LocaleKeys.orderNo.tr(context: context)}: ${order.orderNo!}"), isEnglishOnly: true, // ), // Directionality( // textDirection: ui.TextDirection.ltr, // child: AppCustomChipWidget( // labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // isEnglishOnly: true, // )), // AppCustomChipWidget( // labelText: labViewModel.isSortByClinic ? (order.projectName ?? "") : (order.clinicDescription ?? ""), // ), // ], // ), // // Row( // // children: [ // // CustomButton( // // text: ("Order No: ".needTranslation + order.orderNo!), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // SizedBox(width: 8.h), // // CustomButton( // // text: DateUtil.formatDateToDate(DateUtil.convertStringToDate(order.orderDate ?? ""), false), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // // SizedBox(height: 8.h), // // Row( // // children: [ // // CustomButton( // // text: model.isSortByClinic ? (order.clinicDescription ?? "") : (order.projectName ?? ""), // // onPressed: () {}, // // backgroundColor: AppColors.greyColor, // // borderColor: AppColors.greyColor, // // textColor: AppColors.blackColor, // // fontSize: 10, // // fontWeight: FontWeight.w500, // // borderRadius: 8, // // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // // height: 24.h, // // ), // // ], // // ), // SizedBox(height: 12.h), // Row( // children: [ // Expanded(flex: 2, child: SizedBox()), // // Expanded( // // flex: 1, // // child: Container( // // height: 40.h, // // width: 40.w, // // decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // // color: AppColors.textColor, // // borderRadius: 12, // // ), // // child: Padding( // // padding: EdgeInsets.all(12.h), // // child: Transform.flip( // // flipX: _appState.isArabic(), // // child: Utils.buildSvgWithAssets( // // icon: AppAssets.forward_arrow_icon_small, // // iconColor: AppColors.whiteColor, // // fit: BoxFit.contain, // // ), // // ), // // ), // // ).onPress(() { // // model.currentlySelectedPatientOrder = order; // // labProvider.getPatientLabResultByHospital(order); // // labProvider.getPatientSpecialResult(order); // // Navigator.of(context).push( // // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // // ); // // }), // // ) // // Expanded( // flex: 2, // child: CustomButton( // icon: AppAssets.view_report_icon, // iconColor: AppColors.primaryRedColor, // iconSize: 16.h, // text: LocaleKeys.viewResults.tr(context: context), // onPressed: () { // labViewModel.currentlySelectedPatientOrder = order; // labProvider.getPatientLabResultByHospital(order); // labProvider.getPatientSpecialResult(order); // Navigator.of(context).push( // CustomPageRoute(page: LabResultByClinic(labOrder: order)), // ); // }, // backgroundColor: AppColors.secondaryLightRedColor, // borderColor: AppColors.secondaryLightRedColor, // textColor: AppColors.primaryRedColor, // fontSize: 14, // fontWeight: FontWeight.w500, // borderRadius: 12, // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // height: 40.h, // ), // ) // ], // ), // SizedBox(height: 12.h), // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // SizedBox(height: 12.h), ], ).paddingOnly(top: 16, bottom: 16); }, separatorBuilder: (cxt, index) => Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), itemCount: group.testDetails!.length > 3 ? 3 : group.testDetails!.length), SizedBox(height: 16.h), CustomButton( text: "${LocaleKeys.viewResults.tr()} (${group.testDetails!.length})", onPressed: () { labProvider.currentlySelectedPatientOrder = group; labProvider.getPatientLabResultByHospital(group); labProvider.getPatientSpecialResult(group); Navigator.of(context).push( CustomPageRoute( page: LabResultByClinic(labOrder: group), ), ); }, backgroundColor: AppColors.infoColor.withAlpha(20), borderColor: AppColors.infoColor.withAlpha(0), textColor: AppColors.infoColor, fontSize: (isFoldable || isTablet) ? 12.f : 14.f, fontWeight: FontWeight.w500, borderRadius: 12.r, padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 0), height: 40.h, iconSize: 14.h, icon: AppAssets.view_report_icon, iconColor: AppColors.infoColor, ), SizedBox(height: 16.h), ], ), ) : SizedBox.shrink(), ), ], ), ), ), ), )); }, ) : Utils.getNoDataWidget(context, noDataText: LocaleKeys.noLabResults.tr(context: context))) : // By Test or other tabs keep existing behavior (labViewModel.isLabOrdersLoading) ? Column( children: List.generate( 5, (index) => LabResultItemView( onTap: () {}, labOrder: null, index: index, isLoading: true, )), ) : AlphabeticScroll( alpahbetsAvailable: labViewModel.filteredIndexedCharacterForUniqueTest, details: labViewModel.filteredUniqueTestsList, labViewModel: labViewModel, rangeViewModel: rangeViewModel, appState: _appState, ) ], )); }, ), ); } Color getLabOrderStatusColor(num status) { switch (status) { case 44: return AppColors.warningColorYellow; case 45: return AppColors.warningColorYellow; case 16: return AppColors.successColor; case 17: return AppColors.successColor; default: return AppColors.greyColor; } } String getLabOrderStatusText(num status) { switch (status) { case 44: return LocaleKeys.resultsPending.tr(context: context); case 45: return LocaleKeys.resultsPending.tr(context: context); case 16: return LocaleKeys.resultsAvailable.tr(context: context); case 17: return LocaleKeys.resultsAvailable.tr(context: context); default: return ""; } } getLabSuggestions(LabViewModel model) { if (model.patientLabOrders.isEmpty) { return []; } return model.patientLabOrders.map((m) => m.testDetails).toList(); } } \ No newline at end of file diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart index 2a4fd66d..44a841db 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart @@ -30,6 +30,7 @@ class _LabAiAnalysisDetailedPageState extends State { Widget build(BuildContext context) { labProvider = Provider.of(context, listen: false); return CollapsingListView( + isClose: true, title: LocaleKeys.aiAnalysis.tr(context: context), child: Consumer( builder: (context, model, child) { @@ -415,7 +416,7 @@ class _LabAiAnalysisDetailedPageState extends State { Widget _buildCombinedLabCard(AiGeneratedAttribute attr) { return Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: false), padding: EdgeInsets.all(16.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -502,7 +503,11 @@ class _LabAiAnalysisDetailedPageState extends State { Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h), decoration: BoxDecoration(color: _getResultFlagColor(attr.calculatedResultFlag), borderRadius: BorderRadius.circular(4.r)), - child: ("${LocaleKeys.calculatedValue.tr()}: ${attr.resultValue!}").toText12(fontWeight: FontWeight.w600, color: _getResultTextColor(attr.calculatedResultFlag)), + child: ("${LocaleKeys.calculatedValue.tr()}: ${attr.resultValue!}").toText12( + fontWeight: FontWeight.w600, + color: _getResultTextColor(attr.calculatedResultFlag), + isEnglishOnly: true + ), ), SizedBox(width: 8.h), Container( @@ -534,7 +539,7 @@ class _LabAiAnalysisDetailedPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ LocaleKeys.calculationFormula.tr().toText16(weight: FontWeight.w600), - (attr.calculationFormula ?? "").toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), + (attr.calculationFormula ?? "").toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight, isEnglishOnly: true), ], ), ), diff --git a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart index 1c7d0400..69d9dd76 100644 --- a/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart +++ b/lib/presentation/lab/lab_result_via_clinic/lab_order_result_item.dart @@ -40,7 +40,7 @@ class LabOrderResultItem extends StatelessWidget { // ...labOrder!.testDetails!.map((detail) { Padding( padding: EdgeInsets.only(bottom: 8.h), - child: '${tests!.description}'.toText14(weight: FontWeight.w500), + child: '${tests!.description}'.toText14(weight: FontWeight.w500, isEnglishOnly: true), ), // (tests!.packageShortDescription ?? "").toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), diff --git a/lib/presentation/lab/lab_results/lab_result_details.dart b/lib/presentation/lab/lab_results/lab_result_details.dart index ae73b08b..0b315c50 100644 --- a/lib/presentation/lab/lab_results/lab_result_details.dart +++ b/lib/presentation/lab/lab_results/lab_result_details.dart @@ -28,18 +28,54 @@ import '../../../core/common_models/data_points.dart'; import '../../../widgets/common_bottom_sheet.dart' show showCommonBottomSheetWithoutHeight; import 'dart:ui' as ui; -class LabResultDetails extends StatelessWidget { +class LabResultDetails extends StatefulWidget { final LabResult recentLabResult; final String? testDescription; const LabResultDetails({super.key, required this.recentLabResult, required this.testDescription}); + @override + State createState() => _LabResultDetailsState(); +} + +class _LabResultDetailsState extends State { + final GlobalKey _aiAnalysisKey = GlobalKey(); + LabOrderResponseByAi? _previousAiData; + + LabResult get recentLabResult => widget.recentLabResult; + + String? get testDescription => widget.testDescription; + @override Widget build(BuildContext context) { LabViewModel labViewModel = Provider.of(context, listen: false); final appState = getIt.get(); return Scaffold( body: Consumer(builder: (context, labVM, child) { + // Detect changes in labOrderResponseByAi + WidgetsBinding.instance.addPostFrameCallback((_) { + if (labVM.labOrderResponseByAi != null && _previousAiData == null) { + // AI data just became available — scroll to it + final ctx = _aiAnalysisKey.currentContext; + if (ctx != null) { + Scrollable.ensureVisible( + ctx, + duration: const Duration(milliseconds: 400), + curve: Curves.easeOut, + ); + } + } else if (labVM.labOrderResponseByAi == null && _previousAiData != null) { + // AI data just became null — scroll to top + final scrollable = Scrollable.maybeOf(context); + scrollable?.position.animateTo( + 0, + duration: const Duration(milliseconds: 400), + curve: Curves.easeOut, + ); + } + _previousAiData = labVM.labOrderResponseByAi; + }); + return Column( children: [ Expanded( @@ -110,7 +146,7 @@ class LabResultDetails extends StatelessWidget { selector: (_, model) => model.labOrderResponseByAi, builder: (_, aiData, __) { if (aiData != null) { - return AiAnalysisWidget(data: aiData).paddingOnly(bottom: 16.h); + return AiAnalysisWidget(key: _aiAnalysisKey, data: aiData).paddingOnly(bottom: 16.h); } return const SizedBox.shrink(); }, @@ -187,7 +223,7 @@ class LabResultDetails extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - (recentLabResult.testCode ?? "").toText28(isBold: true, color: AppColors.textColor, letterSpacing: -2), + (recentLabResult.testCode ?? "").toText28(isBold: true, color: AppColors.textColor, letterSpacing: -2, isEnglishOnly: true), Visibility( visible: recentLabResult.checkIfGraphShouldBeDisplayed() == true, child: Column( @@ -224,12 +260,16 @@ class LabResultDetails extends StatelessWidget { mainAxisSize: MainAxisSize.max, children: [ Flexible( - child: ("${recentLabResult.resultValue} ${recentLabResult.uOM}" ?? "").toText28( - isBold: true, - color: context.read().getColor( - recentLabResult.calculatedResultFlag ?? "", - ), - letterSpacing: -2), + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: ("${recentLabResult.resultValue} ${recentLabResult.uOM}" ?? "").toText28( + isBold: true, + color: context.read().getColor( + recentLabResult.calculatedResultFlag ?? "", + ), + letterSpacing: -2, + isEnglishOnly: true), + ), ), SizedBox( width: 4.h, @@ -386,7 +426,7 @@ class LabResultDetails extends StatelessWidget { return SizedBox.shrink(); // } }, - graphColor: AppColors.graphGridColor, + graphColor: AppColors.textColor.withAlpha(90), graphShadowColor: AppColors.graphGridColor.withOpacity(.5), graphGridColor: graphColor.withOpacity(.4), bottomLabelFormatter: (value, data) { @@ -443,7 +483,7 @@ class LabResultDetails extends StatelessWidget { // itemCount: labmodel.isLabResultsHistoryShowMore ? (labmodel.filteredGraphValues.length < 3 ? labmodel.filteredGraphValues : 3) : labmodel.filteredGraphValues.length, itemCount: !labmodel.isLabResultsHistoryShowMore ? (labmodel.mainLabResults.length < 3 ? labmodel.mainLabResults.length : 3) : labmodel.mainLabResults.length, itemBuilder: (context, index) { - var data = labmodel.mainLabResults.reversed.toList()[index]; + var data = labmodel.mainLabResults.toList()[index]; return LabHistoryItem( dayNameAndDate: labmodel.getFormattedDate(DateUtil.convertStringToDate(data.verifiedOnDateTime)), result: data.resultValue??"", diff --git a/lib/presentation/medical_file/patient_sickleaves_list_page.dart b/lib/presentation/medical_file/patient_sickleaves_list_page.dart index 4518eca5..497e637f 100644 --- a/lib/presentation/medical_file/patient_sickleaves_list_page.dart +++ b/lib/presentation/medical_file/patient_sickleaves_list_page.dart @@ -24,6 +24,8 @@ import 'package:provider/provider.dart'; import 'widgets/patient_sick_leave_card.dart'; +import 'dart:ui' as ui; + class PatientSickleavesListPage extends StatefulWidget { const PatientSickleavesListPage({super.key}); @@ -153,14 +155,26 @@ class _PatientSickleavesListPageState extends State { spacing: 6.h, runSpacing: 6.h, children: [ - AppCustomChipWidget( - labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientSickLeaveList[index].appointmentDate), false), + Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(model.patientSickLeaveList[index].appointmentDate), false), + isEnglishOnly: true, + ), ), AppCustomChipWidget( labelText: model.isSickLeavesSortByClinic ? model.patientSickLeaveList[index].projectName! : model.patientSickLeaveList[index].clinicName!, ), AppCustomChipWidget( - labelText: "${model.patientSickLeaveList[index].sickLeaveDays} Days", + richText: Row( + mainAxisSize: MainAxisSize.min, + children: [ + "${model.patientSickLeaveList[index].sickLeaveDays} ".toText10(isEnglishOnly: true), + LocaleKeys.days.tr(context: context).toText10() + ], + ), + // labelText: "${model.patientSickLeaveList[index].sickLeaveDays} ${LocaleKeys.days.tr(context: context)}", + isEnglishOnly: true, ), ], ), diff --git a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart index 18bd2e69..071ccd13 100644 --- a/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart +++ b/lib/presentation/medical_file/widgets/patient_sick_leave_card.dart @@ -21,6 +21,8 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:open_filex/open_filex.dart'; import 'package:provider/provider.dart'; +import 'dart:ui' as ui; + class PatientSickLeaveCard extends StatelessWidget { PatientSickLeaveCard({super.key, required this.patientSickLeavesResponseModel, this.isLoading = false, this.isSickLeaveListPage = false}); @@ -72,11 +74,15 @@ class PatientSickLeaveCard extends StatelessWidget { spacing: 3.h, runSpacing: 4.h, children: [ - AppCustomChipWidget( - icon: AppAssets.doctor_calendar_icon, - labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientSickLeavesResponseModel.appointmentDate), false), - labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h), - ).toShimmer2(isShow: isLoading), + Directionality( + textDirection: ui.TextDirection.ltr, + child: AppCustomChipWidget( + icon: AppAssets.doctor_calendar_icon, + labelText: DateUtil.formatDateToDate(DateUtil.convertStringToDate(patientSickLeavesResponseModel.appointmentDate), false), + labelPadding: EdgeInsetsDirectional.only(start: -4.h, end: 8.h), + isEnglishOnly: true, + ).toShimmer2(isShow: isLoading), + ), AppCustomChipWidget(labelText: isLoading ? "Pending Activation" : patientSickLeavesResponseModel.clinicName!).toShimmer2(isShow: isLoading), ], ), diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart index a621168f..720dc6e6 100644 --- a/lib/presentation/my_family/widget/family_cards.dart +++ b/lib/presentation/my_family/widget/family_cards.dart @@ -311,7 +311,8 @@ class _FamilyCardsState extends State { crossAxisCount: 2, crossAxisSpacing: 10.w, mainAxisSpacing: 10.h, - childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h, + // childAspectRatio: widget.isShowDetails ? 0.56.h : 0.74.h, + childAspectRatio: 0.7.h, ), padding: EdgeInsets.only(bottom: 20.h), itemBuilder: (context, index) { diff --git a/lib/presentation/notifications/notifications_list_page.dart b/lib/presentation/notifications/notifications_list_page.dart index 99201688..e2808f1f 100644 --- a/lib/presentation/notifications/notifications_list_page.dart +++ b/lib/presentation/notifications/notifications_list_page.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; @@ -18,6 +19,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; +import 'dart:ui' as ui; class NotificationsListPage extends StatefulWidget { const NotificationsListPage({super.key}); @@ -134,16 +136,20 @@ class _NotificationsListPageState extends State { color: AppColors.greyColor, borderRadius: BorderRadius.circular(8), ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.access_time, size: 12.w, color: AppColors.textColor), - SizedBox(width: 4.w), - _formatTime(notificationsVM.notificationsList[index].isSentOn).toText10( - weight: FontWeight.w500, - color: AppColors.textColor, - ), - ], + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.access_time, size: 12.w, color: AppColors.textColor), + SizedBox(width: 4.w), + _formatTime(notificationsVM.notificationsList[index].isSentOn).toText10( + weight: FontWeight.w500, + color: AppColors.textColor, + isEnglishOnly: true + ), + ], + ), ), ), SizedBox(width: 8.w), @@ -154,25 +160,32 @@ class _NotificationsListPageState extends State { color: AppColors.greyColor, borderRadius: BorderRadius.circular(8), ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.calendar_today, size: 12.w, color: AppColors.textColor), - SizedBox(width: 4.w), - _formatDate(notificationsVM.notificationsList[index].isSentOn).toText10( - weight: FontWeight.w500, - color: AppColors.textColor, - ), - ], + child: Directionality( + textDirection: ui.TextDirection.ltr, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.calendar_today, size: 12.w, color: AppColors.textColor), + SizedBox(width: 4.w), + _formatDate(notificationsVM.notificationsList[index].isSentOn).toText10( + weight: FontWeight.w500, + color: AppColors.textColor, + isEnglishOnly: true + ), + ], + ), ), ), Spacer(), // Arrow icon - Utils.buildSvgWithAssets( - icon: AppAssets.arrow_forward, - width: 16.w, - height: 16.h, - iconColor: AppColors.greyTextColor, + Transform.flip( + flipX: getIt.get().isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.arrow_forward, + width: 16.w, + height: 16.h, + iconColor: AppColors.greyTextColor, + ), ), ], ), @@ -194,7 +207,7 @@ class _NotificationsListPageState extends State { children: [ Icon(Icons.image_outlined, size: 12.w, color: AppColors.textColor), SizedBox(width: 4.w), - 'Contains Image'.toText10( + LocaleKeys.containsImage.toText10( weight: FontWeight.w500, color: AppColors.textColor, ), diff --git a/lib/presentation/prescriptions/prescription_item_view.dart b/lib/presentation/prescriptions/prescription_item_view.dart index 5b52b99b..fcec404b 100644 --- a/lib/presentation/prescriptions/prescription_item_view.dart +++ b/lib/presentation/prescriptions/prescription_item_view.dart @@ -98,7 +98,7 @@ class PrescriptionItemView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.setReminder.tr(context: context).toText13(isBold: true), - "Notify me before the consumption time".toText10(color: AppColors.textColorLight, isEnglishOnly: true), + LocaleKeys.notifyPrescription.tr(context: context).toText10(color: AppColors.textColorLight), ], ).toShimmer2(isShow: isLoading).expanded, Switch( diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart index 1b40a156..dd4543e7 100644 --- a/lib/presentation/profile_settings/profile_settings.dart +++ b/lib/presentation/profile_settings/profile_settings.dart @@ -42,6 +42,8 @@ import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:in_app_review/in_app_review.dart'; +import 'dart:ui' as ui; + class ProfileSettings extends StatefulWidget { const ProfileSettings({super.key}); @@ -297,11 +299,11 @@ class ProfileSettingsState extends State { children: [ actionItem(AppAssets.call_fill, LocaleKeys.contactUs.tr(context: context), () { launchUrl(Uri.parse("tel://" + "+966 92 006 6666")); - }, trailingLabel: "92 006 6666"), + }, trailingLabel: "92 006 6666", isEnglishOnly: true), 1.divider, actionItem(AppAssets.permission, LocaleKeys.permissionsProfile.tr(context: context), () { openAppSettings(); - }, trailingLabel: getCurrentPermissions()), + }, trailingLabel: getCurrentPermissions(), isEnglishOnly: true), actionItem(AppAssets.feedbackFill, LocaleKeys.feedback.tr(context: context), () { contactUsViewModel.setSelectedFeedbackType( FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'), @@ -392,7 +394,7 @@ class ProfileSettingsState extends State { } Widget actionItem(String icon, String label, VoidCallback onPress, - {String trailingLabel = "", bool? switchValue, ValueChanged? onSwitchChanged, bool isExternalLink = false, bool isShowLoading = false}) { + {String trailingLabel = "", bool? switchValue, ValueChanged? onSwitchChanged, bool isExternalLink = false, bool isShowLoading = false, bool isEnglishOnly = false}) { return SizedBox( height: 56.h, child: Row( @@ -403,7 +405,7 @@ class ProfileSettingsState extends State { if (trailingLabel.isNotEmpty) ConstrainedBox( constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.35), - child: trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1).toShimmer2(isShow: isShowLoading), + child: isEnglishOnly ? Directionality(textDirection: ui.TextDirection.ltr, child: trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, isEnglishOnly: isEnglishOnly).toShimmer2(isShow: isShowLoading)) : trailingLabel.toText14(color: AppColors.greyTextColor, weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, isEnglishOnly: isEnglishOnly).toShimmer2(isShow: isShowLoading), ), switchValue != null ? Switch( diff --git a/lib/presentation/radiology/radiology_orders_page.dart b/lib/presentation/radiology/radiology_orders_page.dart index db2e4f52..07b45c29 100644 --- a/lib/presentation/radiology/radiology_orders_page.dart +++ b/lib/presentation/radiology/radiology_orders_page.dart @@ -146,6 +146,7 @@ class _RadiologyOrdersPageState extends State { model.filterRadiologyReports(''); }); }, + isEnglishOnly: true // chipType: ChipTypeEnum.alert, // isSelected: true, ) @@ -433,7 +434,7 @@ class _RadiologyOrdersPageState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "• ${group.procedureName.toString().trim() ?? ""}".toText14(weight: FontWeight.w500), + "• ${group.procedureName.toString().trim() ?? ""}".toText14(weight: FontWeight.w500, isEnglishOnly: true), // "Lorem ipsum text".toText12(fontWeight: FontWeight.w500, color: AppColors.textColorLight), SizedBox(height: 16.h), CustomButton( diff --git a/lib/presentation/radiology/search_radiology.dart b/lib/presentation/radiology/search_radiology.dart index 7c14fd1d..20ecef47 100644 --- a/lib/presentation/radiology/search_radiology.dart +++ b/lib/presentation/radiology/search_radiology.dart @@ -78,8 +78,9 @@ class _SearchRadiologyContentContentState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ TextInputWidget( - labelText: "Search radiology results", - hintText: "Type test description", + fontFamily: "Poppins", + labelText: LocaleKeys.search.tr(context: context), + hintText: "", controller: searchEditingController, isEnable: true, prefix: null, @@ -93,7 +94,7 @@ class _SearchRadiologyContentContentState extends State ), SizedBox(height: ResponsiveExtension(20).h), if (filteredSuggestions.isNotEmpty) ...[ - "Suggestions".toText16(isBold: true), + LocaleKeys.suggestions.tr(context: context).toText16(isBold: true), ], ], ), @@ -146,8 +147,8 @@ class SuggestionChip extends StatelessWidget { child: label.toText12( // color: isSelected ? Colors.white : Colors.black87, color: AppColors.textColor, - fontWeight: FontWeight.w500, - ), + fontWeight: FontWeight.w500, + isEnglishOnly: true), ), ); } diff --git a/lib/presentation/symptoms_checker/user_info_selection/pages/height_selection_page.dart b/lib/presentation/symptoms_checker/user_info_selection/pages/height_selection_page.dart index ce8087d4..28de7894 100644 --- a/lib/presentation/symptoms_checker/user_info_selection/pages/height_selection_page.dart +++ b/lib/presentation/symptoms_checker/user_info_selection/pages/height_selection_page.dart @@ -49,14 +49,13 @@ class HeightSelectionPage extends StatelessWidget { }, child: Container( alignment: Alignment.center, - color: Colors.transparent, + color: Colors.white, child: Text( 'CM', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14.f, - color: viewModel.isHeightCm ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6), - ), + color: viewModel.isHeightCm ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.6), fontFamily: "Poppins"), ), ), ), @@ -71,14 +70,13 @@ class HeightSelectionPage extends StatelessWidget { }, child: Container( alignment: Alignment.center, - color: Colors.transparent, + color: Colors.white, child: Text( 'FT', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14.f, - color: !viewModel.isHeightCm ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6), - ), + color: !viewModel.isHeightCm ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.6), fontFamily: "Poppins"), ), ), ), @@ -133,8 +131,7 @@ class HeightSelectionPage extends StatelessWidget { style: TextStyle( fontSize: 90.f, color: AppColors.textColor, - height: 1, - ), + height: 1, fontFamily: "Poppins"), ), TextSpan( text: viewModel.isHeightCm ? 'cm' : 'ft', diff --git a/lib/presentation/symptoms_checker/user_info_selection/pages/weight_selection_page.dart b/lib/presentation/symptoms_checker/user_info_selection/pages/weight_selection_page.dart index 6e68eef9..fefc9abe 100644 --- a/lib/presentation/symptoms_checker/user_info_selection/pages/weight_selection_page.dart +++ b/lib/presentation/symptoms_checker/user_info_selection/pages/weight_selection_page.dart @@ -57,13 +57,14 @@ class WeightSelectionPage extends StatelessWidget { }, child: Container( alignment: Alignment.center, - color: Colors.transparent, + color: Colors.white, child: Text( 'KG', style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14.f, - color: isKg ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6), + color: isKg ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.6), + fontFamily: "Poppins" ), ), ), @@ -86,7 +87,8 @@ class WeightSelectionPage extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14.f, - color: !isKg ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.6), + color: !isKg ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.6), + fontFamily: "Poppins" ), ), ), @@ -133,12 +135,12 @@ class WeightSelectionPage extends StatelessWidget { children: [ Text( viewModel.selectedWeight!.round().toString(), - style: TextStyle(fontSize: 100.f, color: AppColors.textColor, height: 1), + style: TextStyle(fontSize: 100.f, color: AppColors.textColor, height: 1, fontFamily: "Poppins"), ), SizedBox(width: 8.w), Text( isKg ? 'kg' : 'lbs', - style: TextStyle(fontWeight: FontWeight.w700, fontSize: 24.f), + style: TextStyle(fontWeight: FontWeight.w700, fontSize: 24.f, fontFamily: "Poppins"), ).paddingOnly(bottom: 10.h), ], ), diff --git a/lib/presentation/symptoms_checker/user_info_selection/widgets/height_scale.dart b/lib/presentation/symptoms_checker/user_info_selection/widgets/height_scale.dart index e09380eb..840cb583 100644 --- a/lib/presentation/symptoms_checker/user_info_selection/widgets/height_scale.dart +++ b/lib/presentation/symptoms_checker/user_info_selection/widgets/height_scale.dart @@ -135,6 +135,7 @@ class _HeightScaleState extends State { color: AppColors.greyTextColor, fontWeight: FontWeight.w500, height: 1, + fontFamily: "Poppins" ), textAlign: TextAlign.right, ), diff --git a/lib/presentation/symptoms_checker/user_info_selection/widgets/weight_scale.dart b/lib/presentation/symptoms_checker/user_info_selection/widgets/weight_scale.dart index 8526a526..2ad4c99c 100644 --- a/lib/presentation/symptoms_checker/user_info_selection/widgets/weight_scale.dart +++ b/lib/presentation/symptoms_checker/user_info_selection/widgets/weight_scale.dart @@ -154,6 +154,7 @@ class _WeightScaleState extends State { color: AppColors.greyTextColor, fontWeight: FontWeight.w500, height: 1, + fontFamily: "Poppins" ), textAlign: TextAlign.center, maxLines: 1, diff --git a/lib/widgets/date_range_selector/date_range_calender.dart b/lib/widgets/date_range_selector/date_range_calender.dart index d6e2eadf..73e783bc 100644 --- a/lib/widgets/date_range_selector/date_range_calender.dart +++ b/lib/widgets/date_range_selector/date_range_calender.dart @@ -109,7 +109,7 @@ class _DateRangeSelectorState extends State { viewHeaderStyle: DateRangePickerViewHeaderStyle( backgroundColor: AppColors.whiteColor, textStyle: TextStyle( - fontSize: 14.f, + fontSize: 12.f, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor, @@ -121,17 +121,25 @@ class _DateRangeSelectorState extends State { selectionShape: DateRangePickerSelectionShape.rectangle, selectionRadius: 12.h, selectionColor: AppColors.transparent, + selectionTextStyle: TextStyle( + fontFamily: "Poppins", + ), startRangeSelectionColor: AppColors.primaryRedColor, endRangeSelectionColor: AppColors.primaryRedColor, rangeSelectionColor: AppColors.primaryRedColor.withOpacity(0.1), + rangeTextStyle: TextStyle( + fontFamily: "Poppins", + ), todayHighlightColor: Colors.transparent, monthCellStyle: DateRangePickerMonthCellStyle( textStyle: TextStyle( + fontFamily: "Poppins", fontSize: 12.f, color: AppColors.textColor, ), todayTextStyle: TextStyle( + fontFamily: "Poppins", color: AppColors.textColor, fontWeight: FontWeight.bold, ), @@ -318,6 +326,7 @@ class _DateRangeSelectorState extends State { width: 1, ), borderRadius: BorderRadius.circular(10)), + isEnglishOnly: true, ).onPress((){ _calendarController.selectedRange = null; model.currentlySelectedRange = Range.LAST_6MONTH; @@ -325,7 +334,13 @@ class _DateRangeSelectorState extends State { }), AppCustomChipWidget( - labelText: "Year ${model.getCurrentYear}", + richText: Row( + children: [ + "${LocaleKeys.year.tr(context: context)} ".toText10(), + model.getCurrentYear.toString().toText10(isEnglishOnly: true), + ], + ), + labelText: "${LocaleKeys.year.tr(context: context)} ${model.getCurrentYear}", backgroundColor: model.currentlySelectedRange == Range.THIS_YEAR ? AppColors.primaryRedColor.withOpacity(0.1) : AppColors.whiteColor, @@ -337,6 +352,7 @@ class _DateRangeSelectorState extends State { width: 1, ), borderRadius: BorderRadius.circular(10)), + isEnglishOnly: true, ).onPress((){ _calendarController.selectedRange = null; model.currentlySelectedRange = Range.THIS_YEAR; diff --git a/lib/widgets/graph/custom_graph.dart b/lib/widgets/graph/custom_graph.dart index 898dc5ea..24da8da5 100644 --- a/lib/widgets/graph/custom_graph.dart +++ b/lib/widgets/graph/custom_graph.dart @@ -281,7 +281,17 @@ class CustomGraph extends StatelessWidget { begin: Alignment.centerLeft, end: Alignment.centerRight, ), - dotData: FlDotData(show: showLinePoints), + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, idx) { + return FlDotCirclePainter( + radius: 6, + color: resolvedGraphColor, + strokeWidth: 2, + strokeColor: Colors.white, + ); + }, + ), belowBarData: BarAreaData( show: showShadow, applyCutOffY: cutOffY != null, @@ -317,7 +327,17 @@ class CustomGraph extends StatelessWidget { begin: Alignment.centerLeft, end: Alignment.centerRight, ), - dotData: FlDotData(show: showLinePoints), + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, idx) { + return FlDotCirclePainter( + radius: 6, + color: secondaryGraphColor ?? AppColors.blueColor, + strokeWidth: 2, + strokeColor: Colors.white, + ); + }, + ), belowBarData: BarAreaData(show: false), ), ); diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index a64775aa..9c92b1bc 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -315,6 +315,7 @@ class TextInputWidget extends StatelessWidget { autofocus: autoFocus, textInputAction: TextInputAction.done, cursorHeight: isWalletAmountInput! ? 40.h : 20.h, + maxLength: isWalletAmountInput! ? 5 : 100, onTapOutside: (event) { FocusManager.instance.primaryFocus?.unfocus(); }, @@ -332,6 +333,7 @@ class TextInputWidget extends StatelessWidget { locale: const Locale('en', 'US'), // Force English locale for text style ), decoration: InputDecoration( + counterText: "", isDense: true, hintText: hintText, hintStyle: TextStyle(fontSize: 14.f, height: 21 / 16, fontWeight: FontWeight.w500, color: hintColor != null ? AppColors.textColor : Color(0xff898A8D), letterSpacing: -0.75),