Offers And Discounts

offers_discounts
Aamir Muhammad 3 weeks ago
parent 90aaed84ed
commit 558a957101

@ -768,7 +768,7 @@
"viewTerms": "لعرض الشروط والأحكام", "viewTerms": "لعرض الشروط والأحكام",
"wantConnectHmgNetwork": "عزيزي العميل، لا يوجد وصول إلى الإنترنت، هل ترغب في الاتصال بشبكة مجموعة الحبيب الطبية لاستخدام تطبيقنا، تأكد من أنك في نطاق شبكة مجموعة الحبيب الطبية", "wantConnectHmgNetwork": "عزيزي العميل، لا يوجد وصول إلى الإنترنت، هل ترغب في الاتصال بشبكة مجموعة الحبيب الطبية لاستخدام تطبيقنا، تأكد من أنك في نطاق شبكة مجموعة الحبيب الطبية",
"failedToAccessHmgServices": "متصل بشبكة مجموعة الحبيب الطبية،\n\nلكن فشل في الوصول إلى خدمات مجموعة الحبيب الطبية", "failedToAccessHmgServices": "متصل بشبكة مجموعة الحبيب الطبية،\n\nلكن فشل في الوصول إلى خدمات مجموعة الحبيب الطبية",
"offerAndPackages": "عروض وباقات", "offerAndPackages": "العروض و الباقات",
"offerAndPackagesDetails": "تتيح لك هذه الخدمة عرض جميع عروض مجموعة الحبيب الطبية:", "offerAndPackagesDetails": "تتيح لك هذه الخدمة عرض جميع عروض مجموعة الحبيب الطبية:",
"invoiceNo": "رقم الفاتورة", "invoiceNo": "رقم الفاتورة",
"invoiceDate": "تاريخ الفاتورة", "invoiceDate": "تاريخ الفاتورة",
@ -1967,9 +1967,9 @@
"notAvailable": "غير متاح", "notAvailable": "غير متاح",
"hide": "إخفاء", "hide": "إخفاء",
"paymentSuccessful": "تم الدفع بنجاح", "paymentSuccessful": "تم الدفع بنجاح",
"typeAnyOffer": "اكتب أي عرض", "typeAnyOffer": "ابحث عن العروض و الباقات",
"validTill": "صالح حتى", "validTill": "صالح لغاية",
"buyNow": "اشتري الآن", "buyNow": "اشترِ الآن",
"availableAt": "متاح في", "availableAt": "متاح في",
"includedServices": "الخدمات المشمولة", "includedServices": "الخدمات المشمولة",
"off": "خصم", "off": "خصم",
@ -1977,8 +1977,8 @@
"orderLabel": "الطلب", "orderLabel": "الطلب",
"purchased": "تم الشراء", "purchased": "تم الشراء",
"validUntil": "صالح حتى", "validUntil": "صالح حتى",
"viewOfferDetails": "عرض تفاصيل العرض", "viewOfferDetails": "تفاصيل العرض",
"viewOrderDetails": "عرض تفاصيل الطلب", "viewOrderDetails": "تفاصيل الطلب",
"hospitalNA": "المستشفى: غير متوفر", "hospitalNA": "المستشفى: غير متوفر",
"hospitalLabel": "المستشفى", "hospitalLabel": "المستشفى",
"showLess": "عرض أقل", "showLess": "عرض أقل",
@ -2001,10 +2001,12 @@
"errorLoadingQRCode": "خطأ في تحميل رمز الاستجابة السريعة", "errorLoadingQRCode": "خطأ في تحميل رمز الاستجابة السريعة",
"noOfferDetailsAvailable": "لا توجد تفاصيل عرض متاحة", "noOfferDetailsAvailable": "لا توجد تفاصيل عرض متاحة",
"noImagesAvailable": "لا توجد صور متاحة", "noImagesAvailable": "لا توجد صور متاحة",
"checkOutThisAmazingOffer": "تحقق من هذا العرض المذهل!", "checkOutThisAmazingOffer": "تحقق من هذا العرض من مستشفى سلمان الحبيب",
"offerPayment": "دفع العرض", "offerPayment": "دفع العرض",
"unableToCreateOrder": "غير قادر على إنشاء الطلب. معلومات العرض أو المستخدم مفقودة.", "unableToCreateOrder": "غير قادر على إنشاء الطلب. معلومات العرض أو المستخدم مفقودة.",
"failedToCreateOrder": "فشل في إنشاء الطلب. يرجى المحاولة مرة أخرى.", "failedToCreateOrder": "فشل في إنشاء الطلب. يرجى المحاولة مرة أخرى.",
"unableToCompletePayment": "غير قادر على إكمال الدفع. معلومات الطلب مفقودة.", "unableToCompletePayment": "غير قادر على إكمال الدفع. معلومات الطلب مفقودة.",
"paymentConfirmationFailed": "تم تسجيل الدفع لكن التأكيد فشل. يرجى الاتصال بالدعم." "paymentConfirmationFailed": "تم تسجيل الدفع لكن التأكيد فشل. يرجى الاتصال بالدعم.",
"offerAndPackageDetails": "تفاصيل العروض والباقات",
"myOrders": "طلباتي"
} }

