From 9986729ba55a3abf9438a158a16f1bb5df6bc763 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 7 May 2026 10:15:44 +0300 Subject: [PATCH] Updates & fixes --- .../habib_wallet/habib_wallet_view_model.dart | 1 + .../profile_settings_view_model.dart | 2 +- lib/main.dart | 2 +- .../appointment_details_page.dart | 70 ++++++++++--------- .../home/lakum_wallet_details.dart | 17 ++--- lib/presentation/home/landing_page.dart | 6 +- .../home/widgets/lakum_wallet_card.dart | 2 +- .../profile_settings/profile_settings.dart | 20 ++++-- .../widgets/preferred_language_widget.dart | 8 +-- .../widgets/update_email_widget.dart | 8 +-- .../update_emergency_contact_widget.dart | 8 +-- .../possible_conditions_screen.dart | 24 ++++++- 12 files changed, 100 insertions(+), 68 deletions(-) diff --git a/lib/features/habib_wallet/habib_wallet_view_model.dart b/lib/features/habib_wallet/habib_wallet_view_model.dart index 3a10ad2d..16997369 100644 --- a/lib/features/habib_wallet/habib_wallet_view_model.dart +++ b/lib/features/habib_wallet/habib_wallet_view_model.dart @@ -339,6 +339,7 @@ class HabibWalletViewModel extends ChangeNotifier { Future getLakumAccountInformation({Function(dynamic)? onSuccess, Function(String)? onError}) async { isLakumAccountInfoLoading = true; + lakumAccountInfo = LakumInquiryInformationResponseModel(); notifyListeners(); final result = await habibWalletRepo.getLakumAccountInformation(identificationNumber: getIt.get().getAuthenticatedUser()!.patientIdentificationNo ?? ""); diff --git a/lib/features/profile_settings/profile_settings_view_model.dart b/lib/features/profile_settings/profile_settings_view_model.dart index 7891357e..64db2481 100644 --- a/lib/features/profile_settings/profile_settings_view_model.dart +++ b/lib/features/profile_settings/profile_settings_view_model.dart @@ -40,7 +40,7 @@ class ProfileSettingsViewModel extends ChangeNotifier { bool isDeactivateAccountSuccess = false; String? deactivateAccountError; - late GetPatientInfoForUpdate getPatientInfoForUpdate; + GetPatientInfoForUpdate? getPatientInfoForUpdate; bool isPatientProfileLoading = false; // ── Profile image state ────────────────────────────────────────────── diff --git a/lib/main.dart b/lib/main.dart index ffe2043e..25639e91 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -98,7 +98,7 @@ Future callAppStateInitializations() async { PlatformDispatcher.instance.onError = (error, stack) { if (!kDebugMode) { FirebaseCrashlytics.instance.recordError(error, stack, - fatal: true, + fatal: false, printDetails: true, reason: "${appState.isAuthenticated ? "Authenticated User ID: ${appState.getAuthenticatedUser()!.patientId} - ${appState.getAuthenticatedUser()!.mobileNumber}" : "Unauthenticated User"} - Uncaught asynchronous error"); diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index c14897d8..2ec8f568 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -838,40 +838,42 @@ class _AppointmentDetailsPageState extends State { iconSize: 36.w, isLocked: false, ).toShimmer2() - : MedicalFileCard( - label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAllowedToRate ?? false) - ? LocaleKeys.ratingSubmitted.tr(context: context) - : LocaleKeys.doctorRatingAppointment.tr(context: context), - textColor: AppColors.blackColor, - backgroundColor: AppColors.whiteColor, - svgIcon: AppAssets.appointmentRatingIcon, - isLargeText: true, - iconSize: 36.w, - isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false), - ).onPress(() { - if ((myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? true)) { - showCommonBottomSheetWithoutHeight( - context, - title: LocaleKeys.doctorRating.tr(context: context), - isCloseButtonVisible: true, - child: StatefulBuilder( - builder: (context, setState) { - return AppointmentRatingWidget( - patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, - ); - }, - ), - callBackFunc: () { - myAppointmentsViewModel.getDoctorsRatingCheck( - doctorID: widget.patientAppointmentHistoryResponseModel.doctorID, - clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, - projectID: widget.patientAppointmentHistoryResponseModel.projectID, - appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo); - }, - isFullScreen: false, - ); - } - }), + : myAppointmentsVM.appointmentRatedResponseModel != null + ? MedicalFileCard( + label: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false) + ? LocaleKeys.ratingSubmitted.tr(context: context) + : LocaleKeys.doctorRatingAppointment.tr(context: context), + textColor: AppColors.blackColor, + backgroundColor: AppColors.whiteColor, + svgIcon: AppAssets.appointmentRatingIcon, + isLargeText: true, + iconSize: 36.w, + isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false), + ).onPress(() { + if (myAppointmentsVM.appointmentRatedResponseModel?.isAllowedToRate ?? false) { + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.doctorRating.tr(context: context), + isCloseButtonVisible: true, + child: StatefulBuilder( + builder: (context, setState) { + return AppointmentRatingWidget( + patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, + ); + }, + ), + callBackFunc: () { + myAppointmentsViewModel.getDoctorsRatingCheck( + doctorID: widget.patientAppointmentHistoryResponseModel.doctorID, + clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, + projectID: widget.patientAppointmentHistoryResponseModel.projectID, + appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo); + }, + isFullScreen: false, + ); + } + }) + : SizedBox.shrink(), ], ); }), diff --git a/lib/presentation/home/lakum_wallet_details.dart b/lib/presentation/home/lakum_wallet_details.dart index ce3133ec..a3f9f9f9 100644 --- a/lib/presentation/home/lakum_wallet_details.dart +++ b/lib/presentation/home/lakum_wallet_details.dart @@ -43,14 +43,15 @@ class LakumWalletDetails extends StatelessWidget { // Check if account number is not available if (viewModel.yahalaAccountNumber == "0" || viewModel.yahalaAccountNumber.isEmpty) { - return Center( - child: Padding( - padding: EdgeInsets.all(32.w), - child: LocaleKeys.lakumMsg.tr().toText14( - color: AppColors.greyTextColor, - ), - ), - ); + return Utils.getNoDataWidget(context); + // return Center( + // child: Padding( + // padding: EdgeInsets.all(32.w), + // child: LocaleKeys.lakumMsg.tr().toText14( + // color: AppColors.greyTextColor, + // ), + // ), + // ); } // Get all transactions diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 6174c166..b6d32f72 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -148,7 +148,7 @@ class _LandingPageState extends State { notificationsViewModel.initNotificationsViewModel(); insuranceViewModel.initInsuranceProvider(); - if(!appState.isRatedVisible) { + if(appState.isRatedVisible) { appointmentRatingViewModel.getLastRatingAppointment(onSuccess: (response) { if (appointmentRatingViewModel.appointmentRatedList.isNotEmpty) { appointmentRatingViewModel.getAppointmentDetails(appointmentRatingViewModel.appointmentRatedList.last.appointmentNo!, appointmentRatingViewModel.appointmentRatedList.last.projectID!, @@ -282,7 +282,7 @@ class _LandingPageState extends State { await authVM.onLoginPressed(); } }), - (appState.isAuthenticated && (int.parse(todoSectionVM.notificationsCount ?? "0") > 0)) + (appState.isAuthenticated && todoSectionVM.notificationsCount != null && todoSectionVM.notificationsCount != "0") ? Positioned( // right: appState.isArabic() ? 8.w : -8.w, top: -8.h, @@ -297,7 +297,7 @@ class _LandingPageState extends State { borderRadius: BorderRadius.circular(20.r), ), child: Text( - todoSectionVM.notificationsCount.toString(), + todoSectionVM.notificationsCount ?? "0", style: TextStyle( color: Colors.white, fontFamily: "Poppins", diff --git a/lib/presentation/home/widgets/lakum_wallet_card.dart b/lib/presentation/home/widgets/lakum_wallet_card.dart index cda3c064..599dc2e8 100644 --- a/lib/presentation/home/widgets/lakum_wallet_card.dart +++ b/lib/presentation/home/widgets/lakum_wallet_card.dart @@ -99,7 +99,7 @@ class LakumWalletCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ NumberFormat.decimalPattern() - .format(habibWalletVM.isLakumAccountInfoLoading ? 123 :habibWalletVM.lakumAccountInfo.pointsBalance) + .format(habibWalletVM.isLakumAccountInfoLoading ? 123 : habibWalletVM.yahalaAccountNumber == "0" ? 0 : habibWalletVM.lakumAccountInfo.pointsBalance) .toString() .toText32(isBold: true, isEnglishOnly: true) .toShimmer2(isShow: habibWalletVM.isLakumAccountInfoLoading, radius: 12.h, width: 80.h, height: 40.h), diff --git a/lib/presentation/profile_settings/profile_settings.dart b/lib/presentation/profile_settings/profile_settings.dart index c581bcd5..bf83a905 100644 --- a/lib/presentation/profile_settings/profile_settings.dart +++ b/lib/presentation/profile_settings/profile_settings.dart @@ -53,11 +53,17 @@ class ProfileSettingsState extends State { @override void initState() { - scheduleMicrotask(() { - insuranceViewModel.initInsuranceProvider(); - }); - _loadPermissions(); super.initState(); + _loadPermissions(); + + // Load data after first frame + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + insuranceViewModel.initInsuranceProvider(); + // Load profile settings for preferred language + profileSettingsViewModel.getProfileSettings(); + } + }); } @override @@ -96,12 +102,14 @@ class ProfileSettingsState extends State { final SwiperController _controller = SwiperController(); late InsuranceViewModel insuranceViewModel; late ContactUsViewModel contactUsViewModel; + late ProfileSettingsViewModel profileSettingsViewModel; String _permissionsLabel = ""; @override Widget build(BuildContext context) { insuranceViewModel = Provider.of(context, listen: false); contactUsViewModel = Provider.of(context, listen: false); + profileSettingsViewModel = Provider.of(context, listen: false); return CollapsingListView( title: LocaleKeys.profileAndSettings.tr(context: context), logout: () { @@ -268,9 +276,9 @@ class ProfileSettingsState extends State { actionItem(AppAssets.language, LocaleKeys.communicationLanguage.tr(context: context), () { profileVm.openPreferredLanguageBottomSheet(); }, - trailingLabel: profileVm.isPatientProfileLoading + trailingLabel: profileVm.isPatientProfileLoading || profileVm.getPatientInfoForUpdate == null ? "English" - : (profileVm.getPatientInfoForUpdate.preferredLanguage! == "1" ? LocaleKeys.arabic.tr(context: context) : LocaleKeys.english.tr(context: context)), + : (profileVm.getPatientInfoForUpdate!.preferredLanguage! == "1" ? LocaleKeys.arabic.tr(context: context) : LocaleKeys.english.tr(context: context)), isShowLoading: profileVm.isPatientProfileLoading), 1.divider, actionItem(AppAssets.smart_phone_fill, LocaleKeys.emrgNo.tr(context: context), () { diff --git a/lib/presentation/profile_settings/widgets/preferred_language_widget.dart b/lib/presentation/profile_settings/widgets/preferred_language_widget.dart index 4cecc651..32dcc57b 100644 --- a/lib/presentation/profile_settings/widgets/preferred_language_widget.dart +++ b/lib/presentation/profile_settings/widgets/preferred_language_widget.dart @@ -29,7 +29,7 @@ class _PreferredLanguageWidgetState extends State { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { setState(() { - selectedValue = profileSettingsViewModel.getPatientInfoForUpdate.preferredLanguage!; + selectedValue = profileSettingsViewModel.getPatientInfoForUpdate?.preferredLanguage!; }); }); } @@ -60,9 +60,9 @@ class _PreferredLanguageWidgetState extends State { profileSettingsViewModel!.updatePatientInfo( patientInfo: { "PreferredLanguage": selectedValue, - "EmailAddress": profileSettingsViewModel.getPatientInfoForUpdate.emailAddress, - "EmergencyContactName": profileSettingsViewModel.getPatientInfoForUpdate.emergencyContactName, - "EmergencyContactNo": profileSettingsViewModel.getPatientInfoForUpdate.emergencyContactNo, + "EmailAddress": profileSettingsViewModel.getPatientInfoForUpdate!.emailAddress, + "EmergencyContactName": profileSettingsViewModel.getPatientInfoForUpdate!.emergencyContactName, + "EmergencyContactNo": profileSettingsViewModel.getPatientInfoForUpdate!.emergencyContactNo, "IsEmailAlertRequired": true, "IsSMSAlertRequired": true, }, diff --git a/lib/presentation/profile_settings/widgets/update_email_widget.dart b/lib/presentation/profile_settings/widgets/update_email_widget.dart index e8e313f4..4f13726a 100644 --- a/lib/presentation/profile_settings/widgets/update_email_widget.dart +++ b/lib/presentation/profile_settings/widgets/update_email_widget.dart @@ -39,7 +39,7 @@ class _UpdateEmailDialogState extends State { // Set the text setState(() { - textController!.text = viewModel.getPatientInfoForUpdate.emailAddress ?? ""; + textController!.text = viewModel.getPatientInfoForUpdate!.emailAddress ?? ""; }); }); @@ -118,10 +118,10 @@ class _UpdateEmailDialogState extends State { LoaderBottomSheet.showLoader(loadingText: LocaleKeys.updatingEmailAddress.tr(context: context)); profileSettingsViewModel!.updatePatientInfo( patientInfo: { - "PreferredLanguage": profileSettingsViewModel!.getPatientInfoForUpdate.preferredLanguage, + "PreferredLanguage": profileSettingsViewModel!.getPatientInfoForUpdate!.preferredLanguage, "EmailAddress": textController!.text, - "EmergencyContactName": profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactName, - "EmergencyContactNo": profileSettingsViewModel!.getPatientInfoForUpdate.emergencyContactNo, + "EmergencyContactName": profileSettingsViewModel!.getPatientInfoForUpdate!.emergencyContactName, + "EmergencyContactNo": profileSettingsViewModel!.getPatientInfoForUpdate!.emergencyContactNo, "IsEmailAlertRequired": true, "IsSMSAlertRequired": true, }, diff --git a/lib/presentation/profile_settings/widgets/update_emergency_contact_widget.dart b/lib/presentation/profile_settings/widgets/update_emergency_contact_widget.dart index 8db805b3..e1faadca 100644 --- a/lib/presentation/profile_settings/widgets/update_emergency_contact_widget.dart +++ b/lib/presentation/profile_settings/widgets/update_emergency_contact_widget.dart @@ -41,7 +41,7 @@ class _UpdateEmergencyContactDialogState extends State { // Set flag to indicate booking is from symptoms checker symptomsCheckerViewModel.setBookingFromSymptomsChecker(true); + // Check if clinicDetailsList is not empty before accessing + if (symptomsCheckerViewModel.clinicDetailsList.isEmpty) { + // Show error if no clinic details available + final dialogService = getIt(); + dialogService.showErrorBottomSheet( + message: appState.isArabic() + ? "لا توجد تفاصيل عيادة متاحة" + : "No clinic details available", + ); + return; + } + // bookAppointmentsViewModel.getLocation(); bookAppointmentsViewModel.setSelectedClinic(GetClinicsListResponseModel( clinicID: symptomsCheckerViewModel.clinicDetailsList.first.clinicID, @@ -395,9 +407,17 @@ class _PossibleConditionsPageState extends State { //if the region screen is opened for the dental clinic then the project id will be in the hospital list as the list is formed form the get project api var id = ""; if (data.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { - id = regionalViewModel.selectedHospital?.hospitalList.first.iD?.toString() ?? ""; + // Check if hospitalList is not empty before accessing first + if (regionalViewModel.selectedHospital?.hospitalList != null && + regionalViewModel.selectedHospital!.hospitalList.isNotEmpty) { + id = regionalViewModel.selectedHospital!.hospitalList.first.iD?.toString() ?? ""; + } } else { - id = regionalViewModel.selectedHospital?.patientDoctorAppointmentList?.first.projectID?.toString() ?? ""; + // Check if patientDoctorAppointmentList is not empty before accessing first + if (regionalViewModel.selectedHospital?.patientDoctorAppointmentList != null && + regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.isNotEmpty) { + id = regionalViewModel.selectedHospital!.patientDoctorAppointmentList!.first.projectID?.toString() ?? ""; + } } bookAppointmentsViewModel.setProjectID(id); return SizedBox.shrink();