added apis

pull/322/head
faizatflutter 1 month ago
parent 7cf593443d
commit 8aa152f1a0

@ -7,8 +7,7 @@ import 'package:hmg_patient_app_new/features/refund_request/models/resp_models/r
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class RefundRequestRepo {
Future<Either<Failure, GenericApiModel<List<RefundableInvoiceItem>>>>
getRefundableInvoices({required int projectID});
Future<Either<Failure, GenericApiModel<List<RefundableInvoiceItem>>>> getRefundableInvoices({required int projectID});
}
class RefundRequestRepoImp implements RefundRequestRepo {
@ -18,8 +17,7 @@ class RefundRequestRepoImp implements RefundRequestRepo {
RefundRequestRepoImp({required this.apiClient, required this.loggerService});
@override
Future<Either<Failure, GenericApiModel<List<RefundableInvoiceItem>>>>
getRefundableInvoices({required int projectID}) async {
Future<Either<Failure, GenericApiModel<List<RefundableInvoiceItem>>>> getRefundableInvoices({required int projectID}) async {
// ApiClient auto-injects: PatientID, TokenID, LanguageID, PatientOutSA,
// PatientTypeID, IPAdress, generalid, VersionID, Channel
Map<String, dynamic> body = {
@ -38,20 +36,14 @@ class RefundRequestRepoImp implements RefundRequestRepo {
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final refundableInvoicesObject =
response['RefundableInvoicesObject'];
final refundableInvoicesObject = response['RefundableInvoicesObject'];
if (refundableInvoicesObject != null) {
final invoiceItemsJson =
refundableInvoicesObject['RefundableInvoiceItems'];
final invoiceItemsJson = refundableInvoicesObject['RefundableInvoiceItems'];
final List<RefundableInvoiceItem> invoicesList =
invoiceItemsJson != null
? (invoiceItemsJson as List)
.map((item) => RefundableInvoiceItem.fromJson(
item as Map<String, dynamic>))
.toList()
: [];
final List<RefundableInvoiceItem> invoicesList = invoiceItemsJson != null
? (invoiceItemsJson as List).map((item) => RefundableInvoiceItem.fromJson(item as Map<String, dynamic>)).toList()
: [];
apiResponse = GenericApiModel<List<RefundableInvoiceItem>>(
messageStatus: messageStatus,
@ -78,4 +70,3 @@ class RefundRequestRepoImp implements RefundRequestRepo {
}
}
}

@ -19,7 +19,12 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
class SelectHospitalBottomSheet extends StatefulWidget {
const SelectHospitalBottomSheet({super.key});
/// Optional callback invoked when the user picks a hospital.
/// When provided, the caller handles the selection instead of the default
/// [HabibWalletViewModel.setSelectedHospital] behaviour.
final void Function(HospitalsModel hospital)? onHospitalSelected;
const SelectHospitalBottomSheet({super.key, this.onHospitalSelected});
@override
State<SelectHospitalBottomSheet> createState() => _SelectHospitalBottomSheetState();
@ -71,6 +76,7 @@ class _SelectHospitalBottomSheetState extends State<SelectHospitalBottomSheet> {
_updateDisplayList();
}
}
habibWalletVM.addListener(listener);
habibWalletVM.getProjectsList();
}
@ -195,22 +201,26 @@ class _SelectHospitalBottomSheetState extends State<SelectHospitalBottomSheet> {
child: Center(child: Utils.getLoadingWidget()),
)
: SizedBox(
height: MediaQuery.sizeOf(context).height * .4,
child: ListView.separated(
itemBuilder: (_, index) {
return HospitalListItemAdvancePayment(
hospitalModel: displayList[index],
isLocationEnabled: sortByLocation,
).onPress(() {
habibWalletVM.setSelectedHospital(displayList[index]);
Navigator.of(context).pop();
});
},
separatorBuilder: (_, __) => SizedBox(
height: 16.h,
),
itemCount: displayList.length),
)
height: MediaQuery.sizeOf(context).height * .4,
child: ListView.separated(
itemBuilder: (_, index) {
return HospitalListItemAdvancePayment(
hospitalModel: displayList[index],
isLocationEnabled: sortByLocation,
).onPress(() {
if (widget.onHospitalSelected != null) {
widget.onHospitalSelected!(displayList[index]);
} else {
habibWalletVM.setSelectedHospital(displayList[index]);
}
Navigator.of(context).pop();
});
},
separatorBuilder: (_, __) => SizedBox(
height: 16.h,
),
itemCount: displayList.length),
)
],
);
}

@ -30,7 +30,7 @@ import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dar
import 'package:hmg_patient_app_new/presentation/home/service_info_page.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart';
import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart';
import 'package:hmg_patient_app_new/presentation/service_price/services_price_list_page.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
@ -42,12 +42,12 @@ import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/dependencies.dart' show getIt;
import '../../core/dependencies.dart';
class ServicesPage extends StatefulWidget {
bool showBackIcon;
final bool showBackIcon;
ServicesPage({super.key, this.showBackIcon = true});
const ServicesPage({super.key, this.showBackIcon = true});
@override
State<ServicesPage> createState() => _ServicesPageState();
@ -560,55 +560,55 @@ class _ServicesPageState extends State<ServicesPage> {
// isExpanded: false, letterSpacing: -1)
// .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.r, width: 80.w, height: 24.h);
})
: LocaleKeys.loginToViewWalletBalance.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.recharge_icon,
iconSize: 24.w,
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: LocaleKeys.recharge.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
),
),
SizedBox(width: 16.w),
Expanded(
child: Container(
height: 183.h,
width: 183.h,
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
: LocaleKeys.loginToViewWalletBalance.tr().toText12(isBold: true, maxLine: 2),
Spacer(),
getIt.get<AppState>().isAuthenticated
? CustomButton(
height: 40.h,
icon: AppAssets.recharge_icon,
iconSize: 24.w,
iconColor: AppColors.infoColor,
textColor: AppColors.infoColor,
text: LocaleKeys.recharge.tr(),
borderWidth: 0.w,
isBold: true,
borderColor: Colors.transparent,
backgroundColor: Color(0xff45A2F8).withValues(alpha: 0.08),
padding: EdgeInsets.all(8.w),
fontSize: 14.f,
onPressed: () {
Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage()));
},
)
: SizedBox.shrink(),
],
).onPress(() async {
if (getIt.get<AppState>().isAuthenticated) {
Navigator.of(context).push(CustomPageRoute(page: HabibWalletPage()));
} else {
await getIt.get<AuthenticationViewModel>().onLoginPressed();
}
}),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
),
SizedBox(width: 16.w),
Expanded(
child: Container(
height: 183.h,
width: 183.h,
padding: EdgeInsets.all(16.w),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 8.w,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Utils.buildSvgWithAssets(
icon: AppAssets.services_medical_file_icon, width: 40.w, height: 40.h, applyThemeColor: false),
LocaleKeys.familyTitle.tr().toText16(isBold: true, maxlines: 2).expanded,

@ -11,7 +11,7 @@ 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/refund_request/refund_request_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/refund_request/widgets/select_hospital_bottom_sheet_refund.dart';
import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
@ -124,7 +124,9 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
context,
title: LocaleKeys.selectHospital.tr(context: context),
isDismissible: false,
child: SelectHospitalBottomSheetRefund(),
child: SelectHospitalBottomSheet(
onHospitalSelected: (hospital) => _vm.setSelectedHospital(hospital),
),
callBackFunc: () {},
);
}),

