From 74b0c1a9264a6f6d1262db61d73d0907d9396813 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Thu, 5 Nov 2026 14:56:52 +0300 Subject: [PATCH] Updates in my appointments workflow --- .../my_appointments/my_appointments_repo.dart | 19 +++++- .../my_appointments_view_model.dart | 63 +++++++++++++++---- .../appointments/my_appointments_page.dart | 6 +- lib/presentation/home/landing_page.dart | 4 +- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 46d24eb7..3f30ee4b 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -25,7 +25,12 @@ import 'models/resp_models/appointment_details_resp_model.dart'; abstract class MyAppointmentsRepo { Future>>> getPatientAppointments( - {required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false, bool isForTimeLine = false}); + {required bool isActiveAppointment, + required bool isArrivedAppointments, + bool isForEyeMeasurement = false, + bool isForTimeLine = false, + bool isAppointmentForHomePage = false, + bool isAppointmentForViewAll = false}); Future>> getPatientShareAppointment( {required int projectID, required int clinicID, required String appointmentNo, required bool isLiveCareAppointment}); @@ -104,8 +109,14 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { MyAppointmentsRepoImp({required this.loggerService, required this.apiClient}); @override - Future>>> getPatientAppointments( - {required bool isActiveAppointment, required bool isArrivedAppointments, bool isForEyeMeasurement = false, bool isForTimeLine = false}) async { + Future>>> getPatientAppointments({ + required bool isActiveAppointment, + required bool isArrivedAppointments, + bool isForEyeMeasurement = false, + bool isForTimeLine = false, + bool isAppointmentForHomePage = false, + bool isAppointmentForViewAll = false, + }) async { Map mapDevice = { "IsActiveAppointment": isActiveAppointment, "IsComingFromCOC": false, @@ -113,6 +124,8 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { "IsForMedicalReport": false, "IsForArrived": isArrivedAppointments, "IsIrisPrescription": isForEyeMeasurement, + "IsForHomePage": isAppointmentForHomePage, + "IsForAppointmentViewAll": isAppointmentForViewAll, "IsForTimeLine": isForTimeLine }; diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index f040fd82..3eb0e965 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -57,6 +57,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { bool isMyDoctorsDataToBeLoaded = true; bool isArrivedAppointmentDataLoaded = false; bool isFullArrivedAppointmentsLoaded = false; + bool isFullUpcomingAppointmentsLoaded = false; bool isEyeMeasurementsAppointmentsLoading = false; @@ -77,6 +78,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { List patientUpcomingAppointmentsHistoryList = []; List patientArrivedAppointmentsHistoryList = []; + List patientHomePageUpcomingAppointmentsHistoryList = []; // List patientAllArrivedAppointmentsHistoryList = []; @@ -174,12 +176,14 @@ class MyAppointmentsViewModel extends ChangeNotifier { patientAppointmentsHistoryList.clear(); patientUpcomingAppointmentsHistoryList.clear(); patientArrivedAppointmentsHistoryList.clear(); + patientHomePageUpcomingAppointmentsHistoryList.clear(); // patientAllArrivedAppointmentsHistoryList.clear(); patientEyeMeasurementsAppointmentsHistoryList.clear(); isMyAppointmentsLoading = true; isTimeLineAppointmentsLoading = true; patientMyDoctorsList.clear(); isFullArrivedAppointmentsLoaded = false; + isFullUpcomingAppointmentsLoaded = false; } isTamaraDetailsLoading = true; isAppointmentPatientShareLoading = true; @@ -223,6 +227,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { if (val) { isMyAppointmentsLoading = true; isMyDoctorsDataToBeLoaded = true; + isFullUpcomingAppointmentsLoaded = false; + isFullArrivedAppointmentsLoaded = false; } isAppointmentDataToBeLoaded = val; notifyListeners(); @@ -269,7 +275,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { ); } - Future getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, {bool isForTimeLine = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { + Future getPatientAppointments(bool isActiveAppointment, bool isArrivedAppointments, + {bool isAppointmentForHomePage = false, bool isAppointmentForViewAll = false, bool isForTimeLine = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { if (patientArrivedAppointmentsHistoryList.isNotEmpty) { isPatientHasQueueAppointment = false; notifyListeners(); @@ -279,13 +286,13 @@ class MyAppointmentsViewModel extends ChangeNotifier { } } - // Skip API call if full data is already loaded and we're not requesting timeline view - if (!isForTimeLine && isFullArrivedAppointmentsLoaded && !isAppointmentDataToBeLoaded) { + // Retain data and skip API call once all upcoming appointments are loaded + // (or if home page data is already loaded and view-all is not requested) + // until isAppointmentDataToBeLoaded is set to true. + if (!isAppointmentDataToBeLoaded && (isFullUpcomingAppointmentsLoaded || !isAppointmentForViewAll)) { return; } - if (!isAppointmentDataToBeLoaded) return; - patientAppointmentsByClinic.clear(); patientAppointmentsByHospital.clear(); patientAppointmentsViewList.clear(); @@ -294,11 +301,16 @@ class MyAppointmentsViewModel extends ChangeNotifier { filteredAppointmentList.clear(); patientAppointmentsHistoryList.clear(); patientUpcomingAppointmentsHistoryList.clear(); + if (!isAppointmentForViewAll) { + patientHomePageUpcomingAppointmentsHistoryList.clear(); + } patientArrivedAppointmentsHistoryList.clear(); + setIsAppointmentsHistoryLoading(true); notifyListeners(); final results = await Future.wait([ - myAppointmentsRepo.getPatientAppointments(isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments), + myAppointmentsRepo.getPatientAppointments( + isActiveAppointment: isActiveAppointment, isArrivedAppointments: isArrivedAppointments, isAppointmentForHomePage: isAppointmentForHomePage, isAppointmentForViewAll: isAppointmentForViewAll), myAppointmentsRepo.getPatientAppointments(isActiveAppointment: false, isArrivedAppointments: true, isForTimeLine: isForTimeLine), ]); @@ -307,8 +319,32 @@ class MyAppointmentsViewModel extends ChangeNotifier { (apiResponse) { if (apiResponse.messageStatus == 2) { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + if (isAppointmentForViewAll) { + if (patientHomePageUpcomingAppointmentsHistoryList.isNotEmpty) { + patientUpcomingAppointmentsHistoryList.addAll(patientHomePageUpcomingAppointmentsHistoryList); + } + isFullUpcomingAppointmentsLoaded = true; + } + isMyAppointmentsLoading = false; + isAppointmentDataToBeLoaded = false; + notifyListeners(); } else if (apiResponse.messageStatus == 1) { - patientUpcomingAppointmentsHistoryList = apiResponse.data!; + patientUpcomingAppointmentsHistoryList = List.from(apiResponse.data!); + + if (!isAppointmentForViewAll) { + patientHomePageUpcomingAppointmentsHistoryList = List.from(patientUpcomingAppointmentsHistoryList); + } + if (isAppointmentForViewAll) { + if (patientHomePageUpcomingAppointmentsHistoryList.isNotEmpty) { + final partialAppointmentNos = patientHomePageUpcomingAppointmentsHistoryList.map((e) => e.appointmentNo?.toString()).whereType().toSet(); + patientUpcomingAppointmentsHistoryList.removeWhere( + (appointment) => partialAppointmentNos.contains(appointment.appointmentNo?.toString()), + ); + patientUpcomingAppointmentsHistoryList.insertAll(0, patientHomePageUpcomingAppointmentsHistoryList); + } + isFullUpcomingAppointmentsLoaded = true; + } + isMyAppointmentsLoading = false; isAppointmentDataToBeLoaded = false; notifyListeners(); @@ -324,6 +360,13 @@ class MyAppointmentsViewModel extends ChangeNotifier { (apiResponse) { if (apiResponse.messageStatus == 2) { // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + isMyAppointmentsLoading = false; + isAppointmentDataToBeLoaded = false; + if (!isForTimeLine) { + isArrivedAppointmentDataLoaded = true; + isFullArrivedAppointmentsLoaded = true; + } + notifyListeners(); } else if (apiResponse.messageStatus == 1) { patientArrivedAppointmentsHistoryList = apiResponse.data!; isMyAppointmentsLoading = false; @@ -343,10 +386,7 @@ class MyAppointmentsViewModel extends ChangeNotifier { patientAppointmentsHistoryList.addAll(patientUpcomingAppointmentsHistoryList); patientAppointmentsHistoryList.addAll(patientArrivedAppointmentsHistoryList); - filteredAppointmentList.addAll(patientAppointmentsHistoryList); - - // Build grouped list immediately so the UI has data for the default (By Clinic) view. - _groupAppointmentsByClinicAndHospital(); + updateListWRTTab(selectedTabIndex); // if (patientArrivedAppointmentsHistoryList.isNotEmpty) { isPatientHasQueueAppointment = false; @@ -359,7 +399,6 @@ class MyAppointmentsViewModel extends ChangeNotifier { } // } - getFiltersForSelectedAppointmentList(filteredAppointmentList); notifyListeners(); } diff --git a/lib/presentation/appointments/my_appointments_page.dart b/lib/presentation/appointments/my_appointments_page.dart index e15edb47..ec0e4503 100644 --- a/lib/presentation/appointments/my_appointments_page.dart +++ b/lib/presentation/appointments/my_appointments_page.dart @@ -43,9 +43,11 @@ class _MyAppointmentsPageState extends State { @override void initState() { scheduleMicrotask(() { - if (!myAppointmentsViewModel.isMyAppointmentsLoading) { + if (myAppointmentsViewModel.isAppointmentDataToBeLoaded || !myAppointmentsViewModel.isFullUpcomingAppointmentsLoaded) { myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: false); + myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: false, isAppointmentForViewAll: true, isAppointmentForHomePage: false); + } else { + myAppointmentsViewModel.updateListWRTTab(myAppointmentsViewModel.selectedTabIndex); } // myAppointmentsViewModel.changeTabToArrived(); }); diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index a11bd611..048d6afc 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -166,7 +166,7 @@ class _LandingPageState extends State { immediateLiveCareViewModel.initImmediateLiveCare(); immediateLiveCareViewModel.getPatientLiveCareHistory(); myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: true); + myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: true, isAppointmentForHomePage: true, isAppointmentForViewAll: false); emergencyServicesViewModel.checkPatientERAdvanceBalance(); // myAppointmentsViewModel.getPatientAppointmentQueueDetails(); notificationsViewModel.initNotificationsViewModel(); @@ -291,7 +291,7 @@ class _LandingPageState extends State { // Refresh Appointments Data myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: true); + myAppointmentsViewModel.getPatientAppointments(true, false, isForTimeLine: true, isAppointmentForHomePage: true, isAppointmentForViewAll: false); medicalFileViewModel.getPatientAllergiesList(); // Refresh Appointments Data // habibWalletVM.initHabibWalletProvider();