pull/204/head
haroon amjad 2 days ago
parent a45980162d
commit e29aba81da

@ -1597,5 +1597,6 @@
"tests": "تحليل", "tests": "تحليل",
"calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.", "calendarPermissionAlert": "يرجى منح إذن الوصول إلى التقويم من إعدادات التطبيق لضبط تذكير تناول الدواء.",
"sortByLocation": "الترتيب حسب الموقع", "sortByLocation": "الترتيب حسب الموقع",
"sortByNearestLocation": "فرز حسب الأقرب إلى موقعك" "sortByNearestLocation": "فرز حسب الأقرب إلى موقعك",
"giveLocationPermissionForNearestList": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق لعرض أقرب المواقع."
} }

@ -1591,5 +1591,6 @@
"tests": "tests", "tests": "tests",
"calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.", "calendarPermissionAlert": "Please grant calendar access permission from app settings to set medication reminder.",
"sortByLocation": "Sort by location", "sortByLocation": "Sort by location",
"sortByNearestLocation": "Sort by nearest to your location" "sortByNearestLocation": "Sort by nearest to your location",
"giveLocationPermissionForNearestList": "Please grant location permission from app settings to see the nearest locations."
} }

@ -1592,5 +1592,6 @@ abstract class LocaleKeys {
static const calendarPermissionAlert = 'calendarPermissionAlert'; static const calendarPermissionAlert = 'calendarPermissionAlert';
static const sortByLocation = 'sortByLocation'; static const sortByLocation = 'sortByLocation';
static const sortByNearestLocation = 'sortByNearestLocation'; static const sortByNearestLocation = 'sortByNearestLocation';
static const giveLocationPermissionForNearestList = 'giveLocationPermissionForNearestList';
} }

@ -1,20 +1,19 @@
import 'package:easy_localization/easy_localization.dart' show StringTranslateExtension; import 'package:easy_localization/easy_localization.dart' show StringTranslateExtension;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/enums.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/debouncer.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
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/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/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.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/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/theme/colors.dart' show AppColors;
import 'package:hmg_patient_app_new/widgets/input_widget.dart'; 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; import '../../../emergency_services/call_ambulance/widgets/type_selection_widget.dart' show TypeSelectionWidget;
// class HospitalBottomSheetBody extends StatelessWidget { // class HospitalBottomSheetBody extends StatelessWidget {
@ -125,8 +124,10 @@ class HospitalBottomSheetBody extends StatelessWidget {
final Function(FacilitySelection) onFacilityClicked; final Function(FacilitySelection) onFacilityClicked;
final Function(PatientDoctorAppointmentList) onHospitalClicked; final Function(PatientDoctorAppointmentList) onHospitalClicked;
final Function(String) onHospitalSearch; final Function(String) onHospitalSearch;
final bool sortByLocation;
final Function(bool)? onSortByLocationToggle;
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}); 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, this.sortByLocation = false, this.onSortByLocationToggle});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -156,7 +157,37 @@ class HospitalBottomSheetBody extends StatelessWidget {
horizontal: ResponsiveExtension(15).h, horizontal: ResponsiveExtension(15).h,
), ),
), ),
SizedBox(height: 24.h), SizedBox(height: 16.h),
if (onSortByLocationToggle != null)
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),
// SizedBox(height: 4.h),
LocaleKeys.sortByNearestLocation.tr(context: context).toText11(color: AppColors.textColorLight, weight: FontWeight.w500),
],
),
],
),
Switch(
value: sortByLocation,
onChanged: onSortByLocationToggle,
activeThumbColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: 0.15),
),
],
),
),
if (onSortByLocationToggle != null) SizedBox(height: 8.h),
TypeSelectionWidget( TypeSelectionWidget(
selectedFacility:selectedFacility , selectedFacility:selectedFacility ,
hmcCount: hmcCount.toString(), hmcCount: hmcCount.toString(),
@ -174,7 +205,7 @@ class HospitalBottomSheetBody extends StatelessWidget {
var hospital = displayList?[index]; var hospital = displayList?[index];
return HospitalListItem( return HospitalListItem(
hospitalData: hospital, hospitalData: hospital,
isLocationEnabled: true, isLocationEnabled: sortByLocation,
).onPress(() { ).onPress(() {
onHospitalClicked(hospital!); onHospitalClicked(hospital!);
});}, });},

@ -97,14 +97,14 @@ class HospitalListItem extends StatelessWidget {
// ) // )
], ],
)), )),
Visibility( // Visibility(
visible: !isLocationEnabled, // visible: !isLocationEnabled,
child: AppCustomChipWidget( // child: AppCustomChipWidget(
labelText: "Location turned off", // labelText: "Location turned off",
deleteIcon: AppAssets.location_unavailable, // deleteIcon: AppAssets.location_unavailable,
deleteIconSize: Size(9.w, 12.h), // deleteIconSize: Size(9.w, 12.h),
textColor: AppColors.blackColor, // textColor: AppColors.blackColor,
)), // )),
], ],
); );
} }