@ -1956,7 +1956,53 @@
"weeklyShift": "Weekly Shift", "weeklyShift": "Weekly Shift",
"dayOff": "Off", "dayOff": "Off",
"hide": "Hide", "hide": "Hide",
"paymentSuccessful": "Payment SuccessFul" "paymentSuccessful": "Payment SuccessFul",
"typeAnyOffer": "Type any offer",
"validTill": "Valid till",
"buyNow": "Buy Now",
"availableAt": "Available at",
"includedServices": "Included Services",
"off": "OFF",
"failedToLoadOfferDetails": "Failed to load offer details",
"orderLabel": "Order",
"purchased": "Purchased",
"validUntil": "Valid until",
"viewOfferDetails": "View Offer Details",
"viewOrderDetails": "View Order Details",
"hospitalNA": "Hospital: N/A",
"hospitalLabel": "Hospital",
"showLess": "Show less",
"redeemed": "Redeemed",
"partiallyRedeemed": "Partially Redeemed",
"available": "Available",
"saveQRCode": "Save QR Code",
"voucherNo": "Voucher No",
"expiresOn": "Expires on",
"saveTheQRCode": "Save the QR Code",
"pleaseShowQRCodeInHospital": "Please save it to your device and show it in hospital to proceed.",
"voucherCodeCopied": "Voucher code copied to clipboard",
"qrCodeNotAvailableToShare": "QR Code not available to share",
"failedToShareQRCode": "Failed to share QR Code",
"failedToSaveQRCode": "Failed to save QR Code",
"qrCodeSavedSuccessfully": "QR Code Saved Successfully",
"qrCodeSavedToDevice": "Your QR code has been saved to your device",
"viewOrderHistory": "View Order History",
"qrCodeNotAvailable": "QR Code not available",
"errorLoadingQRCode": "Error loading QR Code",
"noOfferDetailsAvailable": "No offer details available",
"noImagesAvailable": "No images available",
"checkOutThisAmazingOffer": "Checkout this Offer From HMG",
"offerPayment": "Offer Payment",
"unableToCreateOrder": "Unable to create order. Missing offer or user information.",
"failedToCreateOrder": "Failed to create order. Please try again.",
"unableToCompletePayment": "Unable to complete payment. Missing order information.",
"paymentConfirmationFailed": "Payment recorded but confirmation failed. Please contact support.",
"offerAndPackageDetails": "Offers and Package Detail",
"myOrders": "My Orders"
} }