@ -1,223 +0,0 @@
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/features/refund_request/refund_request_view_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';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
class SelectHospitalBottomSheetRefund extends StatefulWidget {
const SelectHospitalBottomSheetRefund({super.key});
@override
State<SelectHospitalBottomSheetRefund> createState() =>
_SelectHospitalBottomSheetRefundState();
}
class _SelectHospitalBottomSheetRefundState
extends State<SelectHospitalBottomSheetRefund> {
late RefundRequestViewModel refundVM;
late HabibWalletViewModel habibWalletVM;
bool sortByLocation = false;
bool isLoading = false;
List<HospitalsModel> displayList = [];
@override
void initState() {
super.initState();
final appState = getIt.get<AppState>();
sortByLocation = (appState.userLat != 0.0) && (appState.userLong != 0.0);
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateDisplayList();
});
}
void _updateDisplayList() {
final appState = getIt.get<AppState>();
// Reuse the same hospital list already loaded in HabibWalletViewModel
final hospitals = List<HospitalsModel>.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>();
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>();
appState.resetLocation();
setState(() {
sortByLocation = false;
isLoading = true;
});
_refreshHospitalListAfterApi();
}
}
@override
Widget build(BuildContext context) {
refundVM = context.read<RefundRequestViewModel>();
habibWalletVM = context.read<HabibWalletViewModel>();
if (displayList.isEmpty && habibWalletVM.advancePaymentHospitals.isNotEmpty) {
displayList = List.from(habibWalletVM.advancePaymentHospitals);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.selectHospitalForAdvancePayment
.tr(context: context)
.toText16(color: AppColors.greyTextColor, isBold: true),
SizedBox(height: 16.h),
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, isBold: true),
],
),
],
),
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(
itemCount: displayList.length,
separatorBuilder: (_, __) => SizedBox(height: 16.h),
itemBuilder: (_, index) {
return HospitalListItemAdvancePayment(
hospitalModel: displayList[index],
isLocationEnabled: sortByLocation,
).onPress(() {
refundVM.setSelectedHospital(displayList[index]);
Navigator.of(context).pop();
});
},
),
),
],
);
}
}

@ -19,7 +19,9 @@ import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/presentation/home_health_care/hhc_procedures_page.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/presentation/my_family/my_family.dart';
import 'package:hmg_patient_app_new/presentation/servicesPriceList/services_price_list_page.dart';
import 'package:hmg_patient_app_new/presentation/parking/paking_page.dart';
import 'package:hmg_patient_app_new/presentation/refund_request/refund_request_create_page.dart';
import 'package:hmg_patient_app_new/presentation/service_price/services_price_list_page.dart';
import 'package:hmg_patient_app_new/presentation/smartwatches/smartwatch_home_page.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/organ_selector_screen.dart';
import 'package:hmg_patient_app_new/presentation/symptoms_checker/possible_conditions_screen.dart';
@ -41,8 +43,6 @@ import '../core/dependencies.dart';
import '../features/monthly_reports/monthly_reports_repo.dart';
import '../features/monthly_reports/monthly_reports_view_model.dart';
import '../features/qr_parking/qr_parking_view_model.dart';
import 'package:hmg_patient_app_new/presentation/parking/paking_page.dart';
import 'package:hmg_patient_app_new/presentation/refund_request/refund_request_create_page.dart';
import '../services/error_handler_service.dart';
class AppRoutes {

Loading…
Cancel
Save