@ -195,7 +195,7 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
title: LocaleKeys.notice.tr(context: context), title: LocaleKeys.notice.tr(context: context),
context, context,
child: Utils.getWarningWidget( child: Utils.getWarningWidget(
loadingText: "Please grant location permission from app settings to see better results", loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true, isShowActionButtons: true,
onCancelTap: () { onCancelTap: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -215,7 +215,7 @@ class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> {
title: LocaleKeys.notice.tr(context: context), title: LocaleKeys.notice.tr(context: context),
context, context,
child: Utils.getWarningWidget( child: Utils.getWarningWidget(
loadingText: "Please grant location permission from app settings to see better results", loadingText: LocaleKeys.giveLocationPermissionForNearestList.tr(context: context),
isShowActionButtons: true, isShowActionButtons: true,
onCancelTap: () { onCancelTap: () {
Navigator.of(context).pop(); Navigator.of(context).pop();

@ -7,6 +7,7 @@ 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_export.dart';
import 'package:hmg_patient_app_new/core/app_state.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -32,6 +33,7 @@ import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart' show showC
import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart'; import '../appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart';
@ -510,6 +512,8 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.CLINIC_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.CLINIC_SELECTION) {
@ -523,6 +527,78 @@ class _BookAppointmentPageState extends State<BookAppointmentPage> {
return SizedBox.shrink(); return SizedBox.shrink();
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
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,
);
regionVM.setSortByLocation(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,
);
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
bookAppointmentsViewModel.getRegionMappedProjectList();
}
getTitle(AppointmentViaRegionViewmodel data) { getTitle(AppointmentViaRegionViewmodel data) {
if (data.selectedRegionId == null) { if (data.selectedRegionId == null) {
return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600); return LocaleKeys.selectRegion.tr(context: context).toText20(weight: FontWeight.w600);

@ -85,10 +85,12 @@ class DoctorProfilePage extends StatelessWidget {
runSpacing: 4.h, runSpacing: 4.h,
children: [ children: [
AppCustomChipWidget( AppCustomChipWidget(
backgroundColor: AppColors.whiteColor,
iconColor: AppColors.ratingColorYellow, iconColor: AppColors.ratingColorYellow,
labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.projectName}", labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.projectName}",
), ),
AppCustomChipWidget( AppCustomChipWidget(
backgroundColor: AppColors.whiteColor,
iconColor: AppColors.ratingColorYellow, iconColor: AppColors.ratingColorYellow,
labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.clinicDescription}", labelText: "${bookAppointmentsViewModel.doctorsProfileResponseModel.clinicDescription}",
), ),

@ -52,7 +52,7 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
children: [ children: [
Expanded( Expanded(
child: CollapsingListView( child: CollapsingListView(
title: LocaleKeys.chooseDoctor.tr(), title: LocaleKeys.chooseDoctor.tr(context: context),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.h), padding: EdgeInsets.symmetric(horizontal: 24.h),
@ -142,49 +142,49 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (bookAppointmentsVM.isDoctorSearchByNameStarted) // if (bookAppointmentsVM.isDoctorSearchByNameStarted)
Row( // Row(
children: [ // children: [
CustomButton( // CustomButton(
text: LocaleKeys.byClinic.tr(context: context), // text: LocaleKeys.byClinic.tr(context: context),
onPressed: () { // onPressed: () {
bookAppointmentsVM.sortFilteredDoctorList(true); // bookAppointmentsVM.sortFilteredDoctorList(true);
}, // },
backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor, // backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2), // borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withOpacity(0.2),
textColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor, // textColor: bookAppointmentsVM.isSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
SizedBox(width: 8.h), // SizedBox(width: 8.h),
CustomButton( // CustomButton(
text: LocaleKeys.byHospital.tr(context: context), // text: LocaleKeys.byHospital.tr(context: context),
onPressed: () { // onPressed: () {
bookAppointmentsVM.sortFilteredDoctorList(false); // bookAppointmentsVM.sortFilteredDoctorList(false);
}, // },
backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor, // backgroundColor: bookAppointmentsVM.isSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor, // borderColor: bookAppointmentsVM.isSortByClinic ? AppColors.textColor.withOpacity(0.2) : AppColors.primaryRedColor,
textColor: bookAppointmentsVM.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor, // textColor: bookAppointmentsVM.isSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
fontSize: 12, // fontSize: 12,
fontWeight: FontWeight.w500, // fontWeight: FontWeight.w500,
borderRadius: 10, // borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h, // height: 40.h,
), // ),
], // ],
).paddingSymmetrical(0.h, 0.h), // ).paddingSymmetrical(0.h, 0.h),
bookAppointmentsVM.isDoctorSearchByNameStarted bookAppointmentsVM.isDoctorSearchByNameStarted
? ListView.separated( ? ListView.separated(
padding: EdgeInsets.only(top: 20.h), padding: EdgeInsets.only(top: 20.h),
shrinkWrap: true, shrinkWrap: true,
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : bookAppointmentsVM.getGroupedFilteredDoctorsList().length, itemCount: bookAppointmentsVM.isDoctorsListLoading ? 5 : bookAppointmentsVM.filteredDoctorList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final isExpanded = bookAppointmentsVM.expandedGroupIndex == index; // final isExpanded = bookAppointmentsVM.expandedGroupIndex == index;
final groupedDoctors = bookAppointmentsVM.getGroupedFilteredDoctorsList(); // final groupedDoctors = bookAppointmentsVM.getGroupedFilteredDoctorsList();
return bookAppointmentsVM.isDoctorsListLoading return bookAppointmentsVM.isDoctorsListLoading
? DoctorCard( ? DoctorCard(
@ -203,112 +203,184 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.h, hasShadow: true),
child: InkWell( child: Container(
onTap: () { key: ValueKey<int>(index),
bookAppointmentsVM.toggleGroupExpansion(index); padding: EdgeInsets.only(top: 12.h),
// After rebuild, ensure the expanded item is visible child: DoctorCard(
WidgetsBinding.instance.addPostFrameCallback((_) { doctorsListResponseModel: bookAppointmentsVM.filteredDoctorList[index],
final key = _itemKeys[index]; isLoading: false,
if (key != null && key.currentContext != null && bookAppointmentsVM.expandedGroupIndex == index) { bookAppointmentsViewModel: bookAppointmentsViewModel,
Scrollable.ensureVisible( ).paddingSymmetrical(16.h, 0.h).onPress(() async {
key.currentContext!, bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.filteredDoctorList[index]);
duration: Duration(milliseconds: 350), LoaderBottomSheet.showLoader();
curve: Curves.easeInOut, await bookAppointmentsVM.getDoctorProfile(
alignment: 0.1, onSuccess: (dynamic respData) {
LoaderBottomSheet.hideLoader();
Navigator.of(context).push(
CustomPageRoute(
page: DoctorProfilePage(),
),
);
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
); );
} },
}); );
}, // Column(
child: Padding( // children: bookAppointmentsVM.doctorsList[index].map<Widget>((entry) {
padding: EdgeInsets.all(16.h), // final doctorIndex = entry.key;
child: Column( // final doctor = entry.value;
crossAxisAlignment: CrossAxisAlignment.start, // final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1;
children: [ // return Column(
Row( // children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, // DoctorCard(
children: [ // doctorsListResponseModel: doctor,
CustomButton( // isLoading: false,
text: "${groupedDoctors[index].length} ${'doctors'}", // bookAppointmentsViewModel: bookAppointmentsViewModel,
onPressed: () {}, // ).onPress(() async {
backgroundColor: AppColors.greyColor, // bookAppointmentsVM.setSelectedDoctor(doctor);
borderColor: AppColors.greyColor, // LoaderBottomSheet.showLoader();
textColor: AppColors.blackColor, // await bookAppointmentsVM.getDoctorProfile(
fontSize: 10, // onSuccess: (dynamic respData) {
fontWeight: FontWeight.w500, // LoaderBottomSheet.hideLoader();
borderRadius: 8, // Navigator.of(context).push(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0), // CustomPageRoute(
height: 30.h), // page: DoctorProfilePage(),
Icon(isExpanded ? Icons.expand_less : Icons.expand_more), // ),
], // );
), // },
SizedBox(height: 8.h), // onError: (err) {
// Clinic/Hospital name as group title // LoaderBottomSheet.hideLoader();
Text( // showCommonBottomSheetWithoutHeight(
bookAppointmentsVM.isSortByClinic // context,
? (groupedDoctors[index].first.clinicName ?? 'Unknown') // child: Utils.getErrorWidget(loadingText: err),
: (groupedDoctors[index].first.projectName ?? 'Unknown'), // callBackFunc: () {},
style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600), // isFullScreen: false,
overflow: TextOverflow.ellipsis, // isCloseButtonVisible: true,
), // );
// Expanded content - list of doctors in this group // },
AnimatedSwitcher( // );
duration: Duration(milliseconds: 400), // }),
child: isExpanded // if (!isLastDoctor)
? Container( // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
key: ValueKey<int>(index), // ],
padding: EdgeInsets.only(top: 12.h), // );
child: Column( // }).toList(),
children: groupedDoctors[index].asMap().entries.map<Widget>((entry) { // ),
final doctorIndex = entry.key; }),
final doctor = entry.value; // InkWell(
final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1; // onTap: () {
return Column( // bookAppointmentsVM.toggleGroupExpansion(index);
children: [ // // After rebuild, ensure the expanded item is visible
DoctorCard( // WidgetsBinding.instance.addPostFrameCallback((_) {
doctorsListResponseModel: doctor, // final key = _itemKeys[index];
isLoading: false, // if (key != null && key.currentContext != null && bookAppointmentsVM.expandedGroupIndex == index) {
bookAppointmentsViewModel: bookAppointmentsViewModel, // Scrollable.ensureVisible(
).onPress(() async { // key.currentContext!,
bookAppointmentsVM.setSelectedDoctor(doctor); // duration: Duration(milliseconds: 350),
LoaderBottomSheet.showLoader(); // curve: Curves.easeInOut,
await bookAppointmentsVM.getDoctorProfile( // alignment: 0.1,
onSuccess: (dynamic respData) { // );
LoaderBottomSheet.hideLoader(); // }
Navigator.of(context).push( // });
CustomPageRoute( // },
page: DoctorProfilePage(), // child: Padding(
), // padding: EdgeInsets.all(16.h),
); // child: Column(
}, // crossAxisAlignment: CrossAxisAlignment.start,
onError: (err) { // children: [
LoaderBottomSheet.hideLoader(); // Row(
showCommonBottomSheetWithoutHeight( // mainAxisAlignment: MainAxisAlignment.spaceBetween,
context, // children: [
child: Utils.getErrorWidget(loadingText: err), // CustomButton(
callBackFunc: () {}, // text: "${groupedDoctors[index].length} ${'doctors'}",
isFullScreen: false, // onPressed: () {},
isCloseButtonVisible: true, // backgroundColor: AppColors.greyColor,
); // borderColor: AppColors.greyColor,
}, // textColor: AppColors.blackColor,
); // fontSize: 10,
}), // fontWeight: FontWeight.w500,
if (!isLastDoctor) // borderRadius: 8,
Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h), // padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
], // height: 30.h),
); // Icon(isExpanded ? Icons.expand_less : Icons.expand_more),
}).toList(), // ],
), // ),
) // SizedBox(height: 8.h),
: SizedBox.shrink(), // // Clinic/Hospital name as group title
), // Text(
], // bookAppointmentsVM.isSortByClinic
), // ? (groupedDoctors[index].first.clinicName ?? 'Unknown')
), // : (groupedDoctors[index].first.projectName ?? 'Unknown'),
// style: TextStyle(fontSize: 16.h, fontWeight: FontWeight.w600),
// overflow: TextOverflow.ellipsis,
// ),
// // Expanded content - list of doctors in this group
// // AnimatedSwitcher(
// // duration: Duration(milliseconds: 400),
// // child: isExpanded
// // ? Container(
// // key: ValueKey<int>(index),
// // padding: EdgeInsets.only(top: 12.h),
// // child: Column(
// // children: groupedDoctors[index].asMap().entries.map<Widget>((entry) {
// // final doctorIndex = entry.key;
// // final doctor = entry.value;
// // final isLastDoctor = doctorIndex == groupedDoctors[index].length - 1;
// // return Column(
// // children: [
// // DoctorCard(
// // doctorsListResponseModel: doctor,
// // isLoading: false,
// // bookAppointmentsViewModel: bookAppointmentsViewModel,
// // ).onPress(() async {
// // bookAppointmentsVM.setSelectedDoctor(doctor);
// // LoaderBottomSheet.showLoader();
// // await bookAppointmentsVM.getDoctorProfile(
// // onSuccess: (dynamic respData) {
// // LoaderBottomSheet.hideLoader();
// // Navigator.of(context).push(
// // CustomPageRoute(
// // page: DoctorProfilePage(),
// // ),
// // );
// // },
// // onError: (err) {
// // LoaderBottomSheet.hideLoader();
// // showCommonBottomSheetWithoutHeight(
// // context,
// // child: Utils.getErrorWidget(loadingText: err),
// // callBackFunc: () {},
// // isFullScreen: false,
// // isCloseButtonVisible: true,
// // );
// // },
// // );
// // }),
// // if (!isLastDoctor)
// // Divider(color: AppColors.borderOnlyColor.withValues(alpha: 0.05), height: 1.h),
// // ],
// // );
// // }).toList(),
// // ),
// // )
// // : SizedBox.shrink(),
// // ),
// ],
// ),
// ),
// ),
), ),
), ),
), ),
), ));
);
}, },
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
) )

@ -7,6 +7,7 @@ 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/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.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/enums.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.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/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -1118,6 +1119,8 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) {
@ -1301,4 +1304,42 @@ class _SelectClinicPageState extends State<SelectClinicPage> {
initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel.currentlySelectedHospitalFromRegionFlow ?? "0")); initDentalAppointmentBookingFlow(int.parse(bookAppointmentsViewModel.currentlySelectedHospitalFromRegionFlow ?? "0"));
return; return;
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
onFailure: () {
regionVM.setSortByLocation(false);
},
onLocationDeniedForever: () {
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
bookAppointmentsViewModel.getRegionMappedProjectList();
}
} }

