diff --git a/assets/images/svg/edit_icon.svg b/assets/images/svg/edit_icon.svg
new file mode 100644
index 0000000..3f82a2e
--- /dev/null
+++ b/assets/images/svg/edit_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart
index 446bbc2..016e42d 100644
--- a/lib/core/app_assets.dart
+++ b/lib/core/app_assets.dart
@@ -146,6 +146,7 @@ class AppAssets {
static const String ic_low_result = '$svgBasePath/low_result.svg';
static const String ic_critical_low_result = '$svgBasePath/critical_low_result.svg';
static const String livecare_online_icon = '$svgBasePath/livecare_online_icon.svg';
+ static const String edit_icon = '$svgBasePath/edit_icon.svg';
//bottom navigation//
static const String homeBottom = '$svgBasePath/home_bottom.svg';
diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart
index 4568a15..f59d657 100644
--- a/lib/core/utils/push_notification_handler.dart
+++ b/lib/core/utils/push_notification_handler.dart
@@ -8,11 +8,14 @@ import 'package:firebase_messaging/firebase_messaging.dart' as fir;
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_ios_voip_kit_karmm/call_state_type.dart';
+import 'package:flutter_ios_voip_kit_karmm/flutter_ios_voip_kit.dart';
// import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:hmg_patient_app_new/core/utils/local_notifications.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:permission_handler/permission_handler.dart';
import '../cache_consts.dart';
@@ -139,7 +142,7 @@ class PushNotificationHandler {
// late HmsApiAvailability hmsApiAvailability;
- // final voIPKit = FlutterIOSVoIPKit.instance;
+ final voIPKit = FlutterIOSVoIPKit.instance;
late Timer timeOutTimer;
bool isTalking = false;
@@ -188,55 +191,56 @@ class PushNotificationHandler {
this.context = context;
if (Platform.isIOS) {
- // voIPKit.getVoIPToken().then((value) {
- // print("APNS VOIP KIT TOKEN: $value");
- // AppSharedPreferences().setString(APNS_TOKEN, value!);
- // });
- //
- // voIPKit.onDidUpdatePushToken = (String token) {
- // print('🎈 example: onDidUpdatePushToken: $token');
- // };
- //
- // voIPKit.onDidReceiveIncomingPush = (
- // Map payload,
- // ) async {
- // print('🎈 example: onDidReceiveIncomingPush $payload');
- // _timeOut();
- // };
- //
- // voIPKit.onDidRejectIncomingCall = (
- // String uuid,
- // String callerId,
- // ) async {
- // try {
- // print('🎈 example: onDidRejectIncomingCall $uuid - $callerId');
- // timeOutTimer.cancel();
- // } catch (err) {}
- // };
- //
- // voIPKit.onDidAcceptIncomingCall = (
- // String uuid,
- // String callerId,
- // ) async {
- // print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
- // await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
- // await voIPKit.callConnected();
- // await Future.delayed(Duration(seconds: 1));
- //
- // Navigator.pushNamed(
- // locator().navigatorKey.currentContext!,
- // "zoom_call_page",
- // arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false),
- // );
- //
- // await voIPKit.endCall();
- //
- // // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN,
- // // arguments: VideoArgus(
- // // reservationId: int.parse(callerId), token: null, isVideo: true));
- //
- // timeOutTimer.cancel();
- // };
+ voIPKit.getVoIPToken().then((value) {
+ print("🎈 APNS VOIP KIT TOKEN: $value");
+ Utils.saveStringFromPrefs(CacheConst.voipToken, value ?? "");
+ // AppSharedPreferences().setString(APNS_TOKEN, value!);
+ });
+
+ voIPKit.onDidUpdatePushToken = (String token) {
+ print('🎈 example: onDidUpdatePushToken: $token');
+ };
+
+ voIPKit.onDidReceiveIncomingPush = (
+ Map payload,
+ ) async {
+ print('🎈 example: onDidReceiveIncomingPush $payload');
+ // _timeOut();
+ };
+
+ voIPKit.onDidRejectIncomingCall = (
+ String uuid,
+ String callerId,
+ ) async {
+ try {
+ print('🎈 example: onDidRejectIncomingCall $uuid - $callerId');
+ timeOutTimer.cancel();
+ } catch (err) {}
+ };
+
+ voIPKit.onDidAcceptIncomingCall = (
+ String uuid,
+ String callerId,
+ ) async {
+ print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
+ await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
+ await voIPKit.callConnected();
+ await Future.delayed(Duration(seconds: 1));
+
+ // Navigator.pushNamed(
+ // locator().navigatorKey.currentContext!,
+ // "zoom_call_page",
+ // arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false),
+ // );
+
+ await voIPKit.endCall();
+
+ // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN,
+ // arguments: VideoArgus(
+ // reservationId: int.parse(callerId), token: null, isVideo: true));
+
+ // timeOutTimer.cancel();
+ };
}
if (Platform.isAndroid) {
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index efa01d0..8830b78 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -658,7 +658,6 @@ class Utils {
static Widget getPaymentAmountWithSymbol(Widget paymentAmountWidget, Color iconColor, double iconSize, {bool isSaudiCurrency = true, bool isExpanded = true}) {
return Row(
mainAxisAlignment: isExpanded ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.end,
children: [
appState.isArabic()
? Container()
diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart
index 18b5330..0a137ce 100644
--- a/lib/features/book_appointments/book_appointments_repo.dart
+++ b/lib/features/book_appointments/book_appointments_repo.dart
@@ -1,3 +1,5 @@
+import 'dart:io';
+
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
@@ -9,6 +11,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/resp_model
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.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/services/logger_service.dart';
@@ -69,6 +72,13 @@ abstract class BookAppointmentsRepo {
Function(String)? onError});
Future>>> getLiveCareImmediateClinicsList(int age, int genderID, {Function(dynamic)? onSuccess, Function(String)? onError});
+
+ Future>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
+ {Function(dynamic)? onSuccess, Function(String)? onError});
+
+ Future>> addNewCallRequestForImmediateLiveCare(
+ int age, int gender, int serviceID, String clientRequestID, int callTypeID, bool isPharma, String deviceToken, String voipToken,
+ {Function(dynamic)? onSuccess, Function(String)? onError});
}
class BookAppointmentsRepoImp implements BookAppointmentsRepo {
@@ -703,4 +713,101 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future>> getLiveCareImmediateAppointmentFees(int age, int genderID, int serviceID,
+ {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ Map mapDevice = {
+ "Age": age,
+ "Gender": genderID,
+ "ServiceID": serviceID,
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_ER_APPOINTMENT_FEES,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ onError!(error);
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final respObject = response['GetERAppointmentFeesList'];
+
+ final liveCareFeesObj = LiveCareImmediateAppointmentFeesList.fromJson(respObject);
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: liveCareFeesObj,
+ );
+ } 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> addNewCallRequestForImmediateLiveCare(
+ int age, int gender, int serviceID, String clientRequestID, int callTypeID, bool isPharma, String deviceToken, String voipToken,
+ {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
+ Map mapDevice = {
+ "IsPharmacy": isPharma,
+ "ErServiceID": serviceID,
+ "ClientRequestID": clientRequestID,
+ "DeviceToken": deviceToken,
+ "VoipToken": voipToken,
+ "IsFlutter": true,
+ "DeviceType": Platform.isIOS ? 'iOS' : 'Android',
+ "Age": age,
+ "Gender": gender,
+ "IsVoip": Platform.isIOS ? true : false,
+ "CallTypeID": callTypeID
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ADD_NEW_CALL_FOR_PATIENT_ER,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ onError!(error);
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ // final respObject = response['GetERAppointmentFeesList'];
+
+ // final liveCareFeesObj = LiveCareImmediateAppointmentFeesList.fromJson(respObject);
+
+ apiResponse = GenericApiModel(
+ 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()));
+ }
+ }
}
diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart
index ab4ca56..120aa3b 100644
--- a/lib/features/book_appointments/book_appointments_view_model.dart
+++ b/lib/features/book_appointments/book_appointments_view_model.dart
@@ -16,6 +16,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/resp_model
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_immediate_fees_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.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';
@@ -27,8 +28,6 @@ import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_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';
-import 'package:location/location.dart' show Location;
import 'models/resp_models/get_livecare_clinics_response_model.dart';
@@ -64,7 +63,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
//Immediate LiveCare
List immediateLiveCareClinicsList = [];
bool isImmediateLiveCareClinicsLoading = false;
- int liveCareSelectedCallType = 1;
+ int liveCareSelectedCallType = 0; // 1- Video, 2- Audio, 3- Phone
+ late GetLiveCareClinicListResponseModel immediateLiveCareSelectedClinic;
+ late LiveCareImmediateAppointmentFeesList liveCareImmediateAppointmentFeesList;
late DoctorsProfileResponseModel doctorsProfileResponseModel;
@@ -125,6 +126,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
immediateLiveCareClinicsList.clear();
isImmediateLiveCareClinicsLoading = true;
+ liveCareSelectedCallType = 0;
// getLocation();
notifyListeners();
}
@@ -191,12 +193,16 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
-
setLiveCareSelectedCallType(int value) {
liveCareSelectedCallType = value;
notifyListeners();
}
+ setImmediateLiveCareSelectedClinic(GetLiveCareClinicListResponseModel clinic) {
+ immediateLiveCareSelectedClinic = clinic;
+ notifyListeners();
+ }
+
/// this function will decide which clinic api to be called
/// either api for region flow or the select clinic api
Future getClinics() async {
@@ -798,4 +804,49 @@ class BookAppointmentsViewModel extends ChangeNotifier {
},
);
}
+
+ Future getLiveCareImmediateAppointmentFees({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result =
+ await bookAppointmentsRepo.getLiveCareImmediateAppointmentFees(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!, immediateLiveCareSelectedClinic.serviceID!);
+
+ result.fold(
+ (failure) async {
+ onError!(failure.message);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage ?? "Unknown error occurred");
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ liveCareImmediateAppointmentFeesList = apiResponse.data!;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future addNewCallRequestForImmediateLiveCare(String transID, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await bookAppointmentsRepo.addNewCallRequestForImmediateLiveCare(_appState.getAuthenticatedUser()!.age!, _appState.getAuthenticatedUser()!.gender!,
+ immediateLiveCareSelectedClinic.serviceID!, transID, liveCareSelectedCallType, false, _appState.deviceToken, await Utils.getStringFromPrefs(CacheConst.voipToken));
+
+ result.fold(
+ (failure) async {
+ onError!(failure.message);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage ?? "Unknown error occurred");
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/features/book_appointments/models/resp_models/get_livecare_immediate_fees_response_model.dart b/lib/features/book_appointments/models/resp_models/get_livecare_immediate_fees_response_model.dart
new file mode 100644
index 0000000..9a5861e
--- /dev/null
+++ b/lib/features/book_appointments/models/resp_models/get_livecare_immediate_fees_response_model.dart
@@ -0,0 +1,37 @@
+class LiveCareImmediateAppointmentFeesList {
+ String? amount;
+ String? companyName;
+ bool? isInsured;
+ bool? isShowInsuranceUpdateModule;
+ bool? isCash;
+ bool? isEligible;
+ String? tax;
+ String? total;
+ String? currency;
+
+ LiveCareImmediateAppointmentFeesList({this.amount, this.companyName, this.isInsured, this.isShowInsuranceUpdateModule, this.tax, this.total, this.currency});
+
+ LiveCareImmediateAppointmentFeesList.fromJson(Map json) {
+ amount = json['Amount'];
+ companyName = json['CompanyName'];
+ isInsured = json['IsInsured'];
+ isCash = json['IsCash'];
+ isEligible = json['IsEligible'];
+ isShowInsuranceUpdateModule = json['IsShowInsuranceUpdateModule'];
+ tax = json['Tax'];
+ total = json['Total'];
+ currency = json['currency'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['Amount'] = this.amount;
+ data['CompanyName'] = this.companyName;
+ data['IsInsured'] = this.isInsured;
+ data['IsShowInsuranceUpdateModule'] = this.isShowInsuranceUpdateModule;
+ data['Tax'] = this.tax;
+ data['Total'] = this.total;
+ data['currency'] = this.currency;
+ return data;
+ }
+}
diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart
index 6976188..54353a4 100644
--- a/lib/presentation/appointments/appointment_details_page.dart
+++ b/lib/presentation/appointments/appointment_details_page.dart
@@ -419,7 +419,7 @@ class _AppointmentDetailsPageState extends State {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- "Total amount to pay".needTranslation.toText18(isBold: true),
+ "Amount before tax".needTranslation.toText18(isBold: true),
Utils.getPaymentAmountWithSymbol(widget.patientAppointmentHistoryResponseModel.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart
index 9d6b557..7334369 100644
--- a/lib/presentation/appointments/appointment_payment_page.dart
+++ b/lib/presentation/appointments/appointment_payment_page.dart
@@ -257,7 +257,7 @@ class _AppointmentPaymentPageState extends State {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- "Total amount to pay".needTranslation.toText14(isBold: true),
+ "Amount before tax".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
@@ -293,7 +293,7 @@ class _AppointmentPaymentPageState extends State {
if (Utils.havePrivilege(103)) {
startApplePay();
} else {
- openPaymentURL(selectedPaymentMethod);
+ openPaymentURL("ApplePay");
}
})
: SizedBox(height: 12.h),
diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart
new file mode 100644
index 0000000..76f6ad1
--- /dev/null
+++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart
@@ -0,0 +1,301 @@
+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/dependencies.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/book_appointments/book_appointments_view_model.dart';
+import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
+import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart';
+import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/select_livecare_call_type.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/chip/app_custom_chip_widget.dart';
+import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.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:smooth_corner/smooth_corner.dart';
+
+class ImmediateLiveCarePaymentDetails extends StatelessWidget {
+ ImmediateLiveCarePaymentDetails({super.key});
+
+ late BookAppointmentsViewModel bookAppointmentsViewModel;
+ late AppState appState;
+
+ @override
+ Widget build(BuildContext context) {
+ bookAppointmentsViewModel = Provider.of(context, listen: false);
+ appState = getIt.get();
+ return Scaffold(
+ backgroundColor: AppColors.scaffoldBgColor,
+ body: Column(
+ children: [
+ Expanded(
+ child: CollapsingListView(
+ title: "Review LiveCare Request".needTranslation,
+ child: SingleChildScrollView(
+ padding: EdgeInsets.symmetric(horizontal: 24.h),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 24.h),
+ LocaleKeys.patientInfo.tr(context: context).toText16(isBold: true),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Row(
+ children: [
+ Image.asset(
+ appState.getAuthenticatedUser()?.gender == 1 ? AppAssets.male_img : AppAssets.femaleImg,
+ width: 52.h,
+ height: 52.h,
+ ),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true),
+ SizedBox(height: 8.h),
+ AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(height: 24.h),
+ "Clinic Information".needTranslation.toText16(isBold: true),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.generic_clinic_icon, width: 32.h, height: 32.h, fit: BoxFit.contain),
+ SizedBox(width: 8.h),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (appState.isArabic() ? bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceNameN : bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceName)!
+ .toText16(isBold: true),
+ // SizedBox(height: 8.h),
+ // AppCustomChipWidget(labelText: "${appState.getAuthenticatedUser()!.age} Years Old"),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(height: 24.h),
+ "Selected LiveCare Type".needTranslation.toText16(isBold: true),
+ SizedBox(height: 16.h),
+ Consumer(builder: (context, bookAppointmentsVM, child) {
+ return Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16.h),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Utils.buildSvgWithAssets(icon: AppAssets.livecare_clinic_icon, width: 32.h, height: 32.h, fit: BoxFit.contain),
+ SizedBox(width: 8.h),
+ getLiveCareType(bookAppointmentsViewModel.liveCareSelectedCallType).toText16(isBold: true),
+ ],
+ ),
+ Utils.buildSvgWithAssets(icon: AppAssets.edit_icon, width: 24.h, height: 24.h, fit: BoxFit.contain),
+ ],
+ ),
+ ),
+ ).onPress(() {
+ showCommonBottomSheetWithoutHeight(context, child: SelectLiveCareCallType(bookAppointmentsViewModel: bookAppointmentsViewModel), callBackFunc: () async {
+ debugPrint("Selected Call Type: ${bookAppointmentsViewModel.liveCareSelectedCallType}");
+ }, title: "Select LiveCare call type".needTranslation, isCloseButtonVisible: true, isFullScreen: false);
+ });
+ }),
+ SizedBox(height: 24.h)
+ ],
+ ),
+ ),
+ ),
+ ),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.isCash ?? true)
+ ? Container(
+ height: 50.h,
+ decoration: ShapeDecoration(
+ color: AppColors.secondaryLightRedBorderColor,
+ shape: SmoothRectangleBorder(
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
+ smoothness: 1,
+ ),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
+ CustomButton(
+ text: LocaleKeys.updateInsurance.tr(context: context),
+ onPressed: () {
+ Navigator.of(context).push(
+ CustomPageRoute(
+ page: InsuranceHomePage(),
+ ),
+ );
+ },
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.secondaryLightRedBorderColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 8,
+ padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
+ height: 30.h,
+ ).paddingSymmetrical(24.h, 0.h),
+ ],
+ ),
+ )
+ : const SizedBox(),
+ SizedBox(height: 24.h),
+ "Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 17.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Amount before tax".needTranslation.toText14(isBold: true),
+ Utils.getPaymentAmountWithSymbol(bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.amount!.toText16(isBold: true), AppColors.blackColor, 13,
+ isSaudiCurrency: bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar"),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
+ Utils.getPaymentAmountWithSymbol(
+ bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
+ isSaudiCurrency: bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar"),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 17.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ SizedBox(width: 150.h, child: Utils.getPaymentMethods()),
+ Utils.getPaymentAmountWithSymbol(bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true), AppColors.blackColor, 17,
+ isSaudiCurrency: bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar"),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ CustomButton(
+ text: LocaleKeys.payNow.tr(context: context),
+ onPressed: () async {
+ await askVideoCallPermission().then((val) {
+ if (val) {
+ Navigator.of(context).push(
+ CustomPageRoute(
+ page: ImmediateLiveCarePaymentPage(),
+ ),
+ );
+ } else {
+ showCommonBottomSheetWithoutHeight(
+ title: LocaleKeys.notice.tr(context: context),
+ context,
+ child: Utils.getWarningWidget(
+ loadingText:
+ "LiveCare requires Camera, Microphone & Location permissions to enable virtual consultation between patient & doctor, Please allow these to proceed.".needTranslation,
+ isShowActionButtons: true,
+ onCancelTap: () {
+ Navigator.pop(context);
+ },
+ onConfirmTap: () async {
+ openAppSettings();
+ }),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+ });
+ },
+ backgroundColor: AppColors.infoColor,
+ borderColor: AppColors.infoColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ borderRadius: 12,
+ padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
+ height: 50.h,
+ icon: AppAssets.appointment_pay_icon,
+ iconColor: AppColors.whiteColor,
+ iconSize: 18.h,
+ ).paddingSymmetrical(24.h, 24.h),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Future askVideoCallPermission() async {
+ Map statuses = await [
+ Permission.camera,
+ Permission.microphone,
+ ].request();
+
+ if (statuses[Permission.camera] == PermissionStatus.granted && statuses[Permission.microphone] == PermissionStatus.granted) {
+ // Camera permission granted
+ return true;
+ } else {
+ return false;
+ }
+
+ // if (!(await Permission.camera.request().isGranted) || !(await Permission.microphone.request().isGranted)) {
+ // return false;
+ // }
+ }
+
+ String getLiveCareType(int callType) {
+ switch (callType) {
+ case 1:
+ return "Video Call".needTranslation;
+ case 2:
+ return "Audio Call".needTranslation;
+ case 3:
+ return "Phone Call".needTranslation;
+ default:
+ return "Video Call".needTranslation;
+ }
+ }
+}
diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart
new file mode 100644
index 0000000..d4a108c
--- /dev/null
+++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart
@@ -0,0 +1,510 @@
+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/api_consts.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/date_util.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
+import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.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/features/payfort/payfort_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/presentation/insurance/insurance_home_page.dart';
+import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
+import 'package:hmg_patient_app_new/services/cache_service.dart';
+import 'package:hmg_patient_app_new/theme/colors.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:permission_handler/permission_handler.dart';
+import 'package:provider/provider.dart';
+import 'package:smooth_corner/smooth_corner.dart';
+
+class ImmediateLiveCarePaymentPage extends StatefulWidget {
+ ImmediateLiveCarePaymentPage({super.key});
+
+ @override
+ State createState() => _ImmediateLiveCarePaymentPageState();
+}
+
+class _ImmediateLiveCarePaymentPageState extends State {
+ late PayfortViewModel payfortViewModel;
+ late BookAppointmentsViewModel bookAppointmentsViewModel;
+ late MyAppointmentsViewModel myAppointmentsViewModel;
+ late AppState appState;
+
+ MyInAppBrowser? browser;
+ String selectedPaymentMethod = "";
+
+ String transID = "";
+
+ @override
+ void initState() {
+ scheduleMicrotask(() {
+ payfortViewModel.initPayfortViewModel();
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ appState = getIt.get();
+ myAppointmentsViewModel = Provider.of(context);
+ bookAppointmentsViewModel = Provider.of(context, listen: false);
+ payfortViewModel = Provider.of(context);
+ return Scaffold(
+ backgroundColor: AppColors.bgScaffoldColor,
+ body: Consumer(builder: (context, myAppointmentsVM, child) {
+ return Column(
+ children: [
+ Expanded(
+ child: CollapsingListView(
+ title: "Appointment Payment".needTranslation,
+ child: SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(height: 24.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(AppAssets.mada, width: 72.h, height: 25.h),
+ SizedBox(height: 16.h),
+ "Mada".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Transform.flip(
+ flipX: appState.isArabic() ? true : false,
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "MADA";
+ openPaymentURL("mada");
+ }),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Image.asset(AppAssets.visa, width: 50.h, height: 50.h),
+ SizedBox(width: 8.h),
+ Image.asset(AppAssets.Mastercard, width: 40.h, height: 40.h),
+ ],
+ ),
+ SizedBox(height: 16.h),
+ "Visa or Mastercard".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Transform.flip(
+ flipX: appState.isArabic() ? true : false,
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "VISA";
+ openPaymentURL("visa");
+ }),
+ SizedBox(height: 16.h),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 20.h,
+ hasShadow: false,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Image.asset(AppAssets.tamara_en, width: 72.h, height: 25.h),
+ SizedBox(height: 16.h),
+ "Tamara".needTranslation.toText16(isBold: true),
+ ],
+ ),
+ SizedBox(width: 8.h),
+ const Spacer(),
+ Transform.flip(
+ flipX: appState.isArabic() ? true : false,
+ child: Utils.buildSvgWithAssets(
+ icon: AppAssets.forward_arrow_icon,
+ iconColor: AppColors.blackColor,
+ width: 18.h,
+ height: 13.h,
+ fit: BoxFit.contain,
+ ),
+ ),
+ ],
+ ).paddingSymmetrical(16.h, 16.h),
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ selectedPaymentMethod = "TAMARA";
+ openPaymentURL("tamara");
+ }),
+ ],
+ ),
+ ),
+ ),
+ ),
+ Container(
+ decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
+ color: AppColors.whiteColor,
+ borderRadius: 24.h,
+ hasShadow: false,
+ ),
+ child: Consumer(builder: (context, payfortVM, child) {
+ //TODO: Need to add loading state & animation for Apple Pay Configuration
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ (bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.isCash ?? true)
+ ? Container(
+ height: 50.h,
+ decoration: ShapeDecoration(
+ color: AppColors.secondaryLightRedBorderColor,
+ shape: SmoothRectangleBorder(
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
+ smoothness: 1,
+ ),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
+ CustomButton(
+ text: LocaleKeys.updateInsurance.tr(context: context),
+ onPressed: () {
+ Navigator.of(context).push(
+ CustomPageRoute(
+ page: InsuranceHomePage(),
+ ),
+ );
+ },
+ backgroundColor: AppColors.primaryRedColor,
+ borderColor: AppColors.secondaryLightRedBorderColor,
+ textColor: AppColors.whiteColor,
+ fontSize: 10,
+ fontWeight: FontWeight.w500,
+ borderRadius: 8,
+ padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
+ height: 30.h,
+ ).paddingSymmetrical(24.h, 0.h),
+ ],
+ ),
+ )
+ : const SizedBox(),
+ SizedBox(height: 24.h),
+ "Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 17.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Amount before tax".needTranslation.toText14(isBold: true),
+ Utils.getPaymentAmountWithSymbol(bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.amount!.toString().toText16(isBold: true), AppColors.blackColor, 13,
+ isSaudiCurrency: true),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
+ Utils.getPaymentAmountWithSymbol(
+ bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.tax!.toString().toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
+ isSaudiCurrency: true),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ SizedBox(height: 17.h),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "".needTranslation.toText14(isBold: true),
+ Utils.getPaymentAmountWithSymbol(bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.total!.toString().toText24(isBold: true), AppColors.blackColor, 17,
+ isSaudiCurrency: true),
+ ],
+ ).paddingSymmetrical(24.h, 0.h),
+ Platform.isIOS
+ ? Utils.buildSvgWithAssets(
+ icon: AppAssets.apple_pay_button,
+ width: 200.h,
+ height: 80.h,
+ fit: BoxFit.contain,
+ ).paddingSymmetrical(24.h, 0.h).onPress(() {
+ // payfortVM.setIsApplePayConfigurationLoading(true);
+ if (Utils.havePrivilege(103)) {
+ startApplePay();
+ } else {
+ openPaymentURL("ApplePay");
+ }
+ })
+ : SizedBox(height: 12.h),
+ SizedBox(height: 12.h),
+ ],
+ );
+ }),
+ ),
+ ],
+ );
+ }),
+ );
+ }
+
+ 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 {
+ print("onBrowserExit Called!!!!");
+ if (selectedPaymentMethod == "TAMARA") {
+ // checkTamaraPaymentStatus(transID!, appo);
+ // if (tamaraPaymentStatus != null && tamaraPaymentStatus.toLowerCase() == "approved") {
+ // updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
+ // } else {
+ // updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
+ // }
+ } else {
+ checkPaymentStatus();
+ // checkPaymentStatus(appo);
+ }
+ }
+
+ void checkPaymentStatus() async {
+ LoaderBottomSheet.showLoader(loadingText: "Checking payment status, Please wait...".needTranslation);
+ await payfortViewModel.checkPaymentStatus(
+ transactionID: transID,
+ onSuccess: (apiResponse) async {
+ debugPrint(apiResponse.data.toString());
+ if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
+ await bookAppointmentsViewModel.addNewCallRequestForImmediateLiveCare(transID);
+ LoaderBottomSheet.hideLoader();
+
+ // showCommonBottomSheetWithoutHeight(
+ // context,
+ // child: Utils.getSuccessWidget(loadingText: "Payment Successful!".needTranslation),
+ // callBackFunc: () {
+ // Navigator.of(context).pop();
+ // Navigator.of(context).pop();
+ // },
+ // isFullScreen: false,
+ // isCloseButtonVisible: true,
+ // );
+ } else {
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: "Payment Failed! Please try again.".needTranslation),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ }
+ });
+ }
+
+ openPaymentURL(String paymentMethod) {
+ browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
+ transID = Utils.getAppointmentTransID(
+ bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceID!,
+ ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat ? 15 : 12,
+ DateTime.now().millisecondsSinceEpoch,
+ );
+
+ //TODO: Need to pass dynamic params to the payment request instead of static values
+ browser?.openPaymentBrowser(
+ myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!,
+ "LiveCare Payment",
+ transID,
+ "12",
+ "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,
+ "4",
+ bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceID.toString(),
+ context,
+ myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentDate,
+ myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentNo,
+ myAppointmentsViewModel.patientAppointmentShareResponseModel!.clinicID,
+ myAppointmentsViewModel.patientAppointmentShareResponseModel!.doctorID,
+ "3");
+ }
+
+ startApplePay() async {
+ LoaderBottomSheet.showLoader(loadingText: "Fetching Apple Pay details, Please wait...".needTranslation);
+ transID = Utils.getAppointmentTransID(
+ bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceID!,
+ ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat ? 15 : 12,
+ DateTime.now().millisecondsSinceEpoch,
+ );
+
+ ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
+
+ await payfortViewModel.getPayfortConfigurations(
+ serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum(), projectId: ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat ? 15 : 12, integrationId: 2);
+
+ applePayInsertRequest.clientRequestID = transID;
+ applePayInsertRequest.clinicID = bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceID!;
+
+ 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 = "12";
+ applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
+ applePayInsertRequest.channelID = 3;
+ applePayInsertRequest.patientID = appState.getAuthenticatedUser()!.patientId.toString();
+ applePayInsertRequest.patientTypeID = appState.getAuthenticatedUser()!.patientType;
+ applePayInsertRequest.patientOutSA = appState.getAuthenticatedUser()!.outSa;
+ applePayInsertRequest.appointmentDate = DateUtil.convertDateToString(DateTime.now());
+ applePayInsertRequest.appointmentNo = 0;
+ applePayInsertRequest.orderDescription = "LiveCare Payment";
+ applePayInsertRequest.liveServiceID = bookAppointmentsViewModel.immediateLiveCareSelectedClinic.serviceID!.toString();
+ applePayInsertRequest.latitude = "0.0";
+ applePayInsertRequest.longitude = "0.0";
+ applePayInsertRequest.amount = bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.total.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: "LiveCare Payment",
+ orderAmount: double.parse(bookAppointmentsViewModel.liveCareImmediateAppointmentFeesList.total!),
+ 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()}");
+ LoaderBottomSheet.hideLoader();
+ showCommonBottomSheetWithoutHeight(
+ context,
+ child: Utils.getErrorWidget(loadingText: failureResult.message.toString()),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ },
+ onSucceeded: (successResult) async {
+ LoaderBottomSheet.hideLoader();
+ log("successResult: ${successResult.responseMessage.toString()}");
+ selectedPaymentMethod = successResult.paymentOption ?? "VISA";
+ checkPaymentStatus();
+ },
+ // projectId: appo.projectID,
+ // serviceTypeEnum: ServiceTypeEnum.appointmentPayment,
+ );
+ });
+ }
+}
diff --git a/lib/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart b/lib/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart
index 8ec6e4b..6910113 100644
--- a/lib/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart
+++ b/lib/presentation/book_appointment/livecare/select_immediate_livecare_clinic_page.dart
@@ -12,12 +12,15 @@ import 'package:hmg_patient_app_new/features/book_appointments/book_appointments
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_clinics_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_livecare_immediate_clinics_response_model.dart';
+import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/livecare/widgets/select_livecare_call_type.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/clinic_card.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/livecare_clinic_card.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/common_bottom_sheet.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';
class SelectImmediateLiveCareClinicPage extends StatefulWidget {
@@ -37,6 +40,7 @@ class _SelectImmediateLiveCareClinicPageState extends State {
),
SizedBox(width: 8.h),
Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}".toText16(isBold: true),
SizedBox(height: 8.h),
diff --git a/lib/widgets/loader/bottomsheet_loader.dart b/lib/widgets/loader/bottomsheet_loader.dart
index aa97fdf..41d2b15 100644
--- a/lib/widgets/loader/bottomsheet_loader.dart
+++ b/lib/widgets/loader/bottomsheet_loader.dart
@@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:hmg_patient_app_new/core/api_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/utils.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
@@ -11,7 +10,7 @@ class LoaderBottomSheet {
static final NavigationService _navService = GetIt.I();
static bool _isVisible = false;
- static void showLoader() {
+ static void showLoader({String? loadingText}) {
if (_isVisible) return;
_isVisible = true;
@@ -29,7 +28,7 @@ class LoaderBottomSheet {
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Center(
- child: Utils.getLoadingWidget(),
+ child: Utils.getLoadingWidget(loadingText: loadingText),
),
);
},