@ -5,7 +5,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts { class ApiConsts {
static const maxSmallScreen = 660; static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT

@ -543,32 +543,6 @@ class _LandingPageState extends State<LandingPage> {
).paddingSymmetrical(24.w, 0.h) ).paddingSymmetrical(24.w, 0.h)
: SizedBox.shrink(), : SizedBox.shrink(),
// Offers And Discounts Carousel - Auto-scrolling from right to left
appState.isAuthenticated && appState.isEnabledOffersAndDiscountsCarousel
? Column(
children: [
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${LocaleKeys.offers.tr(context: context)} & ${LocaleKeys.discount.tr(context: context)}").toText16(isBold: true),
Row(
children: [
LocaleKeys.viewAll.tr(context: context).toText14(color: AppColors.primaryRedColor, isBold: true),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 14.h),
],
),
],
).paddingSymmetrical(24.h, 0.h).onPress(() {
Navigator.of(context).push(CustomPageRoute(page: OffersAndDiscountsPage()));
}),
SizedBox(height: 16.h),
OffersAndDiscountsCarousel().paddingSymmetrical(24.h, 0.h),
SizedBox(height: 18.h),
],
)
: SizedBox.shrink(),
appState.isAuthenticated appState.isAuthenticated
? Column( ? Column(

@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/theme/colors.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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.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:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart' hide Share; import 'package:share_plus/share_plus.dart' hide Share;
@ -288,37 +289,47 @@ class _OfferAndDiscountsFullScreenSwiperPageState extends State<OfferAndDiscount
getIt<AuthenticationViewModel>().onLoginPressed(); getIt<AuthenticationViewModel>().onLoginPressed();
}); });
} else { } else {
// Ensure patient is authenticated (will re-authenticate if needed) // Show loader during authentication
final isAuthenticated = await vm.ensureAuthenticated( LoaderBottomSheet.showLoader(loadingText: LocaleKeys.pleaseWait.tr(context: context));
onSuccess: () {
// Authentication successful, continue // Ensure patient is authenticated (will re-authenticate if needed)
}, final isAuthenticated = await vm.ensureAuthenticated(
onError: (error) { onSuccess: () {
// Show error to user // Authentication successful, continue
showCommonBottomSheetWithoutHeight( },
context, onError: (error) {
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)), // Hide loader on error
callBackFunc: () {}, LoaderBottomSheet.hideLoader();
isFullScreen: false, // Show error to user
isCloseButtonVisible: true, showCommonBottomSheetWithoutHeight(
); context,
}, child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
); callBackFunc: () {},
isFullScreen: false,
if (!isAuthenticated) { isCloseButtonVisible: true,
return; );
} },
// Set the selected offer and navigate to payment page
if (vm.offerDetails != null) {
vm.setSelectedOffer(vm.offerDetails!);
Navigator.of(context).push(
CustomPageRoute(
page: OffersAndDiscountPaymentPage(),
),
); );
if (!isAuthenticated) {
// Hide loader if authentication failed
LoaderBottomSheet.hideLoader();
return;
}
// Hide loader on success
LoaderBottomSheet.hideLoader();
// Set the selected offer and navigate to payment page
if (vm.offerDetails != null) {
vm.setSelectedOffer(vm.offerDetails!);
Navigator.of(context).push(
CustomPageRoute(
page: OffersAndDiscountPaymentPage(),
),
);
}
} }
}
}, },
backgroundColor: AppColors.primaryRedColor, backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedColor,