@ -2,8 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.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_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/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
@ -337,6 +339,8 @@ class PossibleConditionsPage extends StatelessWidget {
selectedFacility: data.selectedFacility, selectedFacility: data.selectedFacility,
hmcCount: data.hmcCount, hmcCount: data.hmcCount,
hmgCount: data.hmgCount, hmgCount: data.hmgCount,
sortByLocation: data.sortByLocation,
onSortByLocationToggle: (value) => _handleSortByLocationToggle(value, data),
); );
} }
if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) { if (data.bottomSheetState == AppointmentViaRegionState.DOCTOR_SELECTION) {
@ -354,4 +358,42 @@ class PossibleConditionsPage extends StatelessWidget {
} }
return SizedBox.shrink(); return SizedBox.shrink();
} }
void _handleSortByLocationToggle(bool value, AppointmentViaRegionViewmodel regionVM) {
if (value) {
final locationUtils = getIt.get<LocationUtils>();
locationUtils.getLocation(
isShowConfirmDialog: true,
onSuccess: (latLng) {
regionVM.setSortByLocation(true);
_refreshHospitalListAfterApi(regionVM);
},
onFailure: () {
regionVM.setSortByLocation(false);
},
onLocationDeniedForever: () {
regionVM.setSortByLocation(false);
},
);
} else {
final appState = getIt.get<AppState>();
appState.resetLocation();
regionVM.setSortByLocation(false);
_refreshHospitalListAfterApi(regionVM);
}
}
void _refreshHospitalListAfterApi(AppointmentViaRegionViewmodel regionVM) {
void listener() {
if (!bookAppointmentsViewModel.isRegionListLoading) {
bookAppointmentsViewModel.removeListener(listener);
final selectedRegion = regionVM.selectedRegionId;
if (selectedRegion != null && bookAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion] != null) {
regionVM.setDisplayListAndRegionHospitalList(bookAppointmentsViewModel.hospitalList!.registeredDoctorMap![selectedRegion]);
}
}
}
bookAppointmentsViewModel.addListener(listener);
bookAppointmentsViewModel.getRegionMappedProjectList();
}
} }

Loading…
Cancel
Save