ER Online Check-In implemented

pull/92/head
haroon amjad 3 months ago
parent cc1e073f6d
commit 9a48421271

@ -3,6 +3,8 @@ import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/model/resp_model/EROnlineCheckInPaymentDetailsResponse.dart';
import 'package:hmg_patient_app_new/features/emergency_services/model/resp_model/ProjectAvgERWaitingTime.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_models/rrt_procedures_response_model.dart';
@ -19,6 +21,15 @@ abstract class EmergencyServicesRepo {
Future<Either<Failure, GenericApiModel<List<HospitalsModel>>>> getProjectList();
Future<Either<Failure, GenericApiModel<EROnlineCheckInPaymentDetailsResponse>>> checkPatientERPaymentInformation({int projectID});
Future<Either<Failure, GenericApiModel<dynamic>>> ER_CreateAdvancePayment(
{required int projectID, required AuthenticatedUser authUser, required num paymentAmount, required String paymentMethodName, required String paymentReference});
Future<Either<Failure, GenericApiModel<dynamic>>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo});
Future<Either<Failure, GenericApiModel<dynamic>>> getProjectIDFromNFC({required String nfcCode});
Future<Either<Failure, GenericApiModel<dynamic>>> autoGenerateInvoiceERClinic({required int projectID});
}
class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@ -208,4 +219,170 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> ER_CreateAdvancePayment(
{required int projectID, required AuthenticatedUser authUser, required num paymentAmount, required String paymentMethodName, required String paymentReference}) async {
Map<String, dynamic> mapDevice = {
"LanguageID": 1,
"ERAdvanceAmount": {
"ProjectId": projectID,
"PatientId": authUser.patientId,
"ClinicId": 10,
"DepositorName": "${authUser.firstName!} ${authUser.lastName!}",
"MemberId": authUser.patientId,
"NationalityID": authUser.nationalityId,
"PaymentAmount": paymentAmount,
"PaymentDate": DateUtil.convertDateToString(DateTime.now()),
"PaymentMethodName": paymentMethodName,
"PaymentReferenceNumber": paymentReference,
"SourceType": 2
}
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ER_CREATE_ADVANCE_PAYMENT,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final vidaAdvanceNumber = response['ER_AdvancePaymentResponse']['AdvanceNumber'].toString();
print(vidaAdvanceNumber);
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: vidaAdvanceNumber,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo}) async {
Map<String, dynamic> requestBody = {
"AdvanceNumber": advanceNumber,
"AdvanceNumber_VP": advanceNumber,
"PaymentReferenceNumber": paymentReference,
"AppointmentID": appointmentNo,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ADD_ADVANCE_NUMBER_REQUEST,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> getProjectIDFromNFC({required String nfcCode}) async {
Map<String, dynamic> mapDevice = {"nFC_Code": nfcCode};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
GET_PROJECT_FROM_NFC,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final projectID = response['GetProjectByNFC'][0]["ProjectID"];
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: projectID,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> autoGenerateInvoiceERClinic({required int projectID}) async {
Map<String, dynamic> mapDevice = {
"ProjectID": projectID,
"ClinicID": "10",
"IsAdvanceAvailable": true,
"MemberID": 102,
"PaymentMethod": "VISA",
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
AUTO_GENERATE_INVOICE_ER,
body: mapDevice,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: true,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -48,6 +48,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
late RRTProceduresResponseModel selectedRRTProcedure;
bool patientHasAdvanceERBalance = false;
bool isERBookAppointment = false;
late EROnlineCheckInPaymentDetailsResponse erOnlineCheckInPaymentDetailsResponse;
BottomSheetType bottomSheetType = BottomSheetType.FIXED;
@ -69,6 +70,11 @@ class EmergencyServicesViewModel extends ChangeNotifier {
get isGMSAvailable => appState.isGMSAvailable;
void setIsERBookAppointment(bool value) {
isERBookAppointment = value;
notifyListeners();
}
Future<void> getRRTProcedures({Function(dynamic)? onSuccess, Function(String)? onError}) async {
RRTProceduresList.clear();
notifyListeners();
@ -288,6 +294,7 @@ class EmergencyServicesViewModel extends ChangeNotifier {
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) {
patientHasAdvanceERBalance = false;
isERBookAppointment = true;
if (onSuccess != null) {
onSuccess(failure.message);
}
@ -296,8 +303,10 @@ class EmergencyServicesViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
patientHasAdvanceERBalance = false;
isERBookAppointment = true;
} else if (apiResponse.messageStatus == 1) {
patientHasAdvanceERBalance = apiResponse.data;
isERBookAppointment = !patientHasAdvanceERBalance;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@ -328,4 +337,101 @@ class EmergencyServicesViewModel extends ChangeNotifier {
},
);
}
Future<void> ER_CreateAdvancePayment({required String paymentMethodName, required String paymentReference, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await emergencyServicesRepo.ER_CreateAdvancePayment(
projectID: selectedHospital!.iD,
authUser: appState.getAuthenticatedUser()!,
paymentAmount: erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!,
paymentMethodName: paymentMethodName,
paymentReference: paymentReference);
result.fold(
(failure) {
if (onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
} else if (apiResponse.messageStatus == 1) {
// erOnlineCheckInPaymentDetailsResponse = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse.data);
}
}
},
);
}
Future<void> addAdvanceNumberRequest(
{required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await emergencyServicesRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> getProjectIDFromNFC({required String nfcCode, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await emergencyServicesRepo.getProjectIDFromNFC(nfcCode: nfcCode);
result.fold(
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) {
if (onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
if (onError != null) {
onError(apiResponse.errorMessage!);
}
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse.data);
}
}
},
);
}
Future<void> autoGenerateInvoiceERClinic({required int projectID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await emergencyServicesRepo.autoGenerateInvoiceERClinic(projectID: projectID);
result.fold(
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) {
if (onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
if (onError != null) {
onError(apiResponse.data["InvoiceResponse"]["Message"]);
}
} else if (apiResponse.messageStatus == 1) {
patientHasAdvanceERBalance = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse.data);
}
}
},
);
}
}

@ -545,8 +545,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
}
startApplePay() async {
showCommonBottomSheet(context,
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
LoaderBottomSheet.showLoader();
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
@ -625,7 +624,6 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
);
},
onSucceeded: (successResult) async {
Navigator.of(context).pop();
log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus();

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
@ -7,20 +8,31 @@ 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/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_select_checkin_bottom_sheet.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.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';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart';
import '../call_ambulance/widgets/HospitalBottomSheetBody.dart';
class ErOnlineCheckinHome extends StatelessWidget {
const ErOnlineCheckinHome({super.key});
ErOnlineCheckinHome({super.key});
late EmergencyServicesViewModel emergencyServicesViewModel;
bool _supportsNFC = false;
@override
Widget build(BuildContext context) {
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
FlutterNfcKit.nfcAvailability.then((value) {
_supportsNFC = (value == NFCAvailability.available);
});
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
@ -56,23 +68,72 @@ class ErOnlineCheckinHome extends StatelessWidget {
),
),
CustomButton(
text: "Book Appointment".needTranslation,
text: emergencyServicesViewModel.patientHasAdvanceERBalance ? LocaleKeys.checkinOption.tr() : LocaleKeys.bookAppo.tr(),
onPressed: () async {
LoaderBottomSheet.showLoader(loadingText: "Fetching hospitals list...".needTranslation);
await context.read<EmergencyServicesViewModel>().getProjects();
LoaderBottomSheet.hideLoader();
//Project Selection Dropdown
showHospitalBottomSheet(context);
if (emergencyServicesViewModel.patientHasAdvanceERBalance) {
Future.delayed(const Duration(milliseconds: 500), () {
showNfcReader(context, onNcfScan: (String nfcId) {
Future.delayed(const Duration(milliseconds: 100), () async {
print(nfcId);
LoaderBottomSheet.showLoader(loadingText: "Processing check-in...".needTranslation);
await emergencyServicesViewModel.getProjectIDFromNFC(
nfcCode: nfcId,
onSuccess: (value) async {
await emergencyServicesViewModel.autoGenerateInvoiceERClinic(
projectID: value,
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(context,
title: LocaleKeys.onlineCheckIn.tr(),
child: Utils.getSuccessWidget(loadingText: "Your ER Online Check-In has been successfully done. Please proceed to the waiting area.".needTranslation),
callBackFunc: () {
Navigator.pushAndRemoveUntil(
context,
CustomPageRoute(
page: LandingNavigation(),
),
(r) => false);
}, isFullScreen: false);
},
onError: (errMessage) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Unexpected error occurred during check-in. Please contact support.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onError: (err) {});
});
}, onCancel: () {});
});
// showCommonBottomSheetWithoutHeight(context,
// title: LocaleKeys.onlineCheckIn.tr(),
// child: ErOnlineCheckinSelectCheckinBottomSheet(
// projectID: 15,
// ),
// callBackFunc: () {},
// isFullScreen: false);
} else {
LoaderBottomSheet.showLoader(loadingText: "Fetching hospitals list...".needTranslation);
await context.read<EmergencyServicesViewModel>().getProjects();
LoaderBottomSheet.hideLoader();
//Project Selection Dropdown
showHospitalBottomSheet(context);
}
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor,
backgroundColor: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppColors.alertColor : AppColors.primaryRedColor,
borderColor: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppColors.alertColor : AppColors.primaryRedColor,
textColor: AppColors.whiteColor,
fontSize: 16.f,
fontWeight: FontWeight.w500,
borderRadius: 10.r,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50.h,
icon: AppAssets.bookAppoBottom,
icon: emergencyServicesViewModel.patientHasAdvanceERBalance ? AppAssets.appointment_checkin_icon : AppAssets.bookAppoBottom,
iconColor: AppColors.whiteColor,
iconSize: 18.h,
).paddingSymmetrical(24.h, 24.h),

@ -1,23 +1,29 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
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/cache_consts.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/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/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/insurance/insurance_home_page.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';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.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:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
@ -51,14 +57,14 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
void initState() {
scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel();
payfortViewModel.getTamaraInstallmentsDetails().then((val) {
if (emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! >= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! <= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
setState(() {
isShowTamara = true;
});
}
});
// payfortViewModel.getTamaraInstallmentsDetails().then((val) {
// if (emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! >= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.minLimit!.amount! &&
// emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax! <= payfortViewModel.getTamaraInstallmentsDetailsResponseModel!.maxLimit!.amount!) {
// setState(() {
// isShowTamara = true;
// });
// }
// });
});
super.initState();
}
@ -112,7 +118,7 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "MADA";
// openPaymentURL("mada");
openPaymentURL("mada");
}),
SizedBox(height: 16.h),
Container(
@ -154,7 +160,7 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
// openPaymentURL("visa");
openPaymentURL("visa");
}),
SizedBox(height: 16.h),
isShowTamara
@ -191,7 +197,7 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "TAMARA";
// openPaymentURL("tamara");
openPaymentURL("tamara");
})
: SizedBox.shrink(),
],
@ -282,13 +288,12 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() {
// payfortVM.setIsApplePayConfigurationLoading(true);
if (Utils.havePrivilege(103)) {
// startApplePay();
} else {
// openPaymentURL("ApplePay");
}
})
startApplePay();
} else {
openPaymentURL("ApplePay");
}
})
: SizedBox(height: 12.h),
SizedBox(height: 12.h),
],
@ -299,4 +304,207 @@ class _ErOnlineCheckinPaymentPageState extends State<ErOnlineCheckinPaymentPage>
),
);
}
openPaymentURL(String paymentMethod) {
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
transID = Utils.getAdvancePaymentTransID(
emergencyServicesViewModel.selectedHospital!.iD,
appState.getAuthenticatedUser()!.patientId!,
);
//TODO: Need to pass dynamic params to the payment request instead of static values
browser?.openPaymentBrowser(
emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!,
"ER Online Check-In Payment",
transID,
emergencyServicesViewModel.selectedHospital!.iD.toString(),
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
selectedPaymentMethod,
appState.getAuthenticatedUser()!.patientType.toString(),
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
appState.getAuthenticatedUser()!.patientId.toString(),
appState.getAuthenticatedUser()!,
browser!,
false,
"3",
"",
context,
null,
0,
10,
0,
"3");
}
startApplePay() async {
// showCommonBottomSheet(context,
// child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
LoaderBottomSheet.showLoader();
transID = Utils.getAdvancePaymentTransID(
emergencyServicesViewModel.selectedHospital!.iD,
appState.getAuthenticatedUser()!.patientId!,
);
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.erOnlineCheckIn.getIdFromServiceEnum(), projectId: emergencyServicesViewModel.selectedHospital!.iD);
applePayInsertRequest.clientRequestID = transID;
applePayInsertRequest.clinicID = 10;
applePayInsertRequest.currency = appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
applePayInsertRequest.customerEmail = "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com";
applePayInsertRequest.customerID = appState.getAuthenticatedUser()!.patientId.toString();
applePayInsertRequest.customerName = "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}";
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
applePayInsertRequest.doctorID = 0;
applePayInsertRequest.projectID = emergencyServicesViewModel.selectedHospital!.iD.toString();
applePayInsertRequest.serviceID = ServiceTypeEnum.erOnlineCheckIn.getIdFromServiceEnum().toString();
applePayInsertRequest.channelID = 3;
applePayInsertRequest.patientID = appState.getAuthenticatedUser()!.patientId.toString();
applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
applePayInsertRequest.appointmentDate = null;
applePayInsertRequest.appointmentNo = 0;
applePayInsertRequest.orderDescription = "ER Online Check-In Payment";
applePayInsertRequest.liveServiceID = "0";
applePayInsertRequest.latitude = "0.0";
applePayInsertRequest.longitude = "0.0";
applePayInsertRequest.amount = emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!.toString();
applePayInsertRequest.isSchedule = "0";
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
applePayInsertRequest.userName = appState.getAuthenticatedUser()!.patientId;
applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
applePayInsertRequest.paymentOption = "ApplePay";
applePayInsertRequest.isMobSDK = true;
applePayInsertRequest.merchantReference = transID;
applePayInsertRequest.merchantIdentifier = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
applePayInsertRequest.commandType = "PURCHASE";
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
applePayInsertRequest.returnURL = "";
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
payfortViewModel.paymentWithApplePay(
customerName: "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}",
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
customerEmail: "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
orderDescription: "Appointment Payment",
orderAmount: double.parse(emergencyServicesViewModel.erOnlineCheckInPaymentDetailsResponse.patientShareWithTax!.toString()),
merchantReference: transID,
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
Navigator.of(context).pop();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
onSucceeded: (successResult) async {
log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus();
},
);
});
}
void checkPaymentStatus() async {
LoaderBottomSheet.showLoader(loadingText: "Checking payment status, Please wait...".needTranslation);
await payfortViewModel.checkPaymentStatus(
transactionID: transID,
onSuccess: (apiResponse) async {
print(apiResponse.data);
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
if (emergencyServicesViewModel.isERBookAppointment) {
await emergencyServicesViewModel.ER_CreateAdvancePayment(
paymentMethodName: selectedPaymentMethod,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
onSuccess: (value) async {
await emergencyServicesViewModel.addAdvanceNumberRequest(
advanceNumber: value,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
appointmentNo: "0",
onSuccess: (val) {
LoaderBottomSheet.hideLoader();
if (emergencyServicesViewModel.isERBookAppointment) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getSuccessWidget(loadingText: "Your appointment has been booked successfully. Please perform Check-In once you arrive at the hospital.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
} else {}
});
});
} else {}
} else {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
});
}
onBrowserLoadStart(String url) {
print("onBrowserLoadStart");
print(url);
if (selectedPaymentMethod == "tamara") {
if (Platform.isAndroid) {
Uri uri = new Uri.dataFromString(url);
tamaraPaymentStatus = uri.queryParameters['status']!;
tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
} else {
Uri uri = new Uri.dataFromString(url);
tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
tamaraOrderID = uri.queryParameters['orderId']!;
}
}
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.successURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = true;
return;
}
});
// }
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.errorURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = false;
return;
}
});
// }
}
onBrowserExit(bool isPaymentMade) async {
checkPaymentStatus();
}
}

