@riverbankcms/sdk 0.141.0 → 0.143.0
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/dist/{PreviewEditorSidebar-Q-fy9GYw.mjs → PreviewEditorSidebar-DROGfMKi.mjs} +24 -15
- package/dist/{PreviewEditorUI-LYGzgk85.mjs → PreviewEditorUI-BaRjhFu-.mjs} +3 -3
- package/dist/{PreviewQueryProvider-CN0ewic5.mjs → PreviewQueryProvider-BCYICImX.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-CoPYI5Jq.mjs → SdkPreviewModeRuntime-OIABYLES.mjs} +16 -11
- package/dist/{SiteChromeCustomizeContext-D8LePX8x.mjs → SiteChromeCustomizeContext-ohjTvZbc.mjs} +607 -545
- package/dist/_dts/api/src/billing.d.ts +6 -1
- package/dist/_dts/api/src/bookingConfig.d.ts +1 -1
- package/dist/_dts/api/src/commercePortalEndpoints.d.ts +2 -2
- package/dist/_dts/api/src/endpoints.d.ts +7 -27
- package/dist/_dts/api/src/index.d.ts +1 -1
- package/dist/_dts/api/src/publicBookingService.d.ts +1 -0
- package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
- package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +48 -41
- package/dist/_dts/api/src/sdkConfig/layout.d.ts +13 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +3 -8
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -31
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
- package/dist/_dts/billing/src/site-arrangements.d.ts +9 -5
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +56 -0
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +95 -35
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentStatusStep.d.ts +10 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +0 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +12 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationCompletion.d.ts +1 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.d.ts +4 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +9 -11
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +56 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +10 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/usePaymentStatusRecovery.d.ts +23 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +56 -0
- package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -4
- package/dist/_dts/commerce/src/purchase/eventCheckoutRecoveryWindow.d.ts +8 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +2 -1
- package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +1 -13
- package/dist/_dts/commerce/src/purchase/stripeCommissionMetadata.d.ts +1 -2
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +58 -45
- package/dist/_dts/editor-blocks/src/block-editor/ColourFieldOptionsProvider.d.ts +7 -0
- package/dist/_dts/editor-blocks/src/block-editor/colourFieldVisibility.d.ts +7 -0
- package/dist/_dts/editor-blocks/src/block-editor/preparedManifest.d.ts +2 -0
- package/dist/_dts/editor-blocks/src/index.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewFooterEditorPanel.d.ts +3 -6
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/preview/footerInspection.d.ts +16 -0
- package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +6 -0
- package/dist/_dts/sdk/src/config/types.d.ts +2 -18
- package/dist/_dts/sdk/src/config/validation.d.ts +6 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +3 -0
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/footer/mode.d.ts +10 -1
- package/dist/_dts/theme-core/src/schema.d.ts +1 -7
- package/dist/_dts/theme-core/src/site-styles/effectivePageDesign.d.ts +32 -0
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
- package/dist/client/{BookingConsentAgreement-xJeYNdnb.mjs → BookingConsentAgreement-BoCtvzzu.mjs} +2 -2
- package/dist/client/{DiscountCodeDisclosure-DdT6uzl9.mjs → DiscountCodeDisclosure-B5S30nZk.mjs} +1 -1
- package/dist/client/{EventCombined.client-Cp28uYuM.mjs → EventCombined.client-CeZ2-zSt.mjs} +5 -5
- package/dist/client/{EventListing.client-CD6AJsMr.mjs → EventListing.client-DJN3j8B3.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-DBsAi9-e.mjs → LeafletStaticMap-RjtGzDQT.mjs} +1 -1
- package/dist/client/{accordion-6dwbOKYR.mjs → accordion-DOmnDoyg.mjs} +1 -1
- package/dist/client/{bookingForm-CZE9_qPQ.mjs → bookingForm-C0vk7pgS.mjs} +5 -5
- package/dist/client/bookings.mjs +468 -534
- package/dist/client/{carousel-7VHGQARz.mjs → carousel-BZJ7pno3.mjs} +1 -1
- package/dist/client/{cart-Qg_mvQhh.mjs → cart-CaeVAHJl.mjs} +3 -3
- package/dist/client/{checkout-D84rpgdr.mjs → checkout-7wmoNDtG.mjs} +3 -3
- package/dist/client/client.mjs +559 -593
- package/dist/client/{context-Ctp3T0Wr.mjs → context-BOimxE3U.mjs} +12 -1
- package/dist/client/{dates-DJKFcI_N.mjs → dates-BnzVksi4.mjs} +2 -2
- package/dist/client/{eventCalendar-CK31z3vs.mjs → eventCalendar-l-fpaslC.mjs} +7 -7
- package/dist/client/{eventCombined-DiXd-ewn.mjs → eventCombined-DGGvssK6.mjs} +3 -3
- package/dist/client/{eventDetails-CTRgt2DK.mjs → eventDetails-DRiCm_hL.mjs} +4 -4
- package/dist/client/{eventListing-Dy9vi_j_.mjs → eventListing-dph8loYX.mjs} +3 -3
- package/dist/client/{eventRegistration-CnalYMr2.mjs → eventRegistration-ClBohmbY.mjs} +472 -531
- package/dist/client/{form-eUiMveTT.mjs → form-BLVVAnd3.mjs} +2 -2
- package/dist/client/{headerSection-Dy9kQpB1.mjs → headerSection-DHy4C8Ix.mjs} +2 -2
- package/dist/client/hooks.mjs +39 -13
- package/dist/client/{locationMap-DalCmWU0.mjs → locationMap-6HuS28ck.mjs} +2 -2
- package/dist/client/{newsletterForm-SDDPvhS0.mjs → newsletterForm-xOdcOhZP.mjs} +2 -2
- package/dist/client/{pricing-OcMz4SnX.mjs → pricing-ChinRYFt.mjs} +1 -1
- package/dist/client/{productDetail-BQrgHElM.mjs → productDetail-0chA5gbK.mjs} +3 -3
- package/dist/client/{productList-OnPn_UJj.mjs → productList-OoINA0h1.mjs} +3 -3
- package/dist/client/{propsDecoder-zBdsnS-N.mjs → propsDecoder-CIZ-hbIG.mjs} +33 -9
- package/dist/client/rendering/client.mjs +536 -550
- package/dist/client/rendering/islands.mjs +17 -17
- package/dist/client/rendering.mjs +602 -596
- package/dist/client/{scrollToBlock-BNM4Ob2Y.mjs → scrollToBlock-BPZl0gPZ.mjs} +1 -1
- package/dist/client/{shop-Bv1fPTwQ.mjs → shop-CLJFqNIq.mjs} +6 -6
- package/dist/client/{shop-commerce-D4KNGaW8.mjs → shop-commerce-PpANg5wB.mjs} +5 -5
- package/dist/client/{shop-commerce-store-2N5EV0Rc.mjs → shop-commerce-store-TA_Kz2ku.mjs} +1 -1
- package/dist/client/{shopShared-DvJGdHTV.mjs → shopShared-DzcFcA5g.mjs} +3 -3
- package/dist/client/{useEventFilters-BBBvGDHQ.mjs → useEventFilters-CFU21QZo.mjs} +5 -5
- package/dist/preview-next/before-render.mjs +11 -37
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/keepAlive.mjs +11 -37
- package/dist/preview-next/middleware.mjs +11 -37
- package/dist/{previewAuthStore-Gjb6r6vz.mjs → previewAuthStore-JA6-I_sL.mjs} +11 -37
- package/dist/{sdk-runtime-Defnbfzw.mjs → sdk-runtime-CDKl0Fr7.mjs} +2 -2
- package/dist/{separator-CZXO3Sb0.mjs → separator-BTp96X32.mjs} +1 -1
- package/dist/server/components.mjs +80 -51
- package/dist/server/config-validation.mjs +43 -14
- package/dist/server/config.mjs +43 -14
- package/dist/server/data.mjs +39 -13
- package/dist/server/index.mjs +12 -38
- package/dist/server/next.mjs +40 -53
- package/dist/server/page-converter.mjs +20 -8
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +80 -51
- package/dist/server/rendering.mjs +80 -51
- package/dist/server/routing.mjs +52 -17
- package/dist/server/server.mjs +40 -51
- package/dist/server/theme-bridge.mjs +10 -8
- package/dist/server/theme.mjs +10 -8
- package/package.json +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +0 -14
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +0 -8
package/dist/client/bookings.mjs
CHANGED
|
@@ -3114,6 +3114,14 @@ function orderedLiveRunSessions(sessions) {
|
|
|
3114
3114
|
return sessions.filter((session) => session.status !== "cancelled" && Number.isFinite(sessionStartMs(session))).sort((left, right) => sessionStartMs(left) - sessionStartMs(right));
|
|
3115
3115
|
}
|
|
3116
3116
|
//#endregion
|
|
3117
|
+
//#region ../theme-core/src/footer/mode.ts
|
|
3118
|
+
const footerModeSchema = z.enum([
|
|
3119
|
+
"default",
|
|
3120
|
+
"blocks",
|
|
3121
|
+
"default+blocks",
|
|
3122
|
+
"none"
|
|
3123
|
+
]);
|
|
3124
|
+
//#endregion
|
|
3117
3125
|
//#region ../theme-core/src/lib/media.ts
|
|
3118
3126
|
const hotspotSchema = z.object({
|
|
3119
3127
|
x: z.number().min(0).max(1),
|
|
@@ -7447,12 +7455,6 @@ const footerVariant = z.enum([
|
|
|
7447
7455
|
"split"
|
|
7448
7456
|
]);
|
|
7449
7457
|
const footerMaxWidth = z.enum(["container", "full"]);
|
|
7450
|
-
const footerMode = z.enum([
|
|
7451
|
-
"default",
|
|
7452
|
-
"blocks",
|
|
7453
|
-
"default+blocks",
|
|
7454
|
-
"none"
|
|
7455
|
-
]);
|
|
7456
7458
|
const footerNavLayoutMode = z.enum([
|
|
7457
7459
|
"stack",
|
|
7458
7460
|
"inline",
|
|
@@ -7541,9 +7543,9 @@ const footerSchema = z.object({
|
|
|
7541
7543
|
/**
|
|
7542
7544
|
* SDK-only footer rendering mode.
|
|
7543
7545
|
*
|
|
7544
|
-
*
|
|
7546
|
+
* Historical persisted field; SDK rendering mode now lives in layout.footerMode.
|
|
7545
7547
|
*/
|
|
7546
|
-
mode:
|
|
7548
|
+
mode: footerModeSchema.optional(),
|
|
7547
7549
|
variant: footerVariant,
|
|
7548
7550
|
maxWidth: footerMaxWidth,
|
|
7549
7551
|
showLogoText: z.boolean().optional(),
|
|
@@ -8125,6 +8127,15 @@ const publicEventBaseSchema = z.object({
|
|
|
8125
8127
|
timeZone: z.string(),
|
|
8126
8128
|
pricing: publicEventPricingSchema,
|
|
8127
8129
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
8130
|
+
cancellationPolicy: z.object({ refunds: z.object({
|
|
8131
|
+
mode: z.enum([
|
|
8132
|
+
"never",
|
|
8133
|
+
"always",
|
|
8134
|
+
"cutoff"
|
|
8135
|
+
]),
|
|
8136
|
+
cutoffHours: z.number(),
|
|
8137
|
+
method: z.enum(["original_payment_method", "site_credit"])
|
|
8138
|
+
}) }),
|
|
8128
8139
|
consent: blockBookingConsentSchema.nullable(),
|
|
8129
8140
|
accessRestriction: accessRestrictionSchema,
|
|
8130
8141
|
allowedCategoryIds: z.array(z.string()),
|
|
@@ -8349,6 +8360,10 @@ const EVENTS = {
|
|
|
8349
8360
|
method: "POST",
|
|
8350
8361
|
authScope: "portal"
|
|
8351
8362
|
},
|
|
8363
|
+
registrationNextStep: {
|
|
8364
|
+
path: "/public/sites/{siteId}/events/registration-next-step",
|
|
8365
|
+
method: "POST"
|
|
8366
|
+
},
|
|
8352
8367
|
registrationStatus: {
|
|
8353
8368
|
path: "/public/sites/{siteId}/events/registration-status",
|
|
8354
8369
|
method: "GET"
|
|
@@ -8953,6 +8968,13 @@ function createBlockApi(config) {
|
|
|
8953
8968
|
body: data
|
|
8954
8969
|
});
|
|
8955
8970
|
},
|
|
8971
|
+
async checkRegistrationNextStep(data) {
|
|
8972
|
+
const path = buildPath(EVENTS.registrationNextStep.path, { siteId: requireSiteId() });
|
|
8973
|
+
return request(EVENTS.registrationNextStep, {
|
|
8974
|
+
path,
|
|
8975
|
+
body: data
|
|
8976
|
+
});
|
|
8977
|
+
},
|
|
8956
8978
|
async getEventRegistrationStatus(params) {
|
|
8957
8979
|
const sid = requireSiteId();
|
|
8958
8980
|
const path = buildPath(EVENTS.registrationStatus.path, { siteId: sid });
|
|
@@ -14900,188 +14922,15 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
14900
14922
|
});
|
|
14901
14923
|
};
|
|
14902
14924
|
//#endregion
|
|
14903
|
-
//#region ../blocks/src/system/runtime/nodes/events/domain/capacity.ts
|
|
14904
|
-
/**
|
|
14905
|
-
* Compute remaining spots for an event from `availableSpots` with a fallback
|
|
14906
|
-
* to `capacity - registeredCount`. Returns `{ available: null, isFull: false }`
|
|
14907
|
-
* for uncapped events so call sites can render no capacity indicator at all.
|
|
14908
|
-
*
|
|
14909
|
-
* The single source of truth for capacity math across event cards, agenda
|
|
14910
|
-
* rows, and timetable cells — keep wording variations in the call sites.
|
|
14911
|
-
*/
|
|
14912
|
-
function getEventAvailability(event) {
|
|
14913
|
-
if (event.capacity == null) return {
|
|
14914
|
-
available: null,
|
|
14915
|
-
isFull: false
|
|
14916
|
-
};
|
|
14917
|
-
const available = event.availableSpots ?? event.capacity - event.registeredCount;
|
|
14918
|
-
if (available <= 0) return {
|
|
14919
|
-
available: 0,
|
|
14920
|
-
isFull: true
|
|
14921
|
-
};
|
|
14922
|
-
return {
|
|
14923
|
-
available,
|
|
14924
|
-
isFull: false
|
|
14925
|
-
};
|
|
14926
|
-
}
|
|
14927
|
-
/**
|
|
14928
|
-
* Pick the capacity row a booking decision should read: the selected
|
|
14929
|
-
* attendance mode's availability when the visitor has chosen one and the
|
|
14930
|
-
* event publishes it, otherwise the event-level aggregate.
|
|
14931
|
-
*
|
|
14932
|
-
* The mode row is used wholesale. A mode with `capacity: null` on a capped
|
|
14933
|
-
* event is uncapped *by design*: the registration write path applies the
|
|
14934
|
-
* same rule via `getEffectiveOccurrenceCapacityForAttendanceMode`, so falling
|
|
14935
|
-
* back to the event's `availableSpots` here would block bookings the server
|
|
14936
|
-
* accepts. (Waitlist claims are still occurrence-scoped; see issue 1377.)
|
|
14937
|
-
*/
|
|
14938
|
-
function selectEventCapacitySource(event, attendanceMode) {
|
|
14939
|
-
if (!attendanceMode) return event;
|
|
14940
|
-
return (event.attendanceModes ?? []).find((mode) => mode.mode === attendanceMode) ?? event;
|
|
14941
|
-
}
|
|
14942
|
-
/**
|
|
14943
|
-
* Whether the visitor's next step is the waitlist: the source is full *and*
|
|
14944
|
-
* a waitlist is open. The one place this is decided — cards, rows, the
|
|
14945
|
-
* wizard's steps and its action bar all route through here so they agree,
|
|
14946
|
-
* including for producers that omit `availableSpots` and rely on the
|
|
14947
|
-
* `capacity - registeredCount` fallback.
|
|
14948
|
-
*/
|
|
14949
|
-
function canJoinEventWaitlist(event, options) {
|
|
14950
|
-
const source = selectEventCapacitySource(event, options?.attendanceMode);
|
|
14951
|
-
return getEventAvailability(source).isFull && source.waitlistEnabled === true;
|
|
14952
|
-
}
|
|
14953
|
-
//#endregion
|
|
14954
|
-
//#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
|
|
14955
|
-
function isRecord$1(value) {
|
|
14956
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14957
|
-
}
|
|
14958
|
-
function isRuntimeEventDestination(value) {
|
|
14959
|
-
if (!isRecord$1(value) || typeof value.kind !== "string") return false;
|
|
14960
|
-
if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
|
|
14961
|
-
return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
|
|
14962
|
-
}
|
|
14963
|
-
function resolveRuntimeEventDestination(event) {
|
|
14964
|
-
if (isRuntimeEventDestination(event.destination)) return event.destination;
|
|
14965
|
-
return {
|
|
14966
|
-
kind: "native",
|
|
14967
|
-
mode: event.eventDestinationMode === "system-managed" ? "system-managed" : "cms-managed",
|
|
14968
|
-
path: typeof event.path === "string" ? event.path : ""
|
|
14969
|
-
};
|
|
14970
|
-
}
|
|
14971
|
-
//#endregion
|
|
14972
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.ts
|
|
14973
|
-
/** Recovery may select held places; checkout still owns admission and payment validation. */
|
|
14974
|
-
function checkoutRecoveryOptionAvailability(availability) {
|
|
14975
|
-
if (availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable") return {
|
|
14976
|
-
kind: "available",
|
|
14977
|
-
remainingPlaces: null
|
|
14978
|
-
};
|
|
14979
|
-
return availability;
|
|
14980
|
-
}
|
|
14981
|
-
/**
|
|
14982
|
-
* A form-only projection for the explicit existing-checkout path. It permits
|
|
14983
|
-
* collecting the original selection without claiming a new place is available.
|
|
14984
|
-
* The public checkout service identifies the customer and remains the admission
|
|
14985
|
-
* authority; no reservation/customer data is exposed through this projection.
|
|
14986
|
-
*/
|
|
14987
|
-
function getCheckoutRecoveryFormEligibility(eligibility) {
|
|
14988
|
-
if (!eligibility || eligibility.registration.kind !== "none" && eligibility.registration.kind !== "pending_payment" || eligibility.availability.kind === "unavailable" && eligibility.availability.reason !== "full" && eligibility.availability.reason !== "selectionRequired") return eligibility;
|
|
14989
|
-
const amountCents = eligibility.price ?? 0;
|
|
14990
|
-
if (amountCents <= 0 || !eligibility.currency || eligibility.availability.kind === "unavailable" && eligibility.availability.reason === "selectionRequired") return eligibility.registration.kind === "pending_payment" ? {
|
|
14991
|
-
...eligibility,
|
|
14992
|
-
registration: { kind: "none" },
|
|
14993
|
-
ticketTypes: eligibility.ticketTypes.map((option) => ({
|
|
14994
|
-
...option,
|
|
14995
|
-
availability: checkoutRecoveryOptionAvailability(option.availability)
|
|
14996
|
-
}))
|
|
14997
|
-
} : eligibility;
|
|
14998
|
-
const currency = eligibility.currency;
|
|
14999
|
-
const paymentOptions = eligibility.paymentTerms.allowedOptions.map((option) => {
|
|
15000
|
-
switch (option.kind) {
|
|
15001
|
-
case "upfront": return {
|
|
15002
|
-
kind: "payInFull",
|
|
15003
|
-
amountCents,
|
|
15004
|
-
currency
|
|
15005
|
-
};
|
|
15006
|
-
case "deferred_manual": return {
|
|
15007
|
-
kind: "deferredManual",
|
|
15008
|
-
amountCents,
|
|
15009
|
-
currency
|
|
15010
|
-
};
|
|
15011
|
-
case "instalment_plan": return {
|
|
15012
|
-
kind: "instalmentPlan",
|
|
15013
|
-
amountCents,
|
|
15014
|
-
currency
|
|
15015
|
-
};
|
|
15016
|
-
case "flexible_balance": return {
|
|
15017
|
-
kind: "flexibleBalance",
|
|
15018
|
-
amountCents,
|
|
15019
|
-
currency
|
|
15020
|
-
};
|
|
15021
|
-
}
|
|
15022
|
-
});
|
|
15023
|
-
return {
|
|
15024
|
-
...eligibility,
|
|
15025
|
-
registration: { kind: "none" },
|
|
15026
|
-
availability: {
|
|
15027
|
-
kind: "available",
|
|
15028
|
-
remainingPlaces: null,
|
|
15029
|
-
waitlistEnabled: eligibility.waitlistEnabled
|
|
15030
|
-
},
|
|
15031
|
-
eligible: paymentOptions.length > 0,
|
|
15032
|
-
isFull: false,
|
|
15033
|
-
canJoinWaitlist: false,
|
|
15034
|
-
isFree: false,
|
|
15035
|
-
requiresPayment: true,
|
|
15036
|
-
canPayDirectly: paymentOptions.length > 0,
|
|
15037
|
-
paymentOptions,
|
|
15038
|
-
eligiblePasses: [],
|
|
15039
|
-
eligibleMemberships: [],
|
|
15040
|
-
ticketTypes: eligibility.ticketTypes.map((option) => ({
|
|
15041
|
-
...option,
|
|
15042
|
-
availability: checkoutRecoveryOptionAvailability(option.availability)
|
|
15043
|
-
}))
|
|
15044
|
-
};
|
|
15045
|
-
}
|
|
15046
|
-
function canJoinWaitlistOutsideRecovery(event, attendanceMode, checkoutRecovery) {
|
|
15047
|
-
return !checkoutRecovery && event !== null && canJoinEventWaitlist(event, { attendanceMode });
|
|
15048
|
-
}
|
|
15049
|
-
//#endregion
|
|
15050
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.ts
|
|
15051
|
-
/** Recovery belongs to the selected booking subject; changing events resets its scope. */
|
|
15052
|
-
function useCheckoutRecovery(event, setStep) {
|
|
15053
|
-
const [recoveryEventId, setRecoveryEventId] = useState(null);
|
|
15054
|
-
return {
|
|
15055
|
-
checkoutRecovery: event !== null && recoveryEventId === event.selectionId,
|
|
15056
|
-
startCheckoutRecovery: useCallback(() => {
|
|
15057
|
-
if (!event) return;
|
|
15058
|
-
setRecoveryEventId(event.selectionId);
|
|
15059
|
-
setStep("select-tickets");
|
|
15060
|
-
}, [event, setStep])
|
|
15061
|
-
};
|
|
15062
|
-
}
|
|
15063
|
-
/** Authenticated pending bookings enter the same form-only recovery path as guests. */
|
|
15064
|
-
function useCheckoutRecoveryEligibility(eligibility, step, checkoutRecovery, startCheckoutRecovery) {
|
|
15065
|
-
const registrationKind = eligibility?.registration.kind;
|
|
15066
|
-
useEffect(() => {
|
|
15067
|
-
if ((step === "select-event" || step === "select-tickets" || step === "enter-details" || step === "select-payment") && registrationKind === "pending_payment" && !checkoutRecovery) startCheckoutRecovery();
|
|
15068
|
-
}, [
|
|
15069
|
-
registrationKind,
|
|
15070
|
-
step,
|
|
15071
|
-
checkoutRecovery,
|
|
15072
|
-
startCheckoutRecovery
|
|
15073
|
-
]);
|
|
15074
|
-
return useMemo(() => checkoutRecovery ? getCheckoutRecoveryFormEligibility(eligibility) : eligibility, [checkoutRecovery, eligibility]);
|
|
15075
|
-
}
|
|
15076
|
-
//#endregion
|
|
15077
14925
|
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.ts
|
|
15078
14926
|
function resolveRegistrationRecoveryAction(step, action) {
|
|
15079
14927
|
if (step === "payment-failed") return "payment-options";
|
|
15080
|
-
if (step === "
|
|
14928
|
+
if (step === "payment-status") return "none";
|
|
14929
|
+
if (step === "verifying-payment" || step === "verifying-timeout" || step === "redirecting") return "none";
|
|
15081
14930
|
return action;
|
|
15082
14931
|
}
|
|
15083
14932
|
function canRecoverToWaitlist(eligibility) {
|
|
15084
|
-
return
|
|
14933
|
+
return eligibility?.availability.kind === "waitlist" && eligibility.registration.kind !== "pending_payment";
|
|
15085
14934
|
}
|
|
15086
14935
|
function shouldRefreshAfterRegistrationError(step, action, enabled) {
|
|
15087
14936
|
return enabled || step === "error" && action === "places";
|
|
@@ -15098,19 +14947,19 @@ function resetRegistrationAfterExpiry(input) {
|
|
|
15098
14947
|
input.setErrorMessage("");
|
|
15099
14948
|
input.setPendingRegistrationReference(null);
|
|
15100
14949
|
}
|
|
15101
|
-
/**
|
|
14950
|
+
/** Retry the retained submission in place; explicit payment uncertainty stays status-only. */
|
|
15102
14951
|
function recoverRegistrationError(action, handlers) {
|
|
15103
14952
|
switch (action) {
|
|
15104
14953
|
case "none": return;
|
|
15105
14954
|
case "portal":
|
|
15106
|
-
case "payment-status":
|
|
15107
14955
|
window.location.assign("/portal");
|
|
15108
14956
|
return;
|
|
15109
14957
|
case "event":
|
|
15110
14958
|
window.location.assign(window.location.pathname);
|
|
15111
14959
|
return;
|
|
15112
14960
|
case "retry":
|
|
15113
|
-
|
|
14961
|
+
handlers.clearError();
|
|
14962
|
+
handlers.setStep("select-payment");
|
|
15114
14963
|
return;
|
|
15115
14964
|
case "details":
|
|
15116
14965
|
handlers.clearError();
|
|
@@ -15148,13 +14997,43 @@ function validateFormData(formData, requiresConsent = false) {
|
|
|
15148
14997
|
return errors;
|
|
15149
14998
|
}
|
|
15150
14999
|
//#endregion
|
|
15000
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
|
|
15001
|
+
/** Ticket selection requests a quote; only the server admits a booking. */
|
|
15002
|
+
function canRequestTicketOption(availability) {
|
|
15003
|
+
return availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable";
|
|
15004
|
+
}
|
|
15005
|
+
function normalizeTicketSelectionLines(lines) {
|
|
15006
|
+
const quantitiesByTicketType = /* @__PURE__ */ new Map();
|
|
15007
|
+
for (const line of lines) {
|
|
15008
|
+
const quantity = Math.floor(line.quantity);
|
|
15009
|
+
if (quantity <= 0) continue;
|
|
15010
|
+
const key = line.pricingOptionId ?? null;
|
|
15011
|
+
quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
|
|
15012
|
+
}
|
|
15013
|
+
return [...quantitiesByTicketType.entries()].map(([pricingOptionId, quantity]) => ({
|
|
15014
|
+
pricingOptionId,
|
|
15015
|
+
quantity
|
|
15016
|
+
}));
|
|
15017
|
+
}
|
|
15018
|
+
function getTicketSelectionTotal(lines) {
|
|
15019
|
+
return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
|
|
15020
|
+
}
|
|
15021
|
+
function getSingleSelectedPricingOptionId(lines) {
|
|
15022
|
+
const normalized = normalizeTicketSelectionLines(lines);
|
|
15023
|
+
return normalized.length === 1 ? normalized[0]?.pricingOptionId ?? null : null;
|
|
15024
|
+
}
|
|
15025
|
+
function hasValidPricingOptionSelection(input) {
|
|
15026
|
+
if (!input.selectionRequired) return true;
|
|
15027
|
+
if (input.lines.length === 0) return false;
|
|
15028
|
+
const availableOptionIds = new Set(input.visibleOptions.filter((option) => canRequestTicketOption(option.availability)).map((option) => option.pricingOptionId));
|
|
15029
|
+
return input.lines.every((line) => line.pricingOptionId !== null && availableOptionIds.has(line.pricingOptionId));
|
|
15030
|
+
}
|
|
15031
|
+
//#endregion
|
|
15151
15032
|
//#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
|
|
15152
15033
|
function getPortalSubjectEmail(profile) {
|
|
15153
15034
|
return profile?.email ?? null;
|
|
15154
15035
|
}
|
|
15155
15036
|
function transformRegistrationOptionsResponse(response) {
|
|
15156
|
-
const canJoinWaitlist = response.availability.kind === "waitlist";
|
|
15157
|
-
const isFull = response.availability.remainingPlaces === 0 || response.availability.kind === "unavailable" && response.availability.reason === "full";
|
|
15158
15037
|
const eligiblePasses = response.entitlements.passes.map((pass) => ({
|
|
15159
15038
|
id: pass.customerPassId,
|
|
15160
15039
|
passName: pass.passName,
|
|
@@ -15167,7 +15046,6 @@ function transformRegistrationOptionsResponse(response) {
|
|
|
15167
15046
|
const eventAcceptsPasses = response.entitlements.requiresLoginForPasses || eligiblePasses.length > 0 || response.entitlements.availableForPurchase.passes.length > 0;
|
|
15168
15047
|
const eventAcceptsMemberships = response.entitlements.requiresLoginForMemberships || eligibleMemberships.length > 0 || response.entitlements.availableForPurchase.memberships.length > 0;
|
|
15169
15048
|
const monetaryPaymentAvailable = hasMonetaryPaymentOption(response);
|
|
15170
|
-
const registrationAvailable = response.availability.kind === "available" || response.availability.kind === "waitlist";
|
|
15171
15049
|
return {
|
|
15172
15050
|
availability: response.availability,
|
|
15173
15051
|
registration: response.registration,
|
|
@@ -15182,7 +15060,6 @@ function transformRegistrationOptionsResponse(response) {
|
|
|
15182
15060
|
},
|
|
15183
15061
|
transactions: []
|
|
15184
15062
|
} : null,
|
|
15185
|
-
eligible: response.registration.kind === "none" && registrationAvailable,
|
|
15186
15063
|
requiresPayment: monetaryPaymentAvailable,
|
|
15187
15064
|
pricingStrategy: response.pricing.strategy,
|
|
15188
15065
|
paymentTerms: response.pricing.paymentTerms,
|
|
@@ -15197,16 +15074,12 @@ function transformRegistrationOptionsResponse(response) {
|
|
|
15197
15074
|
currency: response.pricing.currency
|
|
15198
15075
|
})),
|
|
15199
15076
|
ticketTypes: response.pricing.options,
|
|
15200
|
-
isFull,
|
|
15201
|
-
waitlistEnabled: response.availability.waitlistEnabled,
|
|
15202
|
-
canJoinWaitlist,
|
|
15203
15077
|
price: response.pricing.subtotalCents,
|
|
15204
15078
|
currency: response.pricing.currency,
|
|
15205
15079
|
requiresAuthForPasses: response.entitlements.requiresLoginForPasses,
|
|
15206
15080
|
requiresAuthForMemberships: response.entitlements.requiresLoginForMemberships,
|
|
15207
15081
|
eligiblePasses,
|
|
15208
15082
|
eligibleMemberships,
|
|
15209
|
-
canPayDirectly: monetaryPaymentAvailable,
|
|
15210
15083
|
eventAcceptsPasses,
|
|
15211
15084
|
eventAcceptsMemberships,
|
|
15212
15085
|
availablePasses: [...response.entitlements.availableForPurchase.passes],
|
|
@@ -15223,8 +15096,8 @@ function getVisibleTicketTypes(input) {
|
|
|
15223
15096
|
})) : [];
|
|
15224
15097
|
return (input.eligibility?.ticketTypes ?? eventTicketTypes).filter((ticketType) => ticketType.isActive && (!input.selectedAttendanceMode || (ticketType.attendanceScope ?? "both") === "both" || (ticketType.attendanceScope ?? "both") === input.selectedAttendanceMode));
|
|
15225
15098
|
}
|
|
15226
|
-
function
|
|
15227
|
-
return ticketTypes.length === 1 && ticketTypes[0]
|
|
15099
|
+
function getImplicitSingleTicketType(ticketTypes) {
|
|
15100
|
+
return ticketTypes.length === 1 && ticketTypes[0] && canRequestTicketOption(ticketTypes[0].availability) ? ticketTypes[0] : null;
|
|
15228
15101
|
}
|
|
15229
15102
|
function findSelectedTicketType(input) {
|
|
15230
15103
|
if (!input.selectedPricingOptionId) return null;
|
|
@@ -15235,32 +15108,74 @@ function findSelectedTicketType(input) {
|
|
|
15235
15108
|
}).find((ticketType) => ticketType.pricingOptionId === input.selectedPricingOptionId) ?? null;
|
|
15236
15109
|
}
|
|
15237
15110
|
//#endregion
|
|
15238
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15111
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
|
|
15112
|
+
/** Public requests share subject identity without copying the run's display sessions. */
|
|
15113
|
+
function toRegistrationRequestSubject(subject, attendanceMode) {
|
|
15114
|
+
return subject.kind === "occurrence" ? {
|
|
15115
|
+
kind: "occurrence",
|
|
15116
|
+
occurrenceId: subject.occurrenceId,
|
|
15117
|
+
attendanceMode: attendanceMode ?? void 0
|
|
15118
|
+
} : {
|
|
15119
|
+
kind: "wholeSeries",
|
|
15120
|
+
eventSeriesId: subject.eventSeriesId,
|
|
15121
|
+
attendanceMode: attendanceMode ?? void 0
|
|
15122
|
+
};
|
|
15123
|
+
}
|
|
15124
|
+
function eventMatchesOccurrenceId(event, occurrenceId) {
|
|
15125
|
+
return event.registrationSubject.kind === "occurrence" && (event.registrationSubject.occurrenceId === occurrenceId || event.selectionId === occurrenceId);
|
|
15126
|
+
}
|
|
15127
|
+
function findEventByOccurrenceId(events, occurrenceId) {
|
|
15128
|
+
return events.find((event) => eventMatchesOccurrenceId(event, occurrenceId)) ?? null;
|
|
15129
|
+
}
|
|
15130
|
+
function findPreSelectedEvent(input) {
|
|
15131
|
+
const occurrenceContext = input.occurrenceContext;
|
|
15132
|
+
if (!occurrenceContext) return input.scopedEvents.length === 1 ? input.scopedEvents[0] ?? null : null;
|
|
15133
|
+
const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
15134
|
+
startsAt: occurrenceContext.startsAt,
|
|
15135
|
+
timeZone: occurrenceContext.timeZone
|
|
15250
15136
|
}));
|
|
15137
|
+
return input.scopedEvents.find((event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
15138
|
+
startsAt: event.startsAt,
|
|
15139
|
+
timeZone: event.timeZone
|
|
15140
|
+
})) === contextDate) ?? null;
|
|
15251
15141
|
}
|
|
15252
|
-
function
|
|
15253
|
-
|
|
15142
|
+
function resolveRegistrationTarget(input) {
|
|
15143
|
+
const subject = input.occurrenceContext ? {
|
|
15144
|
+
kind: "occurrence",
|
|
15145
|
+
occurrenceId: input.occurrenceContext.id
|
|
15146
|
+
} : input.selectedEvent?.registrationSubject ?? null;
|
|
15147
|
+
if (!subject) return null;
|
|
15148
|
+
return {
|
|
15149
|
+
subject,
|
|
15150
|
+
selectedEventId: input.selectedEvent?.selectionId ?? null
|
|
15151
|
+
};
|
|
15254
15152
|
}
|
|
15255
|
-
function
|
|
15256
|
-
|
|
15257
|
-
|
|
15153
|
+
function resolveEventRequiresPayment(input) {
|
|
15154
|
+
if (input.eligibility) return input.eligibility.requiresPayment;
|
|
15155
|
+
if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
|
|
15156
|
+
if (!input.event) return false;
|
|
15157
|
+
return publicEventPricingType(input.event.pricing) === "paid";
|
|
15258
15158
|
}
|
|
15259
|
-
function
|
|
15260
|
-
|
|
15261
|
-
if (input.
|
|
15262
|
-
|
|
15263
|
-
|
|
15159
|
+
function resolveDiscountContext(input) {
|
|
15160
|
+
const selection = input.paymentSelection.method ? input.paymentSelection : null;
|
|
15161
|
+
if (!input.event) return null;
|
|
15162
|
+
if (selection?.method === "pass_bundle" && selection.bundlePassId) return {
|
|
15163
|
+
type: "pass",
|
|
15164
|
+
passId: selection.bundlePassId
|
|
15165
|
+
};
|
|
15166
|
+
if (selection?.method === "membership_bundle" && selection.bundleMembershipId) return {
|
|
15167
|
+
type: "membership",
|
|
15168
|
+
membershipId: selection.bundleMembershipId
|
|
15169
|
+
};
|
|
15170
|
+
if (!input.eventRequiresPayment) return null;
|
|
15171
|
+
if (input.ticketsCount <= 0) return null;
|
|
15172
|
+
if (selection?.method && selection.method !== "stripe") return null;
|
|
15173
|
+
return {
|
|
15174
|
+
type: "event",
|
|
15175
|
+
eventSeriesId: input.event.seriesId,
|
|
15176
|
+
eventCategoryId: input.event.eventCategory?.id ?? null,
|
|
15177
|
+
ticketsCount: input.ticketsCount
|
|
15178
|
+
};
|
|
15264
15179
|
}
|
|
15265
15180
|
//#endregion
|
|
15266
15181
|
//#region ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
|
|
@@ -15380,17 +15295,6 @@ function usePortalAuthWithDeps(deps) {
|
|
|
15380
15295
|
logout
|
|
15381
15296
|
};
|
|
15382
15297
|
}
|
|
15383
|
-
function toRegistrationOptionsSubject(subject, attendanceMode) {
|
|
15384
|
-
return subject.kind === "occurrence" ? {
|
|
15385
|
-
kind: "occurrence",
|
|
15386
|
-
occurrenceId: subject.occurrenceId,
|
|
15387
|
-
attendanceMode: attendanceMode ?? void 0
|
|
15388
|
-
} : {
|
|
15389
|
-
kind: "wholeSeries",
|
|
15390
|
-
eventSeriesId: subject.eventSeriesId,
|
|
15391
|
-
attendanceMode: attendanceMode ?? void 0
|
|
15392
|
-
};
|
|
15393
|
-
}
|
|
15394
15298
|
function useEligibility(params) {
|
|
15395
15299
|
return useEligibilityWithDeps(params, eventRegistrationHooksDeps);
|
|
15396
15300
|
}
|
|
@@ -15431,7 +15335,7 @@ function useEligibilityWithDeps(params, deps) {
|
|
|
15431
15335
|
requestIdRef.current = requestId;
|
|
15432
15336
|
dispatch({ type: "loading-started" });
|
|
15433
15337
|
try {
|
|
15434
|
-
const subject =
|
|
15338
|
+
const subject = toRegistrationRequestSubject(params.subject, params.attendanceMode);
|
|
15435
15339
|
const result = await api.getRegistrationOptions({
|
|
15436
15340
|
subject,
|
|
15437
15341
|
selections: ticketSelections.map((selection) => ({
|
|
@@ -15635,7 +15539,6 @@ const STRIPE_COMMISSION_FREE_REASONS = [
|
|
|
15635
15539
|
"no_commission_plan",
|
|
15636
15540
|
"billing_evidence_invalid",
|
|
15637
15541
|
"fee_rounds_to_zero",
|
|
15638
|
-
"non_commissionable_scope",
|
|
15639
15542
|
"payment_not_stripe"
|
|
15640
15543
|
];
|
|
15641
15544
|
const historicalContext = {
|
|
@@ -15669,9 +15572,9 @@ const eventRegistrationErrors = {
|
|
|
15669
15572
|
message: "Booking is currently closed for this event. Please contact the organiser if you’d like to find out more.",
|
|
15670
15573
|
action: "none"
|
|
15671
15574
|
},
|
|
15672
|
-
|
|
15673
|
-
message: "We’
|
|
15674
|
-
action: "
|
|
15575
|
+
paymentInvestigationRequired: {
|
|
15576
|
+
message: "We still can’t confirm your payment. Please don’t make another payment. Contact the organiser so they can check your booking.",
|
|
15577
|
+
action: "none"
|
|
15675
15578
|
},
|
|
15676
15579
|
paymentProviderUnavailable: {
|
|
15677
15580
|
message: "We couldn’t reach the payment provider. Please try again in a minute.",
|
|
@@ -16169,7 +16072,30 @@ function checkoutReturnCommand(params) {
|
|
|
16169
16072
|
};
|
|
16170
16073
|
return null;
|
|
16171
16074
|
}
|
|
16172
|
-
|
|
16075
|
+
function handleCheckoutReturnOutcome(options, deps, context, outcome) {
|
|
16076
|
+
const { pending, params } = context;
|
|
16077
|
+
if (outcome.kind === "resolved") {
|
|
16078
|
+
deps.clearReturnParams();
|
|
16079
|
+
options.setPendingRegistrationReference(outcome.reference);
|
|
16080
|
+
options.setStep("verifying-payment");
|
|
16081
|
+
return "settled";
|
|
16082
|
+
}
|
|
16083
|
+
if (outcome.kind === "abandoned") {
|
|
16084
|
+
deps.clearReturnParams();
|
|
16085
|
+
options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
|
|
16086
|
+
options.setStep("select-payment");
|
|
16087
|
+
return "settled";
|
|
16088
|
+
}
|
|
16089
|
+
if (outcome.kind === "notFound" && params.registration === "cancelled" && (options.registrationSubject?.kind === "occurrence" || pending?.reference.scope === "occurrence")) {
|
|
16090
|
+
deps.clearReturnParams();
|
|
16091
|
+
options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
|
|
16092
|
+
options.setStep("select-payment");
|
|
16093
|
+
return "settled";
|
|
16094
|
+
}
|
|
16095
|
+
showReturnReconciliation(options, "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.");
|
|
16096
|
+
return outcome.kind === "notFound" ? "settled" : "retryable";
|
|
16097
|
+
}
|
|
16098
|
+
async function handleCheckoutReturn(options, deps, returnContextRef) {
|
|
16173
16099
|
deps.cleanupStaleRegistrations();
|
|
16174
16100
|
const params = deps.readReturnParams();
|
|
16175
16101
|
if (params.registration !== "cancelled" && params.registration !== "success") return "settled";
|
|
@@ -16183,34 +16109,15 @@ async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
|
|
|
16183
16109
|
}
|
|
16184
16110
|
const { checkoutAttemptId } = command;
|
|
16185
16111
|
const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
|
|
16186
|
-
|
|
16112
|
+
returnContextRef.current = { checkoutAttemptId };
|
|
16187
16113
|
if (pending) restorePendingPresentation(options, pending);
|
|
16188
16114
|
options.setStep("verifying-payment");
|
|
16189
16115
|
try {
|
|
16190
16116
|
const outcome = await options.api.resolveEventCheckoutReturn(command);
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
options.setStep("verifying-payment");
|
|
16196
|
-
return "settled";
|
|
16197
|
-
case "abandoned":
|
|
16198
|
-
deps.clearReturnParams();
|
|
16199
|
-
options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
|
|
16200
|
-
options.setStep("select-payment");
|
|
16201
|
-
return "settled";
|
|
16202
|
-
case "notFound":
|
|
16203
|
-
if (params.registration === "cancelled" && (options.registrationSubject?.kind === "occurrence" || pending?.reference.scope === "occurrence")) {
|
|
16204
|
-
deps.clearReturnParams();
|
|
16205
|
-
options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
|
|
16206
|
-
options.setStep("select-payment");
|
|
16207
|
-
return "settled";
|
|
16208
|
-
}
|
|
16209
|
-
showReturnReconciliation(options, "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.");
|
|
16210
|
-
return "settled";
|
|
16211
|
-
case "reconciliationRequired": break;
|
|
16212
|
-
}
|
|
16213
|
-
showReturnReconciliation(options, "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.");
|
|
16117
|
+
return handleCheckoutReturnOutcome(options, deps, {
|
|
16118
|
+
pending,
|
|
16119
|
+
params
|
|
16120
|
+
}, outcome);
|
|
16214
16121
|
} catch {
|
|
16215
16122
|
showReturnReconciliation(options, "We couldn’t check your payment just now. Please check again in a moment. Don’t make another booking while we’re checking.");
|
|
16216
16123
|
}
|
|
@@ -16219,9 +16126,16 @@ async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
|
|
|
16219
16126
|
function useEventRegistrationStripeReturn(options) {
|
|
16220
16127
|
return useEventRegistrationStripeReturnWithDeps(options, eventRegistrationStripeReturnDeps);
|
|
16221
16128
|
}
|
|
16129
|
+
function completeVerifiedRegistration(options, deps, returnContext) {
|
|
16130
|
+
const siteId = options.api.config.siteId;
|
|
16131
|
+
const checkoutAttemptId = returnContext?.checkoutAttemptId;
|
|
16132
|
+
if (siteId && checkoutAttemptId) deps.clearPendingRegistration(siteId, checkoutAttemptId);
|
|
16133
|
+
options.setRegistrationResult({ status: "confirmed" });
|
|
16134
|
+
options.setStep("success");
|
|
16135
|
+
}
|
|
16222
16136
|
function useEventRegistrationStripeReturnWithDeps(options, deps) {
|
|
16223
16137
|
const { api, pendingRegistrationReference, setErrorMessage, setRegistrationResult, setStep, step } = options;
|
|
16224
|
-
const
|
|
16138
|
+
const returnContextRef = useRef(null);
|
|
16225
16139
|
const lookupInFlightRef = useRef(false);
|
|
16226
16140
|
const [lookupState, setLookupState] = useState("settled");
|
|
16227
16141
|
const resolveReturn = useCallback(async () => {
|
|
@@ -16229,7 +16143,7 @@ function useEventRegistrationStripeReturnWithDeps(options, deps) {
|
|
|
16229
16143
|
lookupInFlightRef.current = true;
|
|
16230
16144
|
setLookupState("loading");
|
|
16231
16145
|
try {
|
|
16232
|
-
setLookupState(await handleCheckoutReturn(options, deps,
|
|
16146
|
+
setLookupState(await handleCheckoutReturn(options, deps, returnContextRef));
|
|
16233
16147
|
} finally {
|
|
16234
16148
|
lookupInFlightRef.current = false;
|
|
16235
16149
|
}
|
|
@@ -16252,13 +16166,8 @@ function useEventRegistrationStripeReturnWithDeps(options, deps) {
|
|
|
16252
16166
|
resolveReturn();
|
|
16253
16167
|
}, []);
|
|
16254
16168
|
useEffect(() => {
|
|
16255
|
-
if (verification.status === "completed")
|
|
16256
|
-
|
|
16257
|
-
const checkoutAttemptId = checkoutAttemptIdRef.current;
|
|
16258
|
-
if (siteId && checkoutAttemptId) deps.clearPendingRegistration(siteId, checkoutAttemptId);
|
|
16259
|
-
setRegistrationResult({ status: "confirmed" });
|
|
16260
|
-
setStep("success");
|
|
16261
|
-
} else if (verification.status === "failed") {
|
|
16169
|
+
if (verification.status === "completed") completeVerifiedRegistration(options, deps, returnContextRef.current);
|
|
16170
|
+
else if (verification.status === "failed") {
|
|
16262
16171
|
setErrorMessage("Please try again or choose another payment option. If this keeps happening, contact the organiser for help.");
|
|
16263
16172
|
setStep("payment-failed");
|
|
16264
16173
|
} else if (verification.status === "timeout") setStep("verifying-timeout");
|
|
@@ -16287,7 +16196,10 @@ function registrationErrorPresentation(error) {
|
|
|
16287
16196
|
const reason = error instanceof BlockApiError ? parseEventRegistrationErrorReason(error.tag) : null;
|
|
16288
16197
|
if (reason) return eventRegistrationErrors[reason];
|
|
16289
16198
|
if (error instanceof BlockApiError && error.status < 500) return eventRegistrationErrors.invalidCommitInput;
|
|
16290
|
-
return
|
|
16199
|
+
return {
|
|
16200
|
+
message: "Something went wrong. Please try again.",
|
|
16201
|
+
action: "retry"
|
|
16202
|
+
};
|
|
16291
16203
|
}
|
|
16292
16204
|
//#endregion
|
|
16293
16205
|
//#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.ts
|
|
@@ -16316,26 +16228,6 @@ function useEventRegistrationSubmit(options) {
|
|
|
16316
16228
|
* and the balance left, which the block's copy cannot. Every other method keeps
|
|
16317
16229
|
* whatever success message the site configured.
|
|
16318
16230
|
*/
|
|
16319
|
-
function toRegistrationResult(result) {
|
|
16320
|
-
if (result.alreadyRegistered) {
|
|
16321
|
-
const waitlisted = result.status === "waitlist";
|
|
16322
|
-
return {
|
|
16323
|
-
status: result.status,
|
|
16324
|
-
variant: "info",
|
|
16325
|
-
title: waitlisted ? "Already waitlisted" : "Already registered",
|
|
16326
|
-
message: result.message ?? (waitlisted ? "You are already on the waitlist for this event." : "You are already registered for this event.")
|
|
16327
|
-
};
|
|
16328
|
-
}
|
|
16329
|
-
if (result.status === "waitlist") return {
|
|
16330
|
-
status: "waitlist",
|
|
16331
|
-
title: "Added to waitlist",
|
|
16332
|
-
message: result.message ?? (typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.")
|
|
16333
|
-
};
|
|
16334
|
-
return {
|
|
16335
|
-
status: result.status,
|
|
16336
|
-
message: result.paymentMethod === "pass" ? result.message : void 0
|
|
16337
|
-
};
|
|
16338
|
-
}
|
|
16339
16231
|
function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
16340
16232
|
/**
|
|
16341
16233
|
* The command identity for the submission currently in progress.
|
|
@@ -16349,7 +16241,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
16349
16241
|
* Identical retries retain the command after a lost response. Changed form
|
|
16350
16242
|
* details get a new command so the server applies the new booking intent.
|
|
16351
16243
|
*/
|
|
16352
|
-
const commandRef =
|
|
16244
|
+
const { commandRef } = options;
|
|
16353
16245
|
const inFlightRef = useRef(null);
|
|
16354
16246
|
const submit = async (method, passId, membershipId, selection, submitOptions) => {
|
|
16355
16247
|
const target = options.registrationTarget;
|
|
@@ -16362,19 +16254,15 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
16362
16254
|
const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
|
|
16363
16255
|
try {
|
|
16364
16256
|
let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16257
|
+
let request = buildRegistrationRequest(options, prepared, method, passId, membershipId);
|
|
16258
|
+
const intentKey = registrationRequestIntentKey(request);
|
|
16259
|
+
if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) {
|
|
16260
|
+
prepared = {
|
|
16368
16261
|
...prepared,
|
|
16369
|
-
|
|
16370
|
-
}
|
|
16262
|
+
registrationCommandId: deps.createClientCommandId()
|
|
16263
|
+
};
|
|
16264
|
+
request = buildRegistrationRequest(options, prepared, method, passId, membershipId);
|
|
16371
16265
|
}
|
|
16372
|
-
const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
|
|
16373
|
-
const intentKey = registrationRequestIntentKey(request);
|
|
16374
|
-
if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
|
|
16375
|
-
...prepared,
|
|
16376
|
-
registrationCommandId: deps.createClientCommandId()
|
|
16377
|
-
};
|
|
16378
16266
|
commandRef.current = {
|
|
16379
16267
|
id: prepared.registrationCommandId,
|
|
16380
16268
|
intentKey
|
|
@@ -16383,8 +16271,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
16383
16271
|
...request,
|
|
16384
16272
|
registrationCommandId: prepared.registrationCommandId
|
|
16385
16273
|
});
|
|
16386
|
-
|
|
16387
|
-
return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
|
|
16274
|
+
return await completeRegistrationSubmission(options, deps, prepared, result, submitOptions);
|
|
16388
16275
|
} catch (error) {
|
|
16389
16276
|
if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
|
|
16390
16277
|
const { message, action } = registrationErrorPresentation(error);
|
|
@@ -16408,9 +16295,40 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
16408
16295
|
return pending;
|
|
16409
16296
|
};
|
|
16410
16297
|
}
|
|
16411
|
-
async function completeRegistrationSubmission(options, deps, prepared, result,
|
|
16412
|
-
|
|
16413
|
-
|
|
16298
|
+
async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
|
|
16299
|
+
switch (result.kind) {
|
|
16300
|
+
case "paymentStatusRequired":
|
|
16301
|
+
options.setPaymentStatusRecovery({
|
|
16302
|
+
kind: "ready",
|
|
16303
|
+
subject: result.subject
|
|
16304
|
+
});
|
|
16305
|
+
options.setStep("payment-status");
|
|
16306
|
+
return {
|
|
16307
|
+
ok: true,
|
|
16308
|
+
outcome: { kind: "payment_status" }
|
|
16309
|
+
};
|
|
16310
|
+
case "checkoutRequired":
|
|
16311
|
+
options.setPendingRegistrationReference(result.reference);
|
|
16312
|
+
savePendingCheckout(options, deps, prepared, result.submissionId, result.reference);
|
|
16313
|
+
options.setStep("redirecting");
|
|
16314
|
+
return redirectToCheckout(result.checkoutUrl, submitOptions);
|
|
16315
|
+
case "waitlisted":
|
|
16316
|
+
options.setRegistrationResult({
|
|
16317
|
+
status: "waitlist",
|
|
16318
|
+
title: "Added to waitlist",
|
|
16319
|
+
message: result.waitlist.message
|
|
16320
|
+
});
|
|
16321
|
+
break;
|
|
16322
|
+
case "bookingComplete":
|
|
16323
|
+
case "paymentDeferred":
|
|
16324
|
+
options.setPendingRegistrationReference(result.reference);
|
|
16325
|
+
options.setRegistrationResult({
|
|
16326
|
+
status: "confirmed",
|
|
16327
|
+
message: result.summary.paymentMethod === "pass" ? result.summary.message : void 0
|
|
16328
|
+
});
|
|
16329
|
+
break;
|
|
16330
|
+
}
|
|
16331
|
+
options.commandRef.current = null;
|
|
16414
16332
|
options.setStep("success");
|
|
16415
16333
|
return {
|
|
16416
16334
|
ok: true,
|
|
@@ -16441,15 +16359,7 @@ function prepareSubmitContext(options, registrationCommandId, target, method, pa
|
|
|
16441
16359
|
email: guest.email?.trim().toLowerCase() || void 0,
|
|
16442
16360
|
phone: guest.phone?.trim() || void 0
|
|
16443
16361
|
})) : void 0,
|
|
16444
|
-
subject: target.subject.
|
|
16445
|
-
kind: "occurrence",
|
|
16446
|
-
occurrenceId: target.subject.occurrenceId,
|
|
16447
|
-
attendanceMode: options.selectedAttendanceMode ?? void 0
|
|
16448
|
-
} : {
|
|
16449
|
-
kind: "wholeSeries",
|
|
16450
|
-
eventSeriesId: target.subject.eventSeriesId,
|
|
16451
|
-
attendanceMode: options.selectedAttendanceMode ?? void 0
|
|
16452
|
-
}
|
|
16362
|
+
subject: toRegistrationRequestSubject(target.subject, options.selectedAttendanceMode)
|
|
16453
16363
|
};
|
|
16454
16364
|
}
|
|
16455
16365
|
function resolveSelectionSnapshot(method, passId, membershipId, bundleProductId, selection) {
|
|
@@ -16473,85 +16383,6 @@ function resolveSelectionSnapshot(method, passId, membershipId, bundleProductId,
|
|
|
16473
16383
|
if (method === "free") return { method };
|
|
16474
16384
|
throw new Error("Choose an available payment option.");
|
|
16475
16385
|
}
|
|
16476
|
-
async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions) {
|
|
16477
|
-
options.setStep("redirecting");
|
|
16478
|
-
if (prepared.selectionSnapshot.method !== "stripe") throw new Error("Choose an available payment option.");
|
|
16479
|
-
const checkoutAttemptId = deps.createClientCommandId();
|
|
16480
|
-
const urls = buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: checkoutAttemptId });
|
|
16481
|
-
const result = await options.api.createEventCheckout({
|
|
16482
|
-
subject: prepared.subject,
|
|
16483
|
-
ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
|
|
16484
|
-
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
16485
|
-
email: options.formData.email.trim().toLowerCase(),
|
|
16486
|
-
name: options.formData.name.trim(),
|
|
16487
|
-
phone: options.formData.phone.trim() || void 0,
|
|
16488
|
-
formData: options.formData,
|
|
16489
|
-
consentAccepted: options.formData.consentAccepted,
|
|
16490
|
-
altchaSolution: options.altchaSolution,
|
|
16491
|
-
guests: prepared.guestsPayload,
|
|
16492
|
-
claimToken: options.claimToken ?? void 0,
|
|
16493
|
-
waitlistEntryId: options.waitlistEntryId ?? void 0,
|
|
16494
|
-
discountCode: options.discountCode.trim() || void 0,
|
|
16495
|
-
collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
|
|
16496
|
-
checkoutAttemptId,
|
|
16497
|
-
...urls
|
|
16498
|
-
});
|
|
16499
|
-
if (result.scope !== "wholeSeries") throw new Error("Unexpected registration scope for event checkout.");
|
|
16500
|
-
if ("waitlistEntryId" in result) {
|
|
16501
|
-
options.setRegistrationResult({
|
|
16502
|
-
status: "waitlist",
|
|
16503
|
-
variant: result.alreadyRegistered ? "info" : void 0,
|
|
16504
|
-
title: result.alreadyRegistered ? "Already waitlisted" : "Added to waitlist",
|
|
16505
|
-
message: result.alreadyRegistered ? "You are already on the waitlist for this event." : "You've been added to the waitlist."
|
|
16506
|
-
});
|
|
16507
|
-
options.setStep("success");
|
|
16508
|
-
return {
|
|
16509
|
-
ok: true,
|
|
16510
|
-
outcome: { kind: "completed" }
|
|
16511
|
-
};
|
|
16512
|
-
}
|
|
16513
|
-
if (result.bypassed) return completeBypassedCheckout(options);
|
|
16514
|
-
if (!result.checkoutUrl) throw new Error("Checkout URL missing");
|
|
16515
|
-
savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
|
|
16516
|
-
scope: "wholeSeries",
|
|
16517
|
-
registrationId: result.registrationId
|
|
16518
|
-
});
|
|
16519
|
-
return redirectToCheckout(result.checkoutUrl, submitOptions);
|
|
16520
|
-
}
|
|
16521
|
-
function needsOccurrenceCheckout(result, method) {
|
|
16522
|
-
return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
|
|
16523
|
-
"stripe",
|
|
16524
|
-
"pass_bundle",
|
|
16525
|
-
"membership_bundle"
|
|
16526
|
-
].includes(method);
|
|
16527
|
-
}
|
|
16528
|
-
async function submitOccurrenceCheckout(options, deps, prepared, registration, method, submitOptions) {
|
|
16529
|
-
const reference = {
|
|
16530
|
-
scope: "occurrence",
|
|
16531
|
-
attendeeId: registration.attendeeId
|
|
16532
|
-
};
|
|
16533
|
-
options.setPendingRegistrationReference(reference);
|
|
16534
|
-
options.setStep("redirecting");
|
|
16535
|
-
const checkoutAttemptId = deps.createClientCommandId();
|
|
16536
|
-
const urls = buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: checkoutAttemptId });
|
|
16537
|
-
const result = await options.api.createEventCheckout({
|
|
16538
|
-
subject: {
|
|
16539
|
-
kind: "occurrence",
|
|
16540
|
-
attendeeId: registration.attendeeId
|
|
16541
|
-
},
|
|
16542
|
-
registrationCommandId: prepared.registrationCommandId,
|
|
16543
|
-
checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
|
|
16544
|
-
productId: prepared.bundleProductId,
|
|
16545
|
-
discountCode: options.discountCode.trim() || void 0,
|
|
16546
|
-
collectionOptionKind: prepared.selectionSnapshot.method === "stripe" ? prepared.selectionSnapshot.collectionOptionKind : void 0,
|
|
16547
|
-
...urls
|
|
16548
|
-
});
|
|
16549
|
-
if (result.scope !== "occurrence") throw new Error("Unexpected registration scope for event checkout.");
|
|
16550
|
-
if (result.bypassed) return completeBypassedCheckout(options);
|
|
16551
|
-
if (!result.checkoutUrl) throw new Error("Checkout URL missing");
|
|
16552
|
-
if (prepared.subject.kind === "occurrence") savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference);
|
|
16553
|
-
return redirectToCheckout(result.checkoutUrl, submitOptions);
|
|
16554
|
-
}
|
|
16555
16386
|
function savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference) {
|
|
16556
16387
|
const siteId = options.api.config.siteId;
|
|
16557
16388
|
if (!siteId) return;
|
|
@@ -16564,14 +16395,6 @@ function savePendingCheckout(options, deps, prepared, checkoutAttemptId, referen
|
|
|
16564
16395
|
paymentSelection: prepared.selectionSnapshot
|
|
16565
16396
|
});
|
|
16566
16397
|
}
|
|
16567
|
-
function completeBypassedCheckout(options) {
|
|
16568
|
-
options.setRegistrationResult({ status: "confirmed" });
|
|
16569
|
-
options.setStep("success");
|
|
16570
|
-
return {
|
|
16571
|
-
ok: true,
|
|
16572
|
-
outcome: { kind: "completed" }
|
|
16573
|
-
};
|
|
16574
|
-
}
|
|
16575
16398
|
function redirectToCheckout(checkoutUrl, submitOptions) {
|
|
16576
16399
|
if (submitOptions?.redirect !== "manual") window.location.href = checkoutUrl;
|
|
16577
16400
|
return {
|
|
@@ -16583,12 +16406,23 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
|
|
|
16583
16406
|
};
|
|
16584
16407
|
}
|
|
16585
16408
|
function registrationRequestIntentKey(request) {
|
|
16586
|
-
const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
|
|
16587
|
-
return JSON.stringify(
|
|
16409
|
+
const { registrationCommandId: _command, altchaSolution: _proof, checkout, ...intent } = request;
|
|
16410
|
+
return JSON.stringify({
|
|
16411
|
+
...intent,
|
|
16412
|
+
checkout: checkout ? {
|
|
16413
|
+
discountCode: checkout.discountCode,
|
|
16414
|
+
collectionOptionKind: checkout.collectionOptionKind
|
|
16415
|
+
} : void 0
|
|
16416
|
+
});
|
|
16588
16417
|
}
|
|
16589
|
-
function
|
|
16418
|
+
function buildRegistrationRequest(options, prepared, method, passId, membershipId) {
|
|
16590
16419
|
return {
|
|
16591
16420
|
registrationCommandId: prepared.registrationCommandId,
|
|
16421
|
+
checkout: {
|
|
16422
|
+
...buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: prepared.registrationCommandId }),
|
|
16423
|
+
discountCode: options.discountCode.trim() || void 0,
|
|
16424
|
+
collectionOptionKind: prepared.selectionSnapshot.method === "stripe" ? prepared.selectionSnapshot.collectionOptionKind : void 0
|
|
16425
|
+
},
|
|
16592
16426
|
subject: prepared.subject,
|
|
16593
16427
|
ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
|
|
16594
16428
|
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
@@ -16608,64 +16442,6 @@ function buildOccurrenceRegistrationRequest(options, prepared, method, passId, m
|
|
|
16608
16442
|
};
|
|
16609
16443
|
}
|
|
16610
16444
|
//#endregion
|
|
16611
|
-
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
|
|
16612
|
-
function eventMatchesOccurrenceId(event, occurrenceId) {
|
|
16613
|
-
return event.registrationSubject.kind === "occurrence" && (event.registrationSubject.occurrenceId === occurrenceId || event.selectionId === occurrenceId);
|
|
16614
|
-
}
|
|
16615
|
-
function findEventByOccurrenceId(events, occurrenceId) {
|
|
16616
|
-
return events.find((event) => eventMatchesOccurrenceId(event, occurrenceId)) ?? null;
|
|
16617
|
-
}
|
|
16618
|
-
function findPreSelectedEvent(input) {
|
|
16619
|
-
const occurrenceContext = input.occurrenceContext;
|
|
16620
|
-
if (!occurrenceContext) return input.scopedEvents.length === 1 ? input.scopedEvents[0] ?? null : null;
|
|
16621
|
-
const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
16622
|
-
startsAt: occurrenceContext.startsAt,
|
|
16623
|
-
timeZone: occurrenceContext.timeZone
|
|
16624
|
-
}));
|
|
16625
|
-
return input.scopedEvents.find((event) => eventMatchesOccurrenceId(event, occurrenceContext.id) || getBookingLocalDateKey(toScheduledBookingDateTime({
|
|
16626
|
-
startsAt: event.startsAt,
|
|
16627
|
-
timeZone: event.timeZone
|
|
16628
|
-
})) === contextDate) ?? null;
|
|
16629
|
-
}
|
|
16630
|
-
function resolveRegistrationTarget(input) {
|
|
16631
|
-
const subject = input.occurrenceContext ? {
|
|
16632
|
-
kind: "occurrence",
|
|
16633
|
-
occurrenceId: input.occurrenceContext.id
|
|
16634
|
-
} : input.selectedEvent?.registrationSubject ?? null;
|
|
16635
|
-
if (!subject) return null;
|
|
16636
|
-
return {
|
|
16637
|
-
subject,
|
|
16638
|
-
selectedEventId: input.selectedEvent?.selectionId ?? null
|
|
16639
|
-
};
|
|
16640
|
-
}
|
|
16641
|
-
function resolveEventRequiresPayment(input) {
|
|
16642
|
-
if (input.eligibility) return input.eligibility.requiresPayment;
|
|
16643
|
-
if (input.selectedTicketType) return input.selectedTicketType.priceAmount > 0;
|
|
16644
|
-
if (!input.event) return false;
|
|
16645
|
-
return publicEventPricingType(input.event.pricing) === "paid";
|
|
16646
|
-
}
|
|
16647
|
-
function resolveDiscountContext(input) {
|
|
16648
|
-
const selection = input.paymentSelection.method ? input.paymentSelection : null;
|
|
16649
|
-
if (!input.event) return null;
|
|
16650
|
-
if (selection?.method === "pass_bundle" && selection.bundlePassId) return {
|
|
16651
|
-
type: "pass",
|
|
16652
|
-
passId: selection.bundlePassId
|
|
16653
|
-
};
|
|
16654
|
-
if (selection?.method === "membership_bundle" && selection.bundleMembershipId) return {
|
|
16655
|
-
type: "membership",
|
|
16656
|
-
membershipId: selection.bundleMembershipId
|
|
16657
|
-
};
|
|
16658
|
-
if (!input.eventRequiresPayment) return null;
|
|
16659
|
-
if (input.ticketsCount <= 0) return null;
|
|
16660
|
-
if (selection?.method && selection.method !== "stripe") return null;
|
|
16661
|
-
return {
|
|
16662
|
-
type: "event",
|
|
16663
|
-
eventSeriesId: input.event.seriesId,
|
|
16664
|
-
eventCategoryId: input.event.eventCategory?.id ?? null,
|
|
16665
|
-
ticketsCount: input.ticketsCount
|
|
16666
|
-
};
|
|
16667
|
-
}
|
|
16668
|
-
//#endregion
|
|
16669
16445
|
//#region ../blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.ts
|
|
16670
16446
|
function buildCandidate(input) {
|
|
16671
16447
|
if (!input.eligibilityIsSettled || !input.eligibility || !input.currentEvent) return null;
|
|
@@ -16886,7 +16662,7 @@ function computeAutoSelection(input) {
|
|
|
16886
16662
|
return { method: null };
|
|
16887
16663
|
}
|
|
16888
16664
|
function computeDirectPaymentSelection(eligibility) {
|
|
16889
|
-
if (!eligibility?.
|
|
16665
|
+
if (!eligibility?.requiresPayment) return { method: null };
|
|
16890
16666
|
const approvedKinds = getApprovedDirectPaymentCollectionOptionKinds(eligibility.paymentOptions);
|
|
16891
16667
|
const collectionOptionKind = approvedKinds.includes("upfront") ? "upfront" : approvedKinds[0];
|
|
16892
16668
|
return collectionOptionKind ? {
|
|
@@ -16900,7 +16676,7 @@ function isSelectionValid(input) {
|
|
|
16900
16676
|
if (!eligibility) return selection.method === "stripe" || selection.method === "pass_bundle" || selection.method === "membership_bundle";
|
|
16901
16677
|
switch (selection.method) {
|
|
16902
16678
|
case "free": return eligibility.isFree;
|
|
16903
|
-
case "stripe": return Boolean(eligibility.
|
|
16679
|
+
case "stripe": return Boolean(eligibility.requiresPayment && eligibility.price);
|
|
16904
16680
|
case "pass": return isAuthenticated && ticketsCount === 1 && !!selection.passId && eligibility.eligiblePasses.some((pass) => pass.id === selection.passId);
|
|
16905
16681
|
case "membership": return isAuthenticated && ticketsCount === 1 && !!selection.membershipId && eligibility.eligibleMemberships.some((membership) => membership.id === selection.membershipId);
|
|
16906
16682
|
case "pass_bundle": return ticketsCount === 1 && !!selection.bundlePassId && eligibility.availablePasses.some((pass) => pass.id === selection.bundlePassId);
|
|
@@ -16919,7 +16695,7 @@ function normalizeRegistrationFlowState(state) {
|
|
|
16919
16695
|
ticketsCount: state.ticketsCount,
|
|
16920
16696
|
passOptOut: nextPassOptOut
|
|
16921
16697
|
});
|
|
16922
|
-
const canKeepManualSelection = state.step
|
|
16698
|
+
const canKeepManualSelection = state.step !== "select-tickets" && state.selectionSource === "manual" && isSelectionValid({
|
|
16923
16699
|
selection: state.paymentSelection,
|
|
16924
16700
|
isAuthenticated: state.isAuthenticated,
|
|
16925
16701
|
eligibility: state.eligibility,
|
|
@@ -16985,6 +16761,24 @@ function requiresPaymentStep(params) {
|
|
|
16985
16761
|
if (!params.eventRequiresPayment) return false;
|
|
16986
16762
|
return !isEntitlementSelection(params.paymentSelection);
|
|
16987
16763
|
}
|
|
16764
|
+
//#endregion
|
|
16765
|
+
//#region ../blocks/src/system/runtime/nodes/events/domain/destination.ts
|
|
16766
|
+
function isRecord$1(value) {
|
|
16767
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16768
|
+
}
|
|
16769
|
+
function isRuntimeEventDestination(value) {
|
|
16770
|
+
if (!isRecord$1(value) || typeof value.kind !== "string") return false;
|
|
16771
|
+
if (value.kind === "native") return (value.mode === "cms-managed" || value.mode === "system-managed") && typeof value.path === "string";
|
|
16772
|
+
return value.kind === "external" && typeof value.url === "string" && typeof value.label === "string";
|
|
16773
|
+
}
|
|
16774
|
+
function resolveRuntimeEventDestination(event) {
|
|
16775
|
+
if (isRuntimeEventDestination(event.destination)) return event.destination;
|
|
16776
|
+
return {
|
|
16777
|
+
kind: "native",
|
|
16778
|
+
mode: event.eventDestinationMode === "system-managed" ? "system-managed" : "cms-managed",
|
|
16779
|
+
path: typeof event.path === "string" ? event.path : ""
|
|
16780
|
+
};
|
|
16781
|
+
}
|
|
16988
16782
|
const unsupportedEventRegistrationPageSurfaceSubjectSchema = z.object({
|
|
16989
16783
|
kind: z.literal("unsupported"),
|
|
16990
16784
|
reason: z.enum([
|
|
@@ -17227,7 +17021,7 @@ function resolveEventRegistrationSubmitPlan(input) {
|
|
|
17227
17021
|
const selection = input.paymentSelection.method ? input.paymentSelection : void 0;
|
|
17228
17022
|
if (input.canJoinWaitlist) return {
|
|
17229
17023
|
ok: true,
|
|
17230
|
-
args:
|
|
17024
|
+
args: { method: "free" }
|
|
17231
17025
|
};
|
|
17232
17026
|
switch (input.paymentSelection.method) {
|
|
17233
17027
|
case "pass": return input.paymentSelection.passId ? {
|
|
@@ -17278,6 +17072,10 @@ function resolveHeadlessEventRegistrationStatus(wizard) {
|
|
|
17278
17072
|
case "redirecting": return { tag: "redirecting" };
|
|
17279
17073
|
case "verifying-payment": return { tag: "verifying-payment" };
|
|
17280
17074
|
case "verifying-timeout": return { tag: "verifying-timeout" };
|
|
17075
|
+
case "payment-status": return wizard.paymentStatusRecovery ? {
|
|
17076
|
+
tag: "payment-status",
|
|
17077
|
+
state: wizard.paymentStatusRecovery
|
|
17078
|
+
} : { tag: "ready" };
|
|
17281
17079
|
case "payment-failed": return {
|
|
17282
17080
|
tag: "payment-failed",
|
|
17283
17081
|
message: wizard.errorMessage
|
|
@@ -17324,6 +17122,10 @@ function resolveHeadlessEventRegistrationView(wizard) {
|
|
|
17324
17122
|
kind: "verifying",
|
|
17325
17123
|
message: "Your booking is not confirmed yet. Please don’t make another booking while we check. You can check your payment status again in a moment."
|
|
17326
17124
|
};
|
|
17125
|
+
case "payment-status": return wizard.paymentStatusRecovery ? {
|
|
17126
|
+
kind: "payment-status",
|
|
17127
|
+
state: wizard.paymentStatusRecovery
|
|
17128
|
+
} : { kind: "form" };
|
|
17327
17129
|
case "select-event":
|
|
17328
17130
|
case "select-tickets":
|
|
17329
17131
|
case "enter-details":
|
|
@@ -17590,20 +17392,124 @@ function useWaitlistClaimRestoration(input) {
|
|
|
17590
17392
|
}
|
|
17591
17393
|
//#endregion
|
|
17592
17394
|
//#region ../blocks/src/system/runtime/nodes/event-registration/registrationCompletion.ts
|
|
17395
|
+
function isSelectionSoldOut(availability) {
|
|
17396
|
+
return availability?.kind === "unavailable" && availability.reason === "full";
|
|
17397
|
+
}
|
|
17593
17398
|
function resolveRegistrationAvailabilityBlocker(input) {
|
|
17594
17399
|
if (input.hasWaitlistClaim) return null;
|
|
17595
17400
|
if (input.eligibilityError) return input.eligibilityError;
|
|
17596
17401
|
if (!input.eligibility) return "Registration is not available for this event.";
|
|
17402
|
+
if (input.eligibility.registration.kind === "pending_payment") return null;
|
|
17403
|
+
if (isSelectionSoldOut(input.eligibility.availability)) return null;
|
|
17597
17404
|
if (input.eligibility.availability.kind === "unavailable" && input.eligibility.availability.reason === "paymentUnavailable") return "Payment options are not available for this event.";
|
|
17598
|
-
if (input.eligibility.availability.kind === "unavailable" ||
|
|
17405
|
+
if (input.eligibility.availability.kind === "unavailable" || input.eligibility.registration.kind === "waitlisted") return "Registration is not available for this event.";
|
|
17599
17406
|
return null;
|
|
17600
17407
|
}
|
|
17601
17408
|
function resolvePricingSelectionBlocker(input) {
|
|
17602
17409
|
if (input.selectionRequired && !input.hasValidSelection) return "Choose at least one available ticket to continue.";
|
|
17603
17410
|
return input.slidingScaleSelectionMessage;
|
|
17604
17411
|
}
|
|
17605
|
-
|
|
17606
|
-
|
|
17412
|
+
//#endregion
|
|
17413
|
+
//#region ../blocks/src/system/runtime/nodes/event-registration/usePaymentStatusRecovery.ts
|
|
17414
|
+
function isCheckableRecovery(state) {
|
|
17415
|
+
return state.kind === "ready" || state.kind === "processing" || state.kind === "temporarilyUnavailable";
|
|
17416
|
+
}
|
|
17417
|
+
function assistanceRequired(recovery) {
|
|
17418
|
+
return {
|
|
17419
|
+
kind: "assistanceRequired",
|
|
17420
|
+
subject: recovery.subject
|
|
17421
|
+
};
|
|
17422
|
+
}
|
|
17423
|
+
function applyStatusOutcome(outcome, recovery, setters, setRecovery) {
|
|
17424
|
+
if (outcome.kind === "resolved") {
|
|
17425
|
+
setters.setPendingRegistrationReference(outcome.reference);
|
|
17426
|
+
setters.setRegistrationResult({ status: "confirmed" });
|
|
17427
|
+
setRecovery(null);
|
|
17428
|
+
setters.setStep("success");
|
|
17429
|
+
return;
|
|
17430
|
+
}
|
|
17431
|
+
switch (outcome.kind) {
|
|
17432
|
+
case "paymentProcessing":
|
|
17433
|
+
setRecovery({
|
|
17434
|
+
...recovery,
|
|
17435
|
+
kind: "processing"
|
|
17436
|
+
});
|
|
17437
|
+
return;
|
|
17438
|
+
case "paymentAvailable":
|
|
17439
|
+
setRecovery({
|
|
17440
|
+
...recovery,
|
|
17441
|
+
kind: "paymentAvailable",
|
|
17442
|
+
checkoutUrl: outcome.checkoutUrl
|
|
17443
|
+
});
|
|
17444
|
+
return;
|
|
17445
|
+
case "paymentCheckUnavailable":
|
|
17446
|
+
setRecovery({
|
|
17447
|
+
...recovery,
|
|
17448
|
+
kind: "temporarilyUnavailable"
|
|
17449
|
+
});
|
|
17450
|
+
return;
|
|
17451
|
+
case "paymentRetryAvailable":
|
|
17452
|
+
setRecovery({
|
|
17453
|
+
...recovery,
|
|
17454
|
+
kind: "retryAvailable"
|
|
17455
|
+
});
|
|
17456
|
+
return;
|
|
17457
|
+
case "abandoned":
|
|
17458
|
+
case "notFound":
|
|
17459
|
+
case "reconciliationRequired":
|
|
17460
|
+
case "paymentAssistanceRequired":
|
|
17461
|
+
setRecovery(assistanceRequired(recovery));
|
|
17462
|
+
return;
|
|
17463
|
+
}
|
|
17464
|
+
}
|
|
17465
|
+
function usePaymentStatusRecovery(options) {
|
|
17466
|
+
const [recovery, setRecovery] = useState(null);
|
|
17467
|
+
const checkRef = useRef(null);
|
|
17468
|
+
return {
|
|
17469
|
+
recovery,
|
|
17470
|
+
showRecovery: useCallback((next) => setRecovery(next), []),
|
|
17471
|
+
check: useCallback(() => {
|
|
17472
|
+
if (!recovery || !isCheckableRecovery(recovery) || checkRef.current) return;
|
|
17473
|
+
const pending = (async () => {
|
|
17474
|
+
setRecovery({
|
|
17475
|
+
...recovery,
|
|
17476
|
+
kind: "checking"
|
|
17477
|
+
});
|
|
17478
|
+
try {
|
|
17479
|
+
applyStatusOutcome(await options.api.resolveEventCheckoutReturn({
|
|
17480
|
+
kind: "checkStatus",
|
|
17481
|
+
subject: recovery.subject
|
|
17482
|
+
}), recovery, options, setRecovery);
|
|
17483
|
+
} catch {
|
|
17484
|
+
setRecovery({
|
|
17485
|
+
...recovery,
|
|
17486
|
+
kind: "temporarilyUnavailable"
|
|
17487
|
+
});
|
|
17488
|
+
}
|
|
17489
|
+
})();
|
|
17490
|
+
checkRef.current = pending;
|
|
17491
|
+
pending.finally(() => {
|
|
17492
|
+
if (checkRef.current === pending) checkRef.current = null;
|
|
17493
|
+
});
|
|
17494
|
+
}, [options, recovery]),
|
|
17495
|
+
continuePayment: useCallback(() => {
|
|
17496
|
+
if (recovery?.kind === "paymentAvailable") window.location.assign(recovery.checkoutUrl);
|
|
17497
|
+
}, [recovery]),
|
|
17498
|
+
returnToPayment: useCallback(() => {
|
|
17499
|
+
if (recovery?.kind !== "retryAvailable") return;
|
|
17500
|
+
options.beginNewSubmission();
|
|
17501
|
+
setRecovery(null);
|
|
17502
|
+
options.setOptionsRefreshKey((value) => value + 1);
|
|
17503
|
+
options.setStep("select-payment");
|
|
17504
|
+
}, [options, recovery]),
|
|
17505
|
+
returnToBooking: useCallback(() => {
|
|
17506
|
+
if (recovery?.kind !== "assistanceRequired") return;
|
|
17507
|
+
options.beginNewSubmission();
|
|
17508
|
+
setRecovery(null);
|
|
17509
|
+
options.setOptionsRefreshKey((value) => value + 1);
|
|
17510
|
+
options.setStep("select-tickets");
|
|
17511
|
+
}, [options, recovery])
|
|
17512
|
+
};
|
|
17607
17513
|
}
|
|
17608
17514
|
//#endregion
|
|
17609
17515
|
//#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
@@ -17661,6 +17567,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17661
17567
|
const [errorAction, setErrorAction] = useState("retry");
|
|
17662
17568
|
const [optionsRefreshKey, setOptionsRefreshKey] = useState(0);
|
|
17663
17569
|
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
17570
|
+
const [checkingNextStep, setCheckingNextStep] = useState(false);
|
|
17664
17571
|
const { authState: portalAuthState, profile: portalProfile } = deps.usePortalAuth();
|
|
17665
17572
|
const waitlistClaim = deps.useWaitlistClaim();
|
|
17666
17573
|
const [showMagicLinkModal, setShowMagicLinkModal] = useState(false);
|
|
@@ -17687,28 +17594,29 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17687
17594
|
}), [options.occurrenceContext, selectedEvent]);
|
|
17688
17595
|
const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
|
|
17689
17596
|
const currentEvent = selectedEvent ?? preSelectedEvent;
|
|
17597
|
+
const commandRef = useRef(null);
|
|
17690
17598
|
const setStep = useCallback((nextStep) => {
|
|
17691
17599
|
dispatchFlow({
|
|
17692
17600
|
type: "set-step",
|
|
17693
17601
|
step: nextStep
|
|
17694
17602
|
});
|
|
17695
17603
|
}, []);
|
|
17696
|
-
const {
|
|
17697
|
-
|
|
17698
|
-
|
|
17699
|
-
|
|
17604
|
+
const { recovery: paymentStatusRecovery, showRecovery: setPaymentStatusRecovery, check: handleCheckPaymentStatus, continuePayment: handleContinueExistingPayment, returnToPayment: handleReturnToPayment, returnToBooking: handleReturnToBooking } = usePaymentStatusRecovery({
|
|
17605
|
+
api,
|
|
17606
|
+
beginNewSubmission: () => {
|
|
17607
|
+
commandRef.current = null;
|
|
17608
|
+
},
|
|
17609
|
+
setPendingRegistrationReference,
|
|
17610
|
+
setRegistrationResult,
|
|
17611
|
+
setOptionsRefreshKey,
|
|
17612
|
+
setStep
|
|
17613
|
+
});
|
|
17614
|
+
const usesTicketTypeSelections = usesTieredPricing(currentEvent);
|
|
17700
17615
|
const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
|
|
17701
17616
|
event: currentEvent,
|
|
17702
17617
|
eligibility: null,
|
|
17703
17618
|
selectedAttendanceMode
|
|
17704
|
-
})
|
|
17705
|
-
...option,
|
|
17706
|
-
availability: checkoutRecoveryOptionAvailability(option.availability)
|
|
17707
|
-
} : option), [
|
|
17708
|
-
currentEvent,
|
|
17709
|
-
selectedAttendanceMode,
|
|
17710
|
-
checkoutRecovery
|
|
17711
|
-
]);
|
|
17619
|
+
}), [currentEvent, selectedAttendanceMode]);
|
|
17712
17620
|
const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
|
|
17713
17621
|
const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
|
|
17714
17622
|
const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
|
|
@@ -17746,7 +17654,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17746
17654
|
isAuthenticated: portalAuthState === "authenticated",
|
|
17747
17655
|
occurrenceId: registrationOccurrenceId
|
|
17748
17656
|
});
|
|
17749
|
-
const eligibility =
|
|
17657
|
+
const eligibility = eligibilityResult.eligibility;
|
|
17750
17658
|
const eligibilityLoading = eligibilityResult.isLoading;
|
|
17751
17659
|
const eligibilityError = eligibilityResult.error;
|
|
17752
17660
|
const portalCreditState = eligibilityResult.creditState;
|
|
@@ -17858,14 +17766,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17858
17766
|
event: currentEvent,
|
|
17859
17767
|
eligibility,
|
|
17860
17768
|
selectedAttendanceMode
|
|
17861
|
-
})
|
|
17862
|
-
...option,
|
|
17863
|
-
availability: checkoutRecoveryOptionAvailability(option.availability)
|
|
17864
|
-
} : option), [
|
|
17769
|
+
}), [
|
|
17865
17770
|
currentEvent,
|
|
17866
17771
|
selectedAttendanceMode,
|
|
17867
|
-
eligibility
|
|
17868
|
-
checkoutRecovery
|
|
17772
|
+
eligibility
|
|
17869
17773
|
]);
|
|
17870
17774
|
const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
|
|
17871
17775
|
const selectedTicketType = useMemo(() => findSelectedTicketType({
|
|
@@ -17889,12 +17793,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17889
17793
|
const event = currentEvent;
|
|
17890
17794
|
if (!usesTieredPricing(event)) return false;
|
|
17891
17795
|
if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
|
|
17892
|
-
return
|
|
17893
|
-
}, [
|
|
17894
|
-
currentEvent,
|
|
17895
|
-
selectedAttendanceMode,
|
|
17896
|
-
checkoutRecovery
|
|
17897
|
-
]);
|
|
17796
|
+
return true;
|
|
17797
|
+
}, [currentEvent, selectedAttendanceMode]);
|
|
17898
17798
|
const hasValidTicketSelection = hasValidPricingOptionSelection({
|
|
17899
17799
|
selectionRequired: ticketTypeSelectionRequired,
|
|
17900
17800
|
lines: normalizedSelectedTicketLines,
|
|
@@ -17905,8 +17805,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17905
17805
|
if (selectedTicketLines.length > 0) setSelectedTicketLines([]);
|
|
17906
17806
|
return;
|
|
17907
17807
|
}
|
|
17908
|
-
const availableTicketTypes = eventTicketTypesForSelection.filter((ticketType) => ticketType.availability
|
|
17909
|
-
const implicitTicketType =
|
|
17808
|
+
const availableTicketTypes = eventTicketTypesForSelection.filter((ticketType) => canRequestTicketOption(ticketType.availability));
|
|
17809
|
+
const implicitTicketType = getImplicitSingleTicketType(eventTicketTypesForSelection);
|
|
17910
17810
|
if (implicitTicketType && normalizedSelectedTicketLines.length === 0) {
|
|
17911
17811
|
setSelectedTicketLines([{
|
|
17912
17812
|
pricingOptionId: implicitTicketType.pricingOptionId,
|
|
@@ -17973,6 +17873,26 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
17973
17873
|
selectedEventSlidingScale,
|
|
17974
17874
|
selectedSlidingAmount
|
|
17975
17875
|
]);
|
|
17876
|
+
const checkDetailsNextStep = async () => {
|
|
17877
|
+
if (portalAuthState === "authenticated" || waitlistClaim.claim || eligibility?.availability.kind === "available" || !registrationTarget) return { kind: canRecoverToWaitlist(eligibility) ? "waitlist" : "continue" };
|
|
17878
|
+
setCheckingNextStep(true);
|
|
17879
|
+
try {
|
|
17880
|
+
return await api.checkRegistrationNextStep({
|
|
17881
|
+
subject: toRegistrationRequestSubject(registrationTarget.subject, selectedAttendanceMode),
|
|
17882
|
+
selections: ticketSelections,
|
|
17883
|
+
selectedSlidingAmount: selectedSlidingAmount ?? void 0,
|
|
17884
|
+
email: formData.email,
|
|
17885
|
+
altchaSolution
|
|
17886
|
+
});
|
|
17887
|
+
} catch {
|
|
17888
|
+
return {
|
|
17889
|
+
kind: "unavailable",
|
|
17890
|
+
message: "We could not check availability. Please try again."
|
|
17891
|
+
};
|
|
17892
|
+
} finally {
|
|
17893
|
+
setCheckingNextStep(false);
|
|
17894
|
+
}
|
|
17895
|
+
};
|
|
17976
17896
|
const handleDetailsComplete = async () => {
|
|
17977
17897
|
const blockDetailsCompletion = (message) => {
|
|
17978
17898
|
setErrorAction("places");
|
|
@@ -18004,11 +17924,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18004
17924
|
message: "Check the highlighted fields and try again."
|
|
18005
17925
|
};
|
|
18006
17926
|
}
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18011
|
-
if (!eligibility?.canJoinWaitlist && requiresPaymentStep({
|
|
17927
|
+
const next = await checkDetailsNextStep();
|
|
17928
|
+
if (next.kind === "unavailable") return blockDetailsCompletion(next.message);
|
|
17929
|
+
const canJoinWaitlist = next.kind === "waitlist";
|
|
17930
|
+
if (!canJoinWaitlist && requiresPaymentStep({
|
|
18012
17931
|
eventRequiresPayment,
|
|
18013
17932
|
paymentSelection
|
|
18014
17933
|
})) {
|
|
@@ -18021,7 +17940,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18021
17940
|
const submitPlan = resolveEventRegistrationSubmitPlan({
|
|
18022
17941
|
paymentSelection,
|
|
18023
17942
|
eventRequiresPayment,
|
|
18024
|
-
canJoinWaitlist
|
|
17943
|
+
canJoinWaitlist
|
|
18025
17944
|
});
|
|
18026
17945
|
if (!submitPlan.ok) return blockDetailsCompletion(submitPlan.message);
|
|
18027
17946
|
const submitResult = await handleSubmit(submitPlan.args.method, submitPlan.args.passId, submitPlan.args.membershipId, submitPlan.args.selection);
|
|
@@ -18039,7 +17958,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18039
17958
|
const submitPlan = resolveEventRegistrationSubmitPlan({
|
|
18040
17959
|
paymentSelection,
|
|
18041
17960
|
eventRequiresPayment,
|
|
18042
|
-
canJoinWaitlist:
|
|
17961
|
+
canJoinWaitlist: false
|
|
18043
17962
|
});
|
|
18044
17963
|
if (!submitPlan.ok) {
|
|
18045
17964
|
setErrorMessage(submitPlan.message);
|
|
@@ -18071,6 +17990,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18071
17990
|
const selectionMethod = paymentSelection.method;
|
|
18072
17991
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
18073
17992
|
const handleSubmit = deps.useEventRegistrationSubmit({
|
|
17993
|
+
commandRef,
|
|
18074
17994
|
setErrorAction,
|
|
18075
17995
|
api,
|
|
18076
17996
|
registrationTarget,
|
|
@@ -18087,7 +18007,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18087
18007
|
setPendingRegistrationReference,
|
|
18088
18008
|
setStep,
|
|
18089
18009
|
setRegistrationResult: (result) => setRegistrationResult(result),
|
|
18090
|
-
setErrorMessage
|
|
18010
|
+
setErrorMessage,
|
|
18011
|
+
setPaymentStatusRecovery
|
|
18091
18012
|
});
|
|
18092
18013
|
const handleEventSelect = (event) => {
|
|
18093
18014
|
setSelectedEvent(event);
|
|
@@ -18146,8 +18067,6 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18146
18067
|
scopedEvents,
|
|
18147
18068
|
preSelectedEvent,
|
|
18148
18069
|
hasPreSelectedContext,
|
|
18149
|
-
checkoutRecovery,
|
|
18150
|
-
startCheckoutRecovery,
|
|
18151
18070
|
step,
|
|
18152
18071
|
setStep,
|
|
18153
18072
|
selectedEvent,
|
|
@@ -18201,7 +18120,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18201
18120
|
waitlistClaim,
|
|
18202
18121
|
eligibility,
|
|
18203
18122
|
registrationOptionsState: eligibilityResult.state,
|
|
18204
|
-
eligibilityLoading,
|
|
18123
|
+
eligibilityLoading: eligibilityLoading || checkingNextStep,
|
|
18205
18124
|
eligibilityError,
|
|
18206
18125
|
existingRegistration: existingRegistrationResult.registration,
|
|
18207
18126
|
existingRegistrationLoading: existingRegistrationResult.isLoading || portalAuthState === "authenticated" && eligibilityLoading,
|
|
@@ -18221,6 +18140,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18221
18140
|
discountContext,
|
|
18222
18141
|
shouldShowDiscountToggle,
|
|
18223
18142
|
verification,
|
|
18143
|
+
paymentStatusRecovery,
|
|
18144
|
+
handleCheckPaymentStatus,
|
|
18145
|
+
handleContinueExistingPayment,
|
|
18146
|
+
handleReturnToPayment,
|
|
18147
|
+
handleReturnToBooking,
|
|
18224
18148
|
handleDetailsComplete,
|
|
18225
18149
|
handlePaymentSelect,
|
|
18226
18150
|
handleUseCardInsteadOfPass,
|
|
@@ -18273,7 +18197,7 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18273
18197
|
selection: wizard.paymentSelection
|
|
18274
18198
|
}),
|
|
18275
18199
|
eventRequiresPayment: wizard.eventRequiresPayment,
|
|
18276
|
-
canJoinWaitlist: wizard.eligibility?.
|
|
18200
|
+
canJoinWaitlist: wizard.step !== "select-payment" && wizard.eligibility?.availability.kind === "waitlist" && wizard.eligibility.registration.kind !== "pending_payment"
|
|
18277
18201
|
});
|
|
18278
18202
|
if (!plan.ok) return {
|
|
18279
18203
|
ok: false,
|
|
@@ -18318,6 +18242,7 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18318
18242
|
case "redirecting":
|
|
18319
18243
|
case "verifying-payment":
|
|
18320
18244
|
case "verifying-timeout":
|
|
18245
|
+
case "payment-status":
|
|
18321
18246
|
case "payment-failed": return {
|
|
18322
18247
|
ok: false,
|
|
18323
18248
|
reason: "blocked",
|
|
@@ -18325,27 +18250,7 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18325
18250
|
};
|
|
18326
18251
|
}
|
|
18327
18252
|
}, [submit, wizard]);
|
|
18328
|
-
const back =
|
|
18329
|
-
switch (wizard.step) {
|
|
18330
|
-
case "enter-details":
|
|
18331
|
-
wizard.setStep("select-tickets");
|
|
18332
|
-
return;
|
|
18333
|
-
case "select-payment":
|
|
18334
|
-
wizard.setStep("enter-details");
|
|
18335
|
-
return;
|
|
18336
|
-
case "select-tickets":
|
|
18337
|
-
if (!wizard.hasPreSelectedContext) wizard.setStep("select-event");
|
|
18338
|
-
return;
|
|
18339
|
-
case "select-event":
|
|
18340
|
-
case "error":
|
|
18341
|
-
case "success":
|
|
18342
|
-
case "submitting":
|
|
18343
|
-
case "redirecting":
|
|
18344
|
-
case "verifying-payment":
|
|
18345
|
-
case "verifying-timeout":
|
|
18346
|
-
case "payment-failed": return;
|
|
18347
|
-
}
|
|
18348
|
-
}, [wizard]);
|
|
18253
|
+
const back = useEventRegistrationBack(wizard);
|
|
18349
18254
|
const updateAttendee = useCallback((values) => {
|
|
18350
18255
|
wizard.setFormData(values);
|
|
18351
18256
|
}, [wizard]);
|
|
@@ -18432,7 +18337,8 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18432
18337
|
terminal: {
|
|
18433
18338
|
result: wizard.registrationResult,
|
|
18434
18339
|
errorMessage: wizard.errorMessage,
|
|
18435
|
-
verification: wizard.verification
|
|
18340
|
+
verification: wizard.verification,
|
|
18341
|
+
paymentStatusRecovery: wizard.paymentStatusRecovery
|
|
18436
18342
|
},
|
|
18437
18343
|
actions: {
|
|
18438
18344
|
selectEvent: wizard.handleEventSelect,
|
|
@@ -18456,12 +18362,40 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18456
18362
|
next,
|
|
18457
18363
|
back,
|
|
18458
18364
|
submit,
|
|
18459
|
-
retry: wizard.handleRetry
|
|
18365
|
+
retry: wizard.handleRetry,
|
|
18366
|
+
checkPaymentStatus: wizard.handleCheckPaymentStatus,
|
|
18367
|
+
continueExistingPayment: wizard.handleContinueExistingPayment,
|
|
18368
|
+
returnToPayment: wizard.handleReturnToPayment,
|
|
18369
|
+
returnToBooking: wizard.handleReturnToBooking
|
|
18460
18370
|
}
|
|
18461
18371
|
},
|
|
18462
18372
|
wizard
|
|
18463
18373
|
};
|
|
18464
18374
|
}
|
|
18375
|
+
function useEventRegistrationBack(wizard) {
|
|
18376
|
+
return useCallback(() => {
|
|
18377
|
+
switch (wizard.step) {
|
|
18378
|
+
case "enter-details":
|
|
18379
|
+
wizard.setStep("select-tickets");
|
|
18380
|
+
return;
|
|
18381
|
+
case "select-payment":
|
|
18382
|
+
wizard.setStep("enter-details");
|
|
18383
|
+
return;
|
|
18384
|
+
case "select-tickets":
|
|
18385
|
+
if (!wizard.hasPreSelectedContext) wizard.setStep("select-event");
|
|
18386
|
+
return;
|
|
18387
|
+
case "select-event":
|
|
18388
|
+
case "error":
|
|
18389
|
+
case "success":
|
|
18390
|
+
case "submitting":
|
|
18391
|
+
case "redirecting":
|
|
18392
|
+
case "verifying-payment":
|
|
18393
|
+
case "verifying-timeout":
|
|
18394
|
+
case "payment-status":
|
|
18395
|
+
case "payment-failed": return;
|
|
18396
|
+
}
|
|
18397
|
+
}, [wizard]);
|
|
18398
|
+
}
|
|
18465
18399
|
function useEventRegistrationWizardControllerWithDeps(options, deps) {
|
|
18466
18400
|
const maxTicketsNum = normalizeEventRegistrationMaxTickets(options.maxTickets);
|
|
18467
18401
|
return { wizard: deps.useEventRegistrationWizard({
|
|
@@ -18517,7 +18451,7 @@ function resolvePaymentModel(wizard, directPaymentOptions) {
|
|
|
18517
18451
|
}
|
|
18518
18452
|
function resolveHeadlessDirectPaymentOptions(wizard) {
|
|
18519
18453
|
const eligibility = wizard.eligibility;
|
|
18520
|
-
if (!eligibility?.
|
|
18454
|
+
if (!eligibility?.requiresPayment || !eligibility.price) return [];
|
|
18521
18455
|
const event = wizard.selectedEvent ?? wizard.preSelectedEvent;
|
|
18522
18456
|
return buildEventRegistrationPaymentOptionsViewModel({
|
|
18523
18457
|
eventTitle: event?.title ?? "Event",
|