@ -94,13 +94,16 @@ class _OffersAndDiscountPaymentPageState extends State<OffersAndDiscountPaymentP
if (selectedOffer == null) { if (selectedOffer == null) {
return Center( return Center(
child: Column( child: Container(
mainAxisAlignment: MainAxisAlignment.center, color: AppColors.bgScaffoldColor,
children: [ child: Column(
Icon(Icons.error_outline, size: 64.h, color: AppColors.errorColor), mainAxisAlignment: MainAxisAlignment.center,
SizedBox(height: 16.h), children: [
LocaleKeys.noDataAvailable.tr(context: context).toText16(), Icon(Icons.error_outline, size: 64.h, color: AppColors.errorColor),
], SizedBox(height: 16.h),
LocaleKeys.noDataAvailable.tr(context: context).toText16(),
],
),
), ),
); );
} }
@ -111,225 +114,240 @@ class _OffersAndDiscountPaymentPageState extends State<OffersAndDiscountPaymentP
child: CollapsingListView( child: CollapsingListView(
title: "${LocaleKeys.offerAndPackages.tr(context: context)} ${LocaleKeys.payment.tr(context: context)}", title: "${LocaleKeys.offerAndPackages.tr(context: context)} ${LocaleKeys.payment.tr(context: context)}",
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Container(
crossAxisAlignment: CrossAxisAlignment.start, color: AppColors.bgScaffoldColor,
children: [ child: Column(
SizedBox(height: 24.h), crossAxisAlignment: CrossAxisAlignment.start,
// Offer Summary Card children: [
Container( SizedBox(height: 24.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( // Offer Summary Card
color: AppColors.whiteColor, Container(
borderRadius: 20.h, decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
hasShadow: false, color: AppColors.whiteColor,
), borderRadius: 20.h,
child: Column( hasShadow: false,
crossAxisAlignment: CrossAxisAlignment.start, ),
children: [ child: Column(
(appState.getLanguageID() == 1 ? selectedOffer.nameAr : selectedOffer.name).toText18(isBold: true), crossAxisAlignment: CrossAxisAlignment.start,
SizedBox(height: 8.h), children: [
Row( (appState.getLanguageID() == 1 ? selectedOffer.nameAr : selectedOffer.name).toText18(isBold: true),
mainAxisAlignment: MainAxisAlignment.spaceBetween, SizedBox(height: 8.h),
children: [ Row(
LocaleKeys.price.tr(context: context).toText14(color: AppColors.greyTextColor), mainAxisAlignment: MainAxisAlignment.spaceBetween,
"${selectedOffer.vatExclusivePrice} ${selectedOffer.currency}".toText16(isBold: true, color: AppColors.primaryRedColor), children: [
], LocaleKeys.price.tr(context: context).toText14(color: AppColors.greyTextColor),
), "${selectedOffer.vatExclusivePrice} ${selectedOffer.currency}".toText16(isBold: true, color: AppColors.primaryRedColor),
], ],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 24.h),
LocaleKeys.selectPaymentMethod.tr(context: context).toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
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: [
Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h, fit: BoxFit.contain),
SizedBox(height: 16.h),
LocaleKeys.mada.tr(context: context).toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 40.h,
height: 40.h,
fit: BoxFit.contain,
), ),
), ],
], ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h).onPress(() async { SizedBox(height: 24.h),
selectedPaymentMethod = "MADA"; LocaleKeys.selectPaymentMethod.tr(context: context).toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 16.h),
// Create order first to get order_ref Container(
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPaymentInformation.tr(context: context)); decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
String? orderRef = await createOrder(); color: AppColors.whiteColor,
borderRadius: 20.h,
if (orderRef == null) { hasShadow: false,
// Error already shown in createOrder ),
return; child: Row(
} mainAxisSize: MainAxisSize.max,
children: [
transID = orderRef; Column(
crossAxisAlignment: CrossAxisAlignment.start,
if (appState.isPaytabsEnabled) { children: [
LoaderBottomSheet.hideLoader(); Utils.buildImgWithAssets(icon: AppAssets.mada, width: 72.h, height: 25.h, fit: BoxFit.contain),
paytabsViewModel.setPaymentConfiguration( SizedBox(height: 16.h),
LocaleKeys.offerPayment.tr(context: context), LocaleKeys.mada.tr(context: context).toText16(isBold: true),
getPaymentAmount(), ],
); ),
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async { SizedBox(width: 8.h),
await completePaymentResult(paymentStatus: "success"); const Spacer(),
}, onError: (err) { Transform.flip(
showCommonBottomSheetWithoutHeight( flipX: appState.isArabic(),
context, child: Utils.buildSvgWithAssets(
child: Utils.getErrorWidget(loadingText: err.toString()), icon: AppAssets.forward_arrow_icon,
callBackFunc: () {}, iconColor: AppColors.blackColor,
isFullScreen: false, width: 40.h,
isCloseButtonVisible: true, height: 40.h,
); fit: BoxFit.contain,
}); ),
} else { ),
if (appState.isPayfortHostedPageEnabled) { ],
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.offerPayment.getIdFromServiceEnum(), projectId: 0, integrationId: 1); ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() async {
payfortViewModel.initiatePaymentWithCard( selectedPaymentMethod = "MADA";
transactionID: transID,
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(), // Create order first to get order_ref
amount: getPaymentAmount().toString(), LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPaymentInformation.tr(context: context));
onSucceeded: (paymentResult) async { String? orderRef = await createOrder();
print("Payment Success Data: ${paymentResult.toString()}");
await completePaymentResult(paymentStatus: "success"); if (orderRef == null) {
}, // Error already shown in createOrder
onFailed: (err) { return;
print("Payment Failed Data: ${err.toString()}"); }
showCommonBottomSheetWithoutHeight(
context, transID = orderRef;
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {}, if (appState.isPaytabsEnabled) {
isFullScreen: false, LoaderBottomSheet.hideLoader();
isCloseButtonVisible: true, paytabsViewModel.setPaymentConfiguration(
); LocaleKeys.offerPayment.tr(context: context),
}, getPaymentAmount(),
); );
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async {
await completePaymentResult(paymentStatus: "success");
}, onError: (err) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else { } else {
LoaderBottomSheet.hideLoader(); if (appState.isPayfortHostedPageEnabled) {
openPaymentURL("mada", getPaymentAmount()); await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.offerPayment.getIdFromServiceEnum(), projectId: 0, integrationId: 1);
payfortViewModel.initiatePaymentWithCard(
"mada",
ServiceTypeEnum.offerPayment.getIdFromServiceEnum().toString(),
"false",
DateUtil.convertDateToString(DateTime.now()),
"0",
"0",
transactionID: transID,
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(),
amount: getPaymentAmount().toString(),
onSucceeded: (paymentResult) async {
print("Payment Success Data: ${paymentResult.toString()}");
await completePaymentResult(paymentStatus: "success");
},
onFailed: (err) {
print("Payment Failed Data: ${err.toString()}");
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
);
} else {
LoaderBottomSheet.hideLoader();
openPaymentURL("mada", getPaymentAmount());
}
} }
} }),
}), SizedBox(height: 16.h),
SizedBox(height: 16.h), Container(
Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration( color: AppColors.whiteColor,
color: AppColors.whiteColor, borderRadius: 20.h,
borderRadius: 20.h, hasShadow: false,
hasShadow: false, ),
), child: Row(
child: Row( mainAxisSize: MainAxisSize.max,
mainAxisSize: MainAxisSize.max, children: [
children: [ Column(
Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ Row(
Row( children: [
children: [ Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h),
Utils.buildImgWithAssets(icon: AppAssets.visa, width: 50.h, height: 50.h), SizedBox(width: 8.h),
SizedBox(width: 8.h), Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h, fit: BoxFit.contain),
Utils.buildImgWithAssets(icon: AppAssets.mastercard, width: 40.h, height: 40.h, fit: BoxFit.contain), ],
], ),
SizedBox(height: 16.h),
LocaleKeys.visaOrMastercard.tr(context: context).toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 40.h,
height: 40.h,
fit: BoxFit.contain,
), ),
SizedBox(height: 16.h),
LocaleKeys.visaOrMastercard.tr(context: context).toText16(isBold: true),
],
),
SizedBox(width: 8.h),
const Spacer(),
Transform.flip(
flipX: appState.isArabic(),
child: Utils.buildSvgWithAssets(
icon: AppAssets.forward_arrow_icon,
iconColor: AppColors.blackColor,
width: 40.h,
height: 40.h,
fit: BoxFit.contain,
), ),
), ],
], ).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(16.h, 16.h), ).paddingSymmetrical(24.h, 0.h).onPress(() async {
).paddingSymmetrical(24.h, 0.h).onPress(() async { selectedPaymentMethod = "VISA";
selectedPaymentMethod = "VISA";
// Create order first to get order_ref
// Create order first to get order_ref LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPaymentInformation.tr(context: context));
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.fetchingPaymentInformation.tr(context: context)); String? orderRef = await createOrder();
String? orderRef = await createOrder();
if (orderRef == null) {
if (orderRef == null) { // Error already shown in createOrder
// Error already shown in createOrder return;
return; }
}
transID = orderRef;
transID = orderRef;
if (appState.isPaytabsEnabled) {
if (appState.isPaytabsEnabled) { LoaderBottomSheet.hideLoader();
LoaderBottomSheet.hideLoader(); paytabsViewModel.setPaymentConfiguration(
paytabsViewModel.setPaymentConfiguration( LocaleKeys.offerPayment.tr(context: context),
LocaleKeys.offerPayment.tr(context: context), getPaymentAmount(),
getPaymentAmount(),
);
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async {
await completePaymentResult(paymentStatus: "success");
}, onError: (err) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
if (appState.isPayfortHostedPageEnabled) {
await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.offerPayment.getIdFromServiceEnum(), projectId: 0, integrationId: 1);
payfortViewModel.initiatePaymentWithCard(
transactionID: transID,
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(),
amount: getPaymentAmount().toString(),
onSucceeded: (paymentResult) async {
print("Payment Success Data: ${paymentResult.toString()}");
await completePaymentResult(paymentStatus: "success");
},
onFailed: (err) {
print("Payment Failed Data: ${err.toString()}");
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
); );
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async {
await completePaymentResult(paymentStatus: "success");
}, onError: (err) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else { } else {
LoaderBottomSheet.hideLoader(); if (appState.isPayfortHostedPageEnabled) {
openPaymentURL("visa", getPaymentAmount()); await payfortViewModel.getPayfortConfigurations(serviceId: ServiceTypeEnum.offerPayment.getIdFromServiceEnum(), projectId: 0, integrationId: 1);
payfortViewModel.initiatePaymentWithCard(
transactionID: transID,
"visa",
ServiceTypeEnum.offerPayment.getIdFromServiceEnum().toString(),
"false",
DateUtil.convertDateToString(DateTime.now()),
"0",
"0",
fileNumber: appState.getAuthenticatedUser()!.patientId.toString(),
amount: getPaymentAmount().toString(),
onSucceeded: (paymentResult) async {
print("Payment Success Data: ${paymentResult.toString()}");
await completePaymentResult(paymentStatus: "success");
},
onFailed: (err) {
print("Payment Failed Data: ${err.toString()}");
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
},
);
} else {
LoaderBottomSheet.hideLoader();
openPaymentURL("visa", getPaymentAmount());
}
} }
} }),
}), ],
], ),
), ),
), ),
), ),

