@resira/ui 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -238
- package/dist/index.cjs +257 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -6
- package/dist/index.d.ts +37 -6
- package/dist/index.js +257 -34
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2879 -2809
- package/package.json +59 -59
package/dist/index.cjs
CHANGED
|
@@ -173,6 +173,7 @@ function ResiraProvider({
|
|
|
173
173
|
resourceId,
|
|
174
174
|
domain,
|
|
175
175
|
config,
|
|
176
|
+
checkoutSessionToken,
|
|
176
177
|
onClose,
|
|
177
178
|
children
|
|
178
179
|
}) {
|
|
@@ -262,9 +263,10 @@ function ResiraProvider({
|
|
|
262
263
|
deeplinkGuest,
|
|
263
264
|
onStepChange,
|
|
264
265
|
onBookingComplete,
|
|
265
|
-
onError
|
|
266
|
+
onError,
|
|
267
|
+
checkoutSessionToken
|
|
266
268
|
}),
|
|
267
|
-
[client, resourceId, activeResourceId, setActiveResourceId, catalogMode, allowMultiSelect, domain, theme, locale, domainConfig, stripePublishableKey, termsText, waiverText, showWaiver, showTerms, showRemainingSpots, depositPercent, refundPolicy, onClose, classNames, serviceLayout, visibleServiceCount, groupServicesByCategory, renderServiceCard, showStepIndicator, deeplink, deeplinkGuest, onStepChange, onBookingComplete, onError]
|
|
269
|
+
[client, resourceId, activeResourceId, setActiveResourceId, catalogMode, allowMultiSelect, domain, theme, locale, domainConfig, stripePublishableKey, termsText, waiverText, showWaiver, showTerms, showRemainingSpots, depositPercent, refundPolicy, onClose, classNames, serviceLayout, visibleServiceCount, groupServicesByCategory, renderServiceCard, showStepIndicator, deeplink, deeplinkGuest, onStepChange, onBookingComplete, onError, checkoutSessionToken]
|
|
268
270
|
);
|
|
269
271
|
return /* @__PURE__ */ jsxRuntime.jsx(ResiraContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "resira-root", style: cssVars, children }) });
|
|
270
272
|
}
|
|
@@ -596,6 +598,60 @@ function useDishes(enabled = true) {
|
|
|
596
598
|
}, [client, enabled]);
|
|
597
599
|
return { dishes, loading, error };
|
|
598
600
|
}
|
|
601
|
+
function useCheckoutSession(token) {
|
|
602
|
+
const { client } = useResira();
|
|
603
|
+
const [session, setSession] = react.useState(null);
|
|
604
|
+
const [loading, setLoading] = react.useState(!!token);
|
|
605
|
+
const [error, setError] = react.useState(null);
|
|
606
|
+
const [errorCode, setErrorCode] = react.useState(null);
|
|
607
|
+
react.useEffect(() => {
|
|
608
|
+
if (!token) {
|
|
609
|
+
setSession(null);
|
|
610
|
+
setLoading(false);
|
|
611
|
+
setError(null);
|
|
612
|
+
setErrorCode(null);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
let cancelled = false;
|
|
616
|
+
setLoading(true);
|
|
617
|
+
setError(null);
|
|
618
|
+
setErrorCode(null);
|
|
619
|
+
async function fetchSession() {
|
|
620
|
+
try {
|
|
621
|
+
const data = await client.getCheckoutSession(token);
|
|
622
|
+
if (!cancelled) {
|
|
623
|
+
setSession(data.session);
|
|
624
|
+
}
|
|
625
|
+
} catch (err) {
|
|
626
|
+
if (cancelled) return;
|
|
627
|
+
const apiErr = err;
|
|
628
|
+
const message = apiErr.body?.error ?? (err instanceof Error ? err.message : "Failed to load checkout session");
|
|
629
|
+
if (apiErr.status === 404) {
|
|
630
|
+
setError("Invalid booking link");
|
|
631
|
+
setErrorCode("not_found");
|
|
632
|
+
} else if (message.toLowerCase().includes("consumed")) {
|
|
633
|
+
setError("This booking was already completed");
|
|
634
|
+
setErrorCode("consumed");
|
|
635
|
+
} else if (message.toLowerCase().includes("expired")) {
|
|
636
|
+
setError("Session expired \u2014 please start a new booking");
|
|
637
|
+
setErrorCode("expired");
|
|
638
|
+
} else {
|
|
639
|
+
setError(message);
|
|
640
|
+
setErrorCode("unknown");
|
|
641
|
+
}
|
|
642
|
+
} finally {
|
|
643
|
+
if (!cancelled) {
|
|
644
|
+
setLoading(false);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
fetchSession();
|
|
649
|
+
return () => {
|
|
650
|
+
cancelled = true;
|
|
651
|
+
};
|
|
652
|
+
}, [client, token]);
|
|
653
|
+
return { session, loading, error, errorCode };
|
|
654
|
+
}
|
|
599
655
|
var defaultSize = 20;
|
|
600
656
|
function CalendarIcon({ size = defaultSize, className }) {
|
|
601
657
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2677,7 +2733,8 @@ var STEP_LABELS = {
|
|
|
2677
2733
|
details: "Details",
|
|
2678
2734
|
terms: "Terms",
|
|
2679
2735
|
payment: "Payment",
|
|
2680
|
-
confirmation: "Done"
|
|
2736
|
+
confirmation: "Done",
|
|
2737
|
+
checkout: "Checkout"
|
|
2681
2738
|
};
|
|
2682
2739
|
function ResiraBookingWidget() {
|
|
2683
2740
|
const {
|
|
@@ -2699,16 +2756,26 @@ function ResiraBookingWidget() {
|
|
|
2699
2756
|
deeplinkGuest,
|
|
2700
2757
|
onStepChange,
|
|
2701
2758
|
onBookingComplete,
|
|
2702
|
-
onError
|
|
2759
|
+
onError,
|
|
2760
|
+
checkoutSessionToken
|
|
2703
2761
|
} = useResira();
|
|
2704
2762
|
const isDateBased = domain === "rental";
|
|
2705
2763
|
const isTimeBased = domain === "restaurant" || domain === "watersport" || domain === "service";
|
|
2706
2764
|
const isServiceBased = domain === "watersport" || domain === "service";
|
|
2707
2765
|
const hasPayment = !!stripePublishableKey;
|
|
2708
|
-
const
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2766
|
+
const isCheckoutMode = !!checkoutSessionToken;
|
|
2767
|
+
const {
|
|
2768
|
+
session: checkoutSession,
|
|
2769
|
+
loading: checkoutSessionLoading,
|
|
2770
|
+
error: checkoutSessionError,
|
|
2771
|
+
errorCode: checkoutSessionErrorCode
|
|
2772
|
+
} = useCheckoutSession(checkoutSessionToken);
|
|
2773
|
+
const STEPS = react.useMemo(() => {
|
|
2774
|
+
if (isCheckoutMode) {
|
|
2775
|
+
return ["checkout", "payment", "confirmation"];
|
|
2776
|
+
}
|
|
2777
|
+
return buildSteps(domain, hasPayment, catalogMode);
|
|
2778
|
+
}, [domain, hasPayment, catalogMode, isCheckoutMode]);
|
|
2712
2779
|
const initialStep = STEPS[0];
|
|
2713
2780
|
const [step, setStep] = react.useState(initialStep);
|
|
2714
2781
|
const [selectedResourceIds, setSelectedResourceIds] = react.useState([]);
|
|
@@ -2789,6 +2856,16 @@ function ResiraBookingWidget() {
|
|
|
2789
2856
|
const [paymentFormReady, setPaymentFormReady] = react.useState(false);
|
|
2790
2857
|
const [paymentFormSubmitting, setPaymentFormSubmitting] = react.useState(false);
|
|
2791
2858
|
const paymentPayload = react.useMemo(() => {
|
|
2859
|
+
if (isCheckoutMode && checkoutSession) {
|
|
2860
|
+
return {
|
|
2861
|
+
checkoutSessionToken,
|
|
2862
|
+
guestName: guest.guestName.trim() || checkoutSession.guestName || "",
|
|
2863
|
+
guestEmail: guest.guestEmail.trim() || checkoutSession.guestEmail || void 0,
|
|
2864
|
+
guestPhone: guest.guestPhone.trim() || void 0,
|
|
2865
|
+
notes: guest.notes.trim() || void 0,
|
|
2866
|
+
termsAccepted: termsAccepted || void 0
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2792
2869
|
const resourceId = activeResourceId ?? selectedProduct?.equipmentIds?.[0] ?? "";
|
|
2793
2870
|
return {
|
|
2794
2871
|
productId: selectedProduct?.id ?? "",
|
|
@@ -2805,7 +2882,7 @@ function ResiraBookingWidget() {
|
|
|
2805
2882
|
promoCode: discountCode.trim() || void 0,
|
|
2806
2883
|
termsAccepted: termsAccepted || void 0
|
|
2807
2884
|
};
|
|
2808
|
-
}, [activeResourceId, selectedProduct, selection, guest, discountCode, termsAccepted]);
|
|
2885
|
+
}, [activeResourceId, selectedProduct, selection, guest, discountCode, termsAccepted, isCheckoutMode, checkoutSession, checkoutSessionToken]);
|
|
2809
2886
|
const blockedDates = react.useMemo(() => {
|
|
2810
2887
|
const dates = calendarData?.dates?.blockedDates ?? availability?.dates?.blockedDates ?? [];
|
|
2811
2888
|
return new Set(dates);
|
|
@@ -2863,6 +2940,8 @@ function ResiraBookingWidget() {
|
|
|
2863
2940
|
return locale.payment;
|
|
2864
2941
|
case "confirmation":
|
|
2865
2942
|
return locale.bookingConfirmed;
|
|
2943
|
+
case "checkout":
|
|
2944
|
+
return "Checkout";
|
|
2866
2945
|
}
|
|
2867
2946
|
}, [step, isDateBased, isServiceBased, locale, domain]);
|
|
2868
2947
|
const stepSubtitle = react.useMemo(() => {
|
|
@@ -2881,8 +2960,10 @@ function ResiraBookingWidget() {
|
|
|
2881
2960
|
return "Complete your booking securely";
|
|
2882
2961
|
case "confirmation":
|
|
2883
2962
|
return "";
|
|
2963
|
+
case "checkout":
|
|
2964
|
+
return checkoutSession?.productName ?? "Complete your booking";
|
|
2884
2965
|
}
|
|
2885
|
-
}, [step, domainConfig.label, locale, allowMultiSelect, isServiceBased, selectedProduct, domain]);
|
|
2966
|
+
}, [step, domainConfig.label, locale, allowMultiSelect, isServiceBased, selectedProduct, domain, checkoutSession]);
|
|
2886
2967
|
const canContinue = react.useMemo(() => {
|
|
2887
2968
|
if (step === "resource") {
|
|
2888
2969
|
if (isServiceBased) return !!selectedProduct;
|
|
@@ -3060,6 +3141,35 @@ function ResiraBookingWidget() {
|
|
|
3060
3141
|
const handlePaymentError = react.useCallback((msg) => {
|
|
3061
3142
|
onError?.("payment_error", msg);
|
|
3062
3143
|
}, [onError]);
|
|
3144
|
+
const handleCheckoutSubmit = react.useCallback(async () => {
|
|
3145
|
+
const contactMode = "email-required";
|
|
3146
|
+
const errors = validateGuestForm(guest, {
|
|
3147
|
+
required: locale.required,
|
|
3148
|
+
invalidEmail: locale.invalidEmail,
|
|
3149
|
+
contactRequired: locale.contactRequired
|
|
3150
|
+
}, contactMode);
|
|
3151
|
+
if (Object.keys(errors).length > 0) {
|
|
3152
|
+
setFormErrors(errors);
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3155
|
+
setFormErrors({});
|
|
3156
|
+
if (checkoutSession?.checkoutConfig.termsRequired && !termsAccepted) {
|
|
3157
|
+
setTermsError(locale.termsRequired);
|
|
3158
|
+
return;
|
|
3159
|
+
}
|
|
3160
|
+
setTermsError(null);
|
|
3161
|
+
const result = await createPayment(paymentPayload);
|
|
3162
|
+
if (!result) return;
|
|
3163
|
+
if (result.amountNow === 0) {
|
|
3164
|
+
if (result.reservationId) {
|
|
3165
|
+
const confirmed = await confirmPayment(result.paymentIntentId, result.reservationId);
|
|
3166
|
+
if (!confirmed) return;
|
|
3167
|
+
}
|
|
3168
|
+
setStep("confirmation");
|
|
3169
|
+
} else {
|
|
3170
|
+
setStep("payment");
|
|
3171
|
+
}
|
|
3172
|
+
}, [guest, locale, checkoutSession, termsAccepted, createPayment, paymentPayload, confirmPayment]);
|
|
3063
3173
|
const handleSubmitNoPayment = react.useCallback(async () => {
|
|
3064
3174
|
if (showTerms && !termsAccepted) {
|
|
3065
3175
|
setTermsError(locale.termsRequired);
|
|
@@ -3090,6 +3200,17 @@ function ResiraBookingWidget() {
|
|
|
3090
3200
|
const footerBusy = submitting || creatingPayment || confirmingPayment || paymentFormSubmitting;
|
|
3091
3201
|
const paymentActionDisabled = !paymentIntent || !paymentFormReady || paymentFormSubmitting || confirmingPayment;
|
|
3092
3202
|
const [deeplinkApplied, setDeeplinkApplied] = react.useState(false);
|
|
3203
|
+
const [checkoutGuestFilled, setCheckoutGuestFilled] = react.useState(false);
|
|
3204
|
+
react.useEffect(() => {
|
|
3205
|
+
if (checkoutGuestFilled || !checkoutSession) return;
|
|
3206
|
+
setGuest((prev) => ({
|
|
3207
|
+
guestName: checkoutSession.guestName ?? prev.guestName,
|
|
3208
|
+
guestEmail: checkoutSession.guestEmail ?? prev.guestEmail,
|
|
3209
|
+
guestPhone: prev.guestPhone,
|
|
3210
|
+
notes: prev.notes
|
|
3211
|
+
}));
|
|
3212
|
+
setCheckoutGuestFilled(true);
|
|
3213
|
+
}, [checkoutSession, checkoutGuestFilled]);
|
|
3093
3214
|
react.useEffect(() => {
|
|
3094
3215
|
if (deeplinkApplied || !deeplink) return;
|
|
3095
3216
|
if (deeplink.productId && products.length > 0 && !selectedProduct) {
|
|
@@ -3325,6 +3446,93 @@ function ResiraBookingWidget() {
|
|
|
3325
3446
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "resira-error-message", children: paymentError })
|
|
3326
3447
|
] })
|
|
3327
3448
|
] }),
|
|
3449
|
+
step === "checkout" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3450
|
+
checkoutSessionLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-loading", role: "status", "aria-live": "polite", "aria-busy": "true", children: [
|
|
3451
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "resira-spinner", "aria-hidden": "true" }),
|
|
3452
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-loading-text", children: locale.loading })
|
|
3453
|
+
] }),
|
|
3454
|
+
checkoutSessionError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-error", role: "alert", "aria-live": "assertive", children: [
|
|
3455
|
+
/* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { size: 24 }),
|
|
3456
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "resira-error-message", children: checkoutSessionError }),
|
|
3457
|
+
(checkoutSessionErrorCode === "not_found" || checkoutSessionErrorCode === "expired") && onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3458
|
+
"button",
|
|
3459
|
+
{
|
|
3460
|
+
type: "button",
|
|
3461
|
+
className: "resira-btn resira-btn--secondary resira-error-retry",
|
|
3462
|
+
onClick: onClose,
|
|
3463
|
+
children: "Start a new booking"
|
|
3464
|
+
}
|
|
3465
|
+
)
|
|
3466
|
+
] }),
|
|
3467
|
+
checkoutSession && !checkoutSessionError && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3468
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary", style: { marginBottom: 16 }, children: [
|
|
3469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3470
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: "Service" }),
|
|
3471
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value", children: checkoutSession.productName })
|
|
3472
|
+
] }),
|
|
3473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3474
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: "Date" }),
|
|
3475
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value", children: (/* @__PURE__ */ new Date(checkoutSession.date + "T00:00:00")).toLocaleDateString("default", { weekday: "short", month: "short", day: "numeric" }) })
|
|
3476
|
+
] }),
|
|
3477
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3478
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: "Time" }),
|
|
3479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "resira-summary-value", children: [
|
|
3480
|
+
new Date(checkoutSession.startTime).toLocaleTimeString("default", { hour: "2-digit", minute: "2-digit", hour12: false }),
|
|
3481
|
+
" \u2013 ",
|
|
3482
|
+
new Date(checkoutSession.endTime).toLocaleTimeString("default", { hour: "2-digit", minute: "2-digit", hour12: false })
|
|
3483
|
+
] })
|
|
3484
|
+
] }),
|
|
3485
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3486
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: "Duration" }),
|
|
3487
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "resira-summary-value", children: [
|
|
3488
|
+
checkoutSession.durationMinutes,
|
|
3489
|
+
" min"
|
|
3490
|
+
] })
|
|
3491
|
+
] }),
|
|
3492
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3493
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: locale.guests }),
|
|
3494
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value", children: checkoutSession.partySize })
|
|
3495
|
+
] }),
|
|
3496
|
+
checkoutSession.promoCode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3497
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label", children: locale.discountCode }),
|
|
3498
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value", children: checkoutSession.promoCode })
|
|
3499
|
+
] }),
|
|
3500
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "resira-summary-divider" }),
|
|
3501
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-summary-row", children: [
|
|
3502
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-label resira-summary-total", children: locale.total }),
|
|
3503
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value resira-summary-total", children: formatPrice5(checkoutSession.priceCents, checkoutSession.currency) })
|
|
3504
|
+
] })
|
|
3505
|
+
] }),
|
|
3506
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3507
|
+
GuestForm,
|
|
3508
|
+
{
|
|
3509
|
+
values: guest,
|
|
3510
|
+
onChange: setGuest,
|
|
3511
|
+
errors: formErrors
|
|
3512
|
+
}
|
|
3513
|
+
),
|
|
3514
|
+
checkoutSession.checkoutConfig.termsRequired && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3515
|
+
WaiverConsent,
|
|
3516
|
+
{
|
|
3517
|
+
termsAccepted,
|
|
3518
|
+
onTermsChange: setTermsAccepted,
|
|
3519
|
+
waiverAccepted: false,
|
|
3520
|
+
onWaiverChange: () => {
|
|
3521
|
+
},
|
|
3522
|
+
discountCode: "",
|
|
3523
|
+
onDiscountCodeChange: () => {
|
|
3524
|
+
},
|
|
3525
|
+
onPromoValidated: () => {
|
|
3526
|
+
},
|
|
3527
|
+
error: termsError ?? void 0
|
|
3528
|
+
}
|
|
3529
|
+
) }),
|
|
3530
|
+
paymentError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-error", style: { padding: "12px 0" }, children: [
|
|
3531
|
+
/* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { size: 18 }),
|
|
3532
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "resira-error-message", children: paymentError })
|
|
3533
|
+
] })
|
|
3534
|
+
] })
|
|
3535
|
+
] }),
|
|
3328
3536
|
step === "payment" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3329
3537
|
paymentError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-error", children: [
|
|
3330
3538
|
/* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { size: 24 }),
|
|
@@ -3410,31 +3618,45 @@ function ResiraBookingWidget() {
|
|
|
3410
3618
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "resira-summary-value resira-summary-total", children: formatPrice5(computedPrice.total, currency) })
|
|
3411
3619
|
] })
|
|
3412
3620
|
] })
|
|
3413
|
-
] }) })
|
|
3414
|
-
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3415
|
-
"button",
|
|
3416
|
-
{
|
|
3417
|
-
type: "button",
|
|
3418
|
-
className: "resira-btn resira-btn--primary",
|
|
3419
|
-
style: { marginTop: 20, width: "100%" },
|
|
3420
|
-
onClick: onClose,
|
|
3421
|
-
children: locale.done
|
|
3422
|
-
}
|
|
3423
|
-
)
|
|
3621
|
+
] }) })
|
|
3424
3622
|
] })
|
|
3425
3623
|
] }),
|
|
3426
|
-
|
|
3427
|
-
|
|
3624
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "resira-widget-footer", children: [
|
|
3625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3428
3626
|
"button",
|
|
3429
3627
|
{
|
|
3430
3628
|
type: "button",
|
|
3431
3629
|
className: "resira-btn resira-btn--secondary",
|
|
3432
3630
|
onClick: handleBack,
|
|
3433
|
-
disabled: footerBusy,
|
|
3631
|
+
disabled: footerBusy || currentIndex === 0,
|
|
3632
|
+
style: currentIndex === 0 || step === "confirmation" ? { visibility: "hidden" } : void 0,
|
|
3633
|
+
"aria-hidden": currentIndex === 0 || step === "confirmation",
|
|
3434
3634
|
children: locale.back
|
|
3435
3635
|
}
|
|
3436
3636
|
),
|
|
3437
|
-
|
|
3637
|
+
step === "confirmation" ? onClose ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3638
|
+
"button",
|
|
3639
|
+
{
|
|
3640
|
+
type: "button",
|
|
3641
|
+
className: "resira-btn resira-btn--primary",
|
|
3642
|
+
onClick: onClose,
|
|
3643
|
+
children: locale.done
|
|
3644
|
+
}
|
|
3645
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { visibility: "hidden" }, className: "resira-btn resira-btn--primary", children: locale.continue }) : step === "checkout" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3646
|
+
"button",
|
|
3647
|
+
{
|
|
3648
|
+
type: "button",
|
|
3649
|
+
className: "resira-btn resira-btn--primary",
|
|
3650
|
+
onClick: () => {
|
|
3651
|
+
void handleCheckoutSubmit();
|
|
3652
|
+
},
|
|
3653
|
+
disabled: footerBusy || checkoutSessionLoading || !!checkoutSessionError,
|
|
3654
|
+
children: creatingPayment ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3655
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "resira-spinner", style: { width: 16, height: 16 } }),
|
|
3656
|
+
locale.processingPayment
|
|
3657
|
+
] }) : checkoutSession ? `${locale.payNow} \u2014 ${formatPrice5(checkoutSession.priceCents, checkoutSession.currency)}` : locale.continue
|
|
3658
|
+
}
|
|
3659
|
+
) : step === "resource" || step === "availability" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3438
3660
|
"button",
|
|
3439
3661
|
{
|
|
3440
3662
|
type: "button",
|
|
@@ -3445,8 +3667,7 @@ function ResiraBookingWidget() {
|
|
|
3445
3667
|
disabled: !canContinue || footerBusy,
|
|
3446
3668
|
children: locale.continue
|
|
3447
3669
|
}
|
|
3448
|
-
)
|
|
3449
|
-
step === "details" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3670
|
+
) : step === "details" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3450
3671
|
"button",
|
|
3451
3672
|
{
|
|
3452
3673
|
type: "button",
|
|
@@ -3458,8 +3679,7 @@ function ResiraBookingWidget() {
|
|
|
3458
3679
|
locale.loading
|
|
3459
3680
|
] }) : domain === "restaurant" && !hasPayment ? locale.reserveTable : locale.continue
|
|
3460
3681
|
}
|
|
3461
|
-
)
|
|
3462
|
-
step === "terms" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3682
|
+
) : step === "terms" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3463
3683
|
"button",
|
|
3464
3684
|
{
|
|
3465
3685
|
type: "button",
|
|
@@ -3476,8 +3696,7 @@ function ResiraBookingWidget() {
|
|
|
3476
3696
|
locale.loading
|
|
3477
3697
|
] }) : hasPayment ? locale.continue : locale.bookNow
|
|
3478
3698
|
}
|
|
3479
|
-
)
|
|
3480
|
-
step === "payment" && !paymentIntent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3699
|
+
) : step === "payment" && !paymentIntent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3481
3700
|
"button",
|
|
3482
3701
|
{
|
|
3483
3702
|
type: "button",
|
|
@@ -3491,8 +3710,7 @@ function ResiraBookingWidget() {
|
|
|
3491
3710
|
locale.processingPayment
|
|
3492
3711
|
] }) : computedPrice ? `${locale.payNow} \u2014 ${formatPrice5(computedPrice.amountNow, currency)}` : locale.payNow
|
|
3493
3712
|
}
|
|
3494
|
-
)
|
|
3495
|
-
step === "payment" && paymentIntent?.amountNow != null && paymentIntent.amountNow > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3713
|
+
) : step === "payment" && paymentIntent?.amountNow != null && paymentIntent.amountNow > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3496
3714
|
"button",
|
|
3497
3715
|
{
|
|
3498
3716
|
type: "button",
|
|
@@ -3504,6 +3722,9 @@ function ResiraBookingWidget() {
|
|
|
3504
3722
|
locale.processingPayment
|
|
3505
3723
|
] }) : `${locale.payNow} \u2014 ${formatPrice5(paymentIntent.amountNow, paymentIntent.currency)}`
|
|
3506
3724
|
}
|
|
3725
|
+
) : (
|
|
3726
|
+
/* Fallback placeholder to hold space (e.g. zero-amount payment auto-advancing) */
|
|
3727
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { visibility: "hidden" }, className: "resira-btn resira-btn--primary", children: locale.continue })
|
|
3507
3728
|
)
|
|
3508
3729
|
] })
|
|
3509
3730
|
] });
|
|
@@ -3513,6 +3734,7 @@ function BookingModal({
|
|
|
3513
3734
|
domain,
|
|
3514
3735
|
resourceId,
|
|
3515
3736
|
config,
|
|
3737
|
+
checkoutSessionToken,
|
|
3516
3738
|
trigger,
|
|
3517
3739
|
buttonLabel = "Book Now",
|
|
3518
3740
|
buttonClassName,
|
|
@@ -3636,6 +3858,7 @@ function BookingModal({
|
|
|
3636
3858
|
domain,
|
|
3637
3859
|
resourceId,
|
|
3638
3860
|
config,
|
|
3861
|
+
checkoutSessionToken,
|
|
3639
3862
|
onClose: handleClose,
|
|
3640
3863
|
children: /* @__PURE__ */ jsxRuntime.jsx(ResiraBookingWidget, {})
|
|
3641
3864
|
}
|
|
@@ -4025,6 +4248,7 @@ exports.XIcon = XIcon;
|
|
|
4025
4248
|
exports.resolveTheme = resolveTheme;
|
|
4026
4249
|
exports.themeToCSS = themeToCSS;
|
|
4027
4250
|
exports.useAvailability = useAvailability;
|
|
4251
|
+
exports.useCheckoutSession = useCheckoutSession;
|
|
4028
4252
|
exports.useDish = useDish;
|
|
4029
4253
|
exports.useDishes = useDishes;
|
|
4030
4254
|
exports.usePaymentIntent = usePaymentIntent;
|