From f19d06512aae7a8d8ddc2290b8a79f6dfdbeb413 Mon Sep 17 00:00:00 2001 From: tahaalam Date: Mon, 5 Jan 2026 09:53:30 +0300 Subject: [PATCH] filters changed in region selection bottom sheet --- lib/core/utils/utils.dart | 11 + .../appointment_via_region_viewmodel.dart | 88 +++++++- .../hospital_bottom_sheet_body.dart | 199 ++++++++++++------ .../region_list_widget.dart | 3 +- .../book_appointment_page.dart | 30 ++- .../book_appointment/select_clinic_page.dart | 35 ++- 6 files changed, 299 insertions(+), 67 deletions(-) diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 0302818..8d13190 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -868,6 +868,17 @@ class Utils { isHMC: hospital.isHMC); } + + static HospitalsModel? convertToHospitalsModel(PatientDoctorAppointmentList? item) { + if (item == null) return null; + return HospitalsModel( + name: item.filterName, + nameN: item.filterName, + distanceInKilometers: item.distanceInKMs, + isHMC: item.isHMC, + ); + } + static bool havePrivilege(int id) { bool isHavePrivilege = false; try { diff --git a/lib/features/my_appointments/appointment_via_region_viewmodel.dart b/lib/features/my_appointments/appointment_via_region_viewmodel.dart index f51f701..c5dcaf6 100644 --- a/lib/features/my_appointments/appointment_via_region_viewmodel.dart +++ b/lib/features/my_appointments/appointment_via_region_viewmodel.dart @@ -1,6 +1,10 @@ import 'package:flutter/foundation.dart' show ChangeNotifier; +import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart' show AppState; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; +import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/dental_chief_complaints_page.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/laser/laser_appointment.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/select_clinic_page.dart'; @@ -30,7 +34,14 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier { AppointmentViaRegionState bottomSheetState = AppointmentViaRegionState.REGION_SELECTION; final AppState appState; - + TextEditingController searchController = TextEditingController(); + List? hospitalList; + List? hmgHospitalList; + List? hmcHospitalList; + List? displayList; + FacilitySelection selectedFacility = FacilitySelection.ALL; + int hmgCount = 0; + int hmcCount = 0; RegionBottomSheetType regionBottomSheetType = RegionBottomSheetType.FOR_REGION; AppointmentViaRegionViewmodel({required this.navigationService,required this.appState}); @@ -40,6 +51,35 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier { notifyListeners(); } + void setDisplayListAndRegionHospitalList(PatientDoctorAppointmentListByRegion? registeredDoctorMap){ + if(registeredDoctorMap == null) { + return; + } + selectedFacility = FacilitySelection.ALL; + hmcHospitalList = []; + hmgHospitalList = []; + hospitalList = []; + displayList = []; + for(var data in registeredDoctorMap.hmgDoctorList!){ + hmgHospitalList?.add(data); + + } + + for(var data in registeredDoctorMap.hmcDoctorList!){ + hmcHospitalList?.add(data); + + } + + hospitalList!.addAll(hmgHospitalList!); + hospitalList!.addAll(hmcHospitalList!); + + hmcCount = registeredDoctorMap.hmcSize; + hmgCount = registeredDoctorMap.hmgSize; + + getDisplayList(); + + } + void setFacility(String? facility) { selectedFacilityType = facility; notifyListeners(); @@ -71,7 +111,7 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier { setSelectedRegionId(null); break; case AppointmentViaRegionState.HOSPITAL_SELECTION: - setBottomSheetState(AppointmentViaRegionState.TYPE_SELECTION); + setBottomSheetState(AppointmentViaRegionState.REGION_SELECTION); break; default: } @@ -129,4 +169,48 @@ class AppointmentViaRegionViewmodel extends ChangeNotifier { ), ); } + + searchHospitals(String query) { + if (query.isEmpty) { + getDisplayList(); + return; + } + List? sourceList; + switch (selectedFacility) { + case FacilitySelection.ALL: + sourceList = hospitalList; + break; + case FacilitySelection.HMG: + sourceList = hmgHospitalList; + break; + case FacilitySelection.HMC: + sourceList = hmcHospitalList; + break; + } + displayList = sourceList?.where((hospital) => hospital.filterName != null && hospital.filterName!.toLowerCase().contains(query.toLowerCase())).toList(); + notifyListeners(); + } + + getDisplayList() { + switch (selectedFacility) { + case FacilitySelection.ALL: + displayList = hospitalList; + break; + case FacilitySelection.HMG: + displayList = hmgHospitalList; + break; + case FacilitySelection.HMC: + displayList = hmcHospitalList; + break; + } + notifyListeners(); + } + + + setSelectedFacility(FacilitySelection selection) { + selectedFacility = selection; + notifyListeners(); + } + + } diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart index ad48a6d..eed45df 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart @@ -1,58 +1,151 @@ import 'package:easy_localization/easy_localization.dart' show StringTranslateExtension; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; +import 'package:hmg_patient_app_new/core/utils/debouncer.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.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/appointment_via_region_viewmodel.dart'; import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.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/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart'; import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:provider/provider.dart'; +import '../../../../features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel; +import '../../../emergency_services/call_ambulance/widgets/type_selection_widget.dart' show TypeSelectionWidget; + +// class HospitalBottomSheetBody extends StatelessWidget { +// late BookAppointmentsViewModel appointmentsViewModel; +// late AppointmentViaRegionViewmodel regionalViewModel; +// final TextEditingController searchText = TextEditingController(); +// +// HospitalBottomSheetBody({super.key}); +// +// @override +// Widget build(BuildContext context) { +// appointmentsViewModel = Provider.of(context); +// regionalViewModel = Provider.of(context); +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// LocaleKeys.selectHospital.tr(), +// style: TextStyle( +// fontSize: 21, +// fontWeight: FontWeight.w600, +// color: AppColors.blackColor, +// ), +// ), +// Text( +// LocaleKeys.selectHospitalSubTitle.tr(), +// style: TextStyle( +// fontSize: 16, +// fontWeight: FontWeight.w500, +// color: AppColors.greyTextColor, +// ), +// ), +// SizedBox(height: 16.h), +// TextInputWidget( +// labelText: LocaleKeys.search.tr(), +// hintText: LocaleKeys.searchHospital.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( +// height: MediaQuery.sizeOf(context).height * .4, +// child: ListView.separated( +// itemBuilder: (_, index) { +// var hospital = regionalViewModel.selectedFacilityType == FacilitySelection.HMG.name +// ? appointmentsViewModel.filteredHospitalList!.registeredDoctorMap![regionalViewModel.selectedRegionId!]!.hmgDoctorList![index] +// : appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId!]?.hmcDoctorList?[index]; +// return HospitalListItem( +// hospitalData: hospital, +// isLocationEnabled: appointmentsViewModel.isLocationEnabled(), +// ).onPress(() { +// regionalViewModel.setHospitalModel(hospital); +// if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION) { +// regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); +// regionalViewModel.handleLastStepForRegion(); +// } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { +// regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); +// regionalViewModel.handleLastStepForClinic(); +// } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { +// regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); +// regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); +// // regionalViewModel.handleLastStepForClinic(); +// } +// }); +// }, +// separatorBuilder: (_, __) => SizedBox( +// height: 16.h, +// ), +// itemCount: (regionalViewModel.selectedFacilityType == FacilitySelection.HMG.name +// ? (appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId]?.hmgDoctorList) +// : (appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId]?.hmcDoctorList)) +// ?.length ?? +// 0), +// ) +// ], +// ); +// } +// } + class HospitalBottomSheetBody extends StatelessWidget { - late BookAppointmentsViewModel appointmentsViewModel; - late AppointmentViaRegionViewmodel regionalViewModel; - final TextEditingController searchText = TextEditingController(); - HospitalBottomSheetBody({super.key}); + final TextEditingController searchText ; + final Debouncer debouncer = Debouncer(milliseconds: 500); + + final int hmcCount; + final int hmgCount; + final List? displayList; + final FacilitySelection selectedFacility; + final Function(FacilitySelection) onFacilityClicked; + final Function(PatientDoctorAppointmentList) onHospitalClicked; + final Function(String) onHospitalSearch; + + HospitalBottomSheetBody({super.key, required this.hmcCount, required this.hmgCount, this.displayList, required this.selectedFacility, required this.onFacilityClicked, required this.onHospitalClicked, required this.onHospitalSearch, required this.searchText}); @override Widget build(BuildContext context) { - appointmentsViewModel = Provider.of(context); - regionalViewModel = Provider.of(context); + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - LocaleKeys.selectHospital.tr(), - style: TextStyle( - fontSize: 21, - fontWeight: FontWeight.w600, - color: AppColors.blackColor, - ), - ), - Text( - LocaleKeys.selectHospitalSubTitle.tr(), - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: AppColors.greyTextColor, - ), - ), - SizedBox(height: 16.h), TextInputWidget( labelText: LocaleKeys.search.tr(), hintText: LocaleKeys.searchHospital.tr(), controller: searchText, onChange: (value) { - appointmentsViewModel.filterHospitalListByString( - value, regionalViewModel.selectedRegionId, regionalViewModel.selectedFacilityType == FacilitySelection.HMG.name); + debouncer.run((){ + onHospitalSearch(value??""); + }); }, isEnable: true, prefix: null, + autoFocus: false, isBorderAllowed: false, keyboardType: TextInputType.text, @@ -64,46 +157,34 @@ class HospitalBottomSheetBody extends StatelessWidget { ), ), SizedBox(height: 24.h), - // TypeSelectionWidget( - // hmcCount: "0", - // hmgCount: "0", - // ), - // SizedBox(height: 21.h), + TypeSelectionWidget( + selectedFacility:selectedFacility , + hmcCount: hmcCount.toString(), + hmgCount: hmgCount.toString(), + onitemClicked: (selectedValue){ + onFacilityClicked(selectedValue); + }, + ), + SizedBox(height: 21.h), SizedBox( - height: MediaQuery.sizeOf(context).height * .4, - child: ListView.separated( - itemBuilder: (_, index) { - var hospital = regionalViewModel.selectedFacilityType == FacilitySelection.HMG.name - ? appointmentsViewModel.filteredHospitalList!.registeredDoctorMap![regionalViewModel.selectedRegionId!]!.hmgDoctorList![index] - : appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId!]?.hmcDoctorList?[index]; + height: MediaQuery.sizeOf(context).height * .4, + child: ListView.separated( + itemBuilder: (_, index) + { + var hospital = displayList?[index]; return HospitalListItem( hospitalData: hospital, - isLocationEnabled: appointmentsViewModel.isLocationEnabled(), + isLocationEnabled: true, ).onPress(() { - regionalViewModel.setHospitalModel(hospital); - if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION) { - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); - regionalViewModel.handleLastStepForRegion(); - } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); - regionalViewModel.handleLastStepForClinic(); - } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); - regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); - // regionalViewModel.handleLastStepForClinic(); - } - }); - }, + onHospitalClicked(hospital!); + });}, separatorBuilder: (_, __) => SizedBox( - height: 16.h, - ), - itemCount: (regionalViewModel.selectedFacilityType == FacilitySelection.HMG.name - ? (appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId]?.hmgDoctorList) - : (appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[regionalViewModel.selectedRegionId]?.hmcDoctorList)) - ?.length ?? - 0), - ) + height: 16.h, + ), + itemCount: displayList?.length ?? 0, + )) ], ); } } + diff --git a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart index 2def72c..6588c2e 100644 --- a/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart +++ b/lib/presentation/appointments/widgets/region_bottomsheet/region_list_widget.dart @@ -79,7 +79,8 @@ class _RegionBottomSheetBodyState extends State { hmgCount: "${myAppointmentsVM.hospitalList?.registeredDoctorMap?[key]?.hmgSize ?? 0}", ).onPress(() { regionalViewModel.setSelectedRegionId(key); - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.TYPE_SELECTION); + regionalViewModel.setDisplayListAndRegionHospitalList(myAppointmentsVM.hospitalList?.registeredDoctorMap![key]); + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); }); }, ), diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 5aa1b7c..76dc1be 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -35,6 +35,7 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:provider/provider.dart'; import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart'; +// import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/widgets/HospitalBottomSheetBody.dart'; class BookAppointmentPage extends StatefulWidget { const BookAppointmentPage({super.key}); @@ -511,7 +512,34 @@ class _BookAppointmentPageState extends State { ); } if (data.bottomSheetState == AppointmentViaRegionState.HOSPITAL_SELECTION) { - return HospitalBottomSheetBody(); + return HospitalBottomSheetBody( + searchText: data.searchController, + displayList: data.displayList, + onFacilityClicked: (value) { + data.setSelectedFacility(value); + data.getDisplayList(); + }, + onHospitalClicked: (hospital) { + regionalViewModel.setHospitalModel(hospital); + if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); + regionalViewModel.handleLastStepForRegion(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinic(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { + var appointmentsViewModel = Provider.of(context); + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); + } + }, + onHospitalSearch: (value) { + data.searchHospitals(value ?? ""); + }, + selectedFacility: data.selectedFacility, + hmcCount: data.hmcCount, + hmgCount: data.hmgCount, + ); } if (data.bottomSheetState == AppointmentViaRegionState.CLINIC_SELECTION) { // Navigator.of(context).pop(); diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index 450e86b..48c0cd5 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -1019,12 +1019,12 @@ class _SelectClinicPageState extends State { regionalViewModel.setBottomSheetType(type); // AppointmentViaRegionViewmodel? viewmodel = null; showCommonBottomSheetWithoutHeight(context, title: "", titleWidget: Consumer(builder: (_, data, __) => getTitle(data)), isDismissible: false, - child: Consumer(builder: (_, data, __) { - return getRegionalSelectionWidget(data); + child: Consumer(builder: (context, data, __) { + return getRegionalSelectionWidget(data, context); }), callBackFunc: () {}); } - Widget getRegionalSelectionWidget(AppointmentViaRegionViewmodel data) { + Widget getRegionalSelectionWidget(AppointmentViaRegionViewmodel data, BuildContext context) { if (data.bottomSheetState == AppointmentViaRegionState.REGION_SELECTION) { return RegionBottomSheetBody(); } @@ -1035,7 +1035,34 @@ class _SelectClinicPageState extends State { ); } if (data.bottomSheetState == AppointmentViaRegionState.HOSPITAL_SELECTION) { - return HospitalBottomSheetBody(); + return HospitalBottomSheetBody( + searchText: data.searchController, + displayList: data.displayList, + onFacilityClicked: (value) { + data.setSelectedFacility(value); + data.getDisplayList(); + }, + onHospitalClicked: (hospital) { + regionalViewModel.setHospitalModel(hospital); + if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_REGION) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); + regionalViewModel.handleLastStepForRegion(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.FOR_CLINIIC) { + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinic(); + } else if (regionalViewModel.regionBottomSheetType == RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER) { + var appointmentsViewModel = Provider.of(context, listen: false); + regionalViewModel.setBottomSheetState(AppointmentViaRegionState.DOCTOR_SELECTION); + regionalViewModel.handleLastStepForClinicForDentalAndLaser(appointmentsViewModel.selectedClinic.clinicID ?? -1); + } + }, + onHospitalSearch: (value) { + data.searchHospitals(value ?? ""); + }, + selectedFacility: data.selectedFacility, + hmcCount: data.hmcCount, + hmgCount: data.hmgCount, + ); } if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { //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