@ -133,12 +133,18 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
getIt<AuthenticationViewModel>().onLoginPressed(); getIt<AuthenticationViewModel>().onLoginPressed();
}); });
} else { } else {
// Show loader during authentication
LoaderBottomSheet.showLoader(loadingText: LocaleKeys.pleaseWait.tr(context: context));
// Ensure patient is authenticated (will re-authenticate if needed) // Ensure patient is authenticated (will re-authenticate if needed)
final isAuthenticated = await viewModel.ensureAuthenticated( final isAuthenticated = await viewModel.ensureAuthenticated(
onSuccess: () { onSuccess: () {
// Authentication successful, continue // Authentication successful, continue
}, },
onError: (error) { onError: (error) {
// Hide loader on error
LoaderBottomSheet.hideLoader();
// Show error to user
showCommonBottomSheetWithoutHeight( showCommonBottomSheetWithoutHeight(
context, context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)), child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
@ -150,8 +156,15 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
); );
if (!isAuthenticated) { if (!isAuthenticated) {
// Hide loader if authentication failed
LoaderBottomSheet.hideLoader();
return; return;
} }
// Hide loader on success
LoaderBottomSheet.hideLoader();
// Set the selected offer and navigate to payment page
viewModel.setSelectedOffer(viewModel.offerDetails!); viewModel.setSelectedOffer(viewModel.offerDetails!);
Navigator.of(context).push( Navigator.of(context).push(
CustomPageRoute( CustomPageRoute(
@ -359,10 +372,7 @@ class _OffersAndDiscountsDetailedPageState extends State<OffersAndDiscountsDetai
// Branches Section // Branches Section
if (offer.branches.isNotEmpty) ...[ if (offer.branches.isNotEmpty) ...[
LocaleKeys.availableAt.tr(context: context).toText18( LocaleKeys.availableAt.tr(context: context).toText18(isBold: true, weight: FontWeight.w700),
isBold: true,
weight: FontWeight.w700,
),
SizedBox(height: 12.h), SizedBox(height: 12.h),
Wrap( Wrap(
spacing: 8.w, spacing: 8.w,

Loading…
Cancel
Save