@ -0,0 +1,169 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.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/common_models/privilege/ProjectDetailListModel.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/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/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/appointments/my_appointments_page.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/nfc/nfc_reader_sheet.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
class ErOnlineCheckinSelectCheckinBottomSheet extends StatelessWidget {
ErOnlineCheckinSelectCheckinBottomSheet({super.key, required this.projectID});
bool _supportsNFC = false;
int projectID = 0;
late LocationUtils locationUtils;
late AppState appState;
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
FlutterNfcKit.nfcAvailability.then((value) {
_supportsNFC = (value == NFCAvailability.available);
});
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
checkInOptionCard(
AppAssets.checkin_location_icon,
"Live Location".needTranslation,
"Verify your location to be at hospital to check in".needTranslation,
).onPress(() {
// locationUtils = LocationUtils(
// isShowConfirmDialog: false,
// navigationService: myAppointmentsViewModel.navigationService,
// appState: myAppointmentsViewModel.appState,
// );
locationUtils.getCurrentLocation(onSuccess: (value) {
projectDetailListModel = Utils.getProjectDetailObj(appState, projectID);
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
print(dist);
if (dist <= projectDetailListModel.geofenceRadius!) {
sendCheckInRequest(projectDetailListModel.checkInQrCode!, context);
} else {
showCommonBottomSheetWithoutHeight(context,
title: "Error".needTranslation,
child: Utils.getErrorWidget(loadingText: "Please ensure you're within the hospital location to perform online check-in.".needTranslation), callBackFunc: () {
Navigator.of(context).pop();
}, isFullScreen: false);
}
});
}),
SizedBox(height: 16.h),
checkInOptionCard(
AppAssets.checkin_nfc_icon,
"NFC (Near Field Communication)".needTranslation,
"Scan your phone via NFC board to check in".needTranslation,
).onPress(() {
Future.delayed(const Duration(milliseconds: 500), () {
showNfcReader(context, onNcfScan: (String nfcId) {
Future.delayed(const Duration(milliseconds: 100), () {
sendCheckInRequest(nfcId, context);
});
}, onCancel: () {});
});
}),
SizedBox(height: 16.h),
checkInOptionCard(
AppAssets.checkin_qr_icon,
"QR Code".needTranslation,
"Scan QR code with your camera to check in".needTranslation,
).onPress(() async {
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
if (onlineCheckInQRCode != "") {
sendCheckInRequest(onlineCheckInQRCode, context);
} else {}
}),
],
);
}
Widget checkInOptionCard(String icon, String title, String subTitle) {
return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.h,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.buildSvgWithAssets(icon: icon, width: 40.h, height: 40.h, fit: BoxFit.fill),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title.toText16(isBold: true, color: AppColors.textColor),
subTitle.toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor),
],
),
),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small,
iconColor: AppColors.blackColor,
width: 18.h,
height: 13.h,
fit: BoxFit.contain,
),
),
],
),
],
).paddingAll(16.h),
);
}
void sendCheckInRequest(String scannedCode, BuildContext context) async {
showCommonBottomSheet(context,
child: Utils.getLoadingWidget(), callBackFunc: (str) {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
// await myAppointmentsViewModel.sendCheckInNfcRequest(
// patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel,
// scannedCode: scannedCode,
// checkInType: 2,
// onSuccess: (apiResponse) {
// Navigator.of(context).pop();
// showCommonBottomSheetWithoutHeight(context, title: "Success".needTranslation, child: Utils.getSuccessWidget(loadingText: LocaleKeys.success.tr()), callBackFunc: () {
// Navigator.of(context).pop();
// Navigator.pushAndRemoveUntil(
// context,
// CustomPageRoute(
// page: LandingNavigation(),
// ),
// (r) => false);
// Navigator.of(context).push(
// CustomPageRoute(page: MyAppointmentsPage()),
// );
// }, isFullScreen: false);
// },
// onError: (error) {
// Navigator.of(context).pop();
// showCommonBottomSheetWithoutHeight(context, title: "Error".needTranslation, child: Utils.getErrorWidget(loadingText: error), callBackFunc: () {
// Navigator.of(context).pop();
// }, isFullScreen: false);
// },
// );
}
}

@ -16,6 +16,7 @@ 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/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart';
@ -28,6 +29,7 @@ import 'package:hmg_patient_app_new/presentation/appointments/widgets/appointmen
import 'package:hmg_patient_app_new/presentation/authentication/quick_login.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/book_appointment_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_pending_request_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart';
@ -64,6 +66,7 @@ class _LandingPageState extends State<LandingPage> {
late InsuranceViewModel insuranceViewModel;
late ImmediateLiveCareViewModel immediateLiveCareViewModel;
late BookAppointmentsViewModel bookAppointmentsViewModel;
late EmergencyServicesViewModel emergencyServicesViewModel;
final SwiperController _controller = SwiperController();
@ -93,6 +96,7 @@ class _LandingPageState extends State<LandingPage> {
insuranceViewModel.initInsuranceProvider();
immediateLiveCareViewModel.initImmediateLiveCare();
immediateLiveCareViewModel.getPatientLiveCareHistory();
emergencyServicesViewModel.checkPatientERAdvanceBalance();
}
});
super.initState();
@ -105,6 +109,7 @@ class _LandingPageState extends State<LandingPage> {
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false);
insuranceViewModel = Provider.of<InsuranceViewModel>(context, listen: false);
immediateLiveCareViewModel = Provider.of<ImmediateLiveCareViewModel>(context, listen: false);
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
appState = getIt.get<AppState>();
return PopScope(
canPop: false,
@ -296,6 +301,8 @@ class _LandingPageState extends State<LandingPage> {
).paddingSymmetrical(24.h, 0.h);
},
),
// Consumer for LiveCare pending request
Consumer<ImmediateLiveCareViewModel>(
builder: (context, immediateLiveCareVM, child) {
return immediateLiveCareVM.patientHasPendingLiveCareRequest
@ -353,6 +360,66 @@ class _LandingPageState extends State<LandingPage> {
: SizedBox(height: 12.h);
},
),
// Consumer for ER Online Check-In pending request
Consumer<EmergencyServicesViewModel>(
builder: (context, emergencyServicesVM, child) {
return emergencyServicesVM.patientHasAdvanceERBalance
? Column(
children: [
SizedBox(height: 4.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 20.r,
hasShadow: true,
side: BorderSide(color: AppColors.primaryRedColor, width: 3.h),
),
width: double.infinity,
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AppCustomChipWidget(
labelText: "ER Online Check-In Request",
backgroundColor: AppColors.primaryRedColor.withValues(alpha: 0.10),
textColor: AppColors.primaryRedColor,
),
Utils.buildSvgWithAssets(icon: AppAssets.appointment_checkin_icon, width: 24.h, height: 24.h, iconColor: AppColors.primaryRedColor),
],
),
SizedBox(height: 8.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"You have ER Online Check-In Request".needTranslation.toText12(isBold: true),
Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon_small,
iconColor: AppColors.blackColor,
width: 20.h,
height: 15.h,
fit: BoxFit.contain,
),
],
),
],
),
),
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: ErOnlineCheckinHome()));
// context.read<EmergencyServicesViewModel>().navigateToEROnlineCheckIn();
}),
SizedBox(height: 12.h),
],
)
: SizedBox(height: 12.h);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [

Loading…
Cancel
Save