@riverbankcms/sdk 0.142.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.
Files changed (90) hide show
  1. package/dist/{PreviewEditorSidebar-Dk6Dt11f.mjs → PreviewEditorSidebar-DROGfMKi.mjs} +4 -4
  2. package/dist/{PreviewEditorUI-D6EQTsCA.mjs → PreviewEditorUI-BaRjhFu-.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-CC-EPkyQ.mjs → PreviewQueryProvider-BCYICImX.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-DH1n4ytY.mjs → SdkPreviewModeRuntime-OIABYLES.mjs} +5 -5
  5. package/dist/{SiteChromeCustomizeContext-DunIzY0K.mjs → SiteChromeCustomizeContext-ohjTvZbc.mjs} +491 -525
  6. package/dist/_dts/api/src/endpoints.d.ts +7 -0
  7. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +7 -0
  8. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +48 -41
  9. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -1
  10. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +8 -0
  11. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +95 -35
  12. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentStatusStep.d.ts +10 -0
  13. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +0 -2
  14. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +12 -1
  15. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.d.ts +2 -2
  16. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationCompletion.d.ts +1 -4
  17. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +12 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.d.ts +1 -1
  19. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +1 -0
  20. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.d.ts +4 -5
  21. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +9 -11
  22. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +56 -2
  23. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +10 -4
  24. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/usePaymentStatusRecovery.d.ts +23 -0
  25. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +1 -1
  26. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -4
  27. package/dist/_dts/commerce/src/purchase/eventCheckoutRecoveryWindow.d.ts +8 -0
  28. package/dist/_dts/commerce/src/purchase/index.d.ts +2 -1
  29. package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +1 -13
  30. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3113 -3077
  31. package/dist/_dts/sdk/src/version.d.ts +1 -1
  32. package/dist/client/{BookingConsentAgreement-CnJeq3_r.mjs → BookingConsentAgreement-BoCtvzzu.mjs} +2 -2
  33. package/dist/client/{DiscountCodeDisclosure-BINEO6J9.mjs → DiscountCodeDisclosure-B5S30nZk.mjs} +1 -1
  34. package/dist/client/{EventCombined.client-srxNQ6sZ.mjs → EventCombined.client-CeZ2-zSt.mjs} +5 -5
  35. package/dist/client/{EventListing.client-DbyVyGkX.mjs → EventListing.client-DJN3j8B3.mjs} +2 -2
  36. package/dist/client/{LeafletStaticMap-B-wpijzL.mjs → LeafletStaticMap-RjtGzDQT.mjs} +1 -1
  37. package/dist/client/{accordion-B-iUXU7n.mjs → accordion-DOmnDoyg.mjs} +1 -1
  38. package/dist/client/{bookingForm-BXYPke5q.mjs → bookingForm-C0vk7pgS.mjs} +5 -5
  39. package/dist/client/bookings.mjs +449 -525
  40. package/dist/client/{carousel-Cr4aj63H.mjs → carousel-BZJ7pno3.mjs} +1 -1
  41. package/dist/client/{cart-DibP9WWa.mjs → cart-CaeVAHJl.mjs} +3 -3
  42. package/dist/client/{checkout-CrSBVnL8.mjs → checkout-7wmoNDtG.mjs} +3 -3
  43. package/dist/client/client.mjs +518 -540
  44. package/dist/client/{context-Ces-AgdR.mjs → context-BOimxE3U.mjs} +12 -1
  45. package/dist/client/{dates-BXyNeNhB.mjs → dates-BnzVksi4.mjs} +2 -2
  46. package/dist/client/{eventCalendar-HwpPeqrH.mjs → eventCalendar-l-fpaslC.mjs} +7 -7
  47. package/dist/client/{eventCombined-BpFUkuEI.mjs → eventCombined-DGGvssK6.mjs} +3 -3
  48. package/dist/client/{eventDetails-DK_agiWy.mjs → eventDetails-DRiCm_hL.mjs} +4 -4
  49. package/dist/client/{eventListing-DhzHqP1c.mjs → eventListing-dph8loYX.mjs} +3 -3
  50. package/dist/client/{eventRegistration-BdQ_Dn2d.mjs → eventRegistration-ClBohmbY.mjs} +472 -530
  51. package/dist/client/{form-B1frcuzy.mjs → form-BLVVAnd3.mjs} +2 -2
  52. package/dist/client/{headerSection-CT5z460s.mjs → headerSection-DHy4C8Ix.mjs} +2 -2
  53. package/dist/client/hooks.mjs +12 -0
  54. package/dist/client/{locationMap-CIQXB9i2.mjs → locationMap-6HuS28ck.mjs} +2 -2
  55. package/dist/client/{newsletterForm-BYNYZSes.mjs → newsletterForm-xOdcOhZP.mjs} +2 -2
  56. package/dist/client/{pricing-CbTlAsmt.mjs → pricing-ChinRYFt.mjs} +1 -1
  57. package/dist/client/{productDetail-CR7Z3yjS.mjs → productDetail-0chA5gbK.mjs} +3 -3
  58. package/dist/client/{productList-DXj00vzR.mjs → productList-OoINA0h1.mjs} +3 -3
  59. package/dist/client/{propsDecoder-DiLiBdek.mjs → propsDecoder-CIZ-hbIG.mjs} +14 -1
  60. package/dist/client/rendering/client.mjs +506 -539
  61. package/dist/client/rendering/islands.mjs +17 -17
  62. package/dist/client/rendering.mjs +517 -539
  63. package/dist/client/{scrollToBlock-CrcbBf0h.mjs → scrollToBlock-BPZl0gPZ.mjs} +1 -1
  64. package/dist/client/{shop-DgqiB_1b.mjs → shop-CLJFqNIq.mjs} +6 -6
  65. package/dist/client/{shop-commerce-D_J781in.mjs → shop-commerce-PpANg5wB.mjs} +5 -5
  66. package/dist/client/{shop-commerce-store-PGUbDwqe.mjs → shop-commerce-store-TA_Kz2ku.mjs} +1 -1
  67. package/dist/client/{shopShared-C_Bb2zwG.mjs → shopShared-DzcFcA5g.mjs} +3 -3
  68. package/dist/client/{useEventFilters-CM17Xpr1.mjs → useEventFilters-CFU21QZo.mjs} +5 -5
  69. package/dist/preview-next/before-render.mjs +11 -0
  70. package/dist/preview-next/client/runtime.mjs +4 -4
  71. package/dist/preview-next/keepAlive.mjs +11 -0
  72. package/dist/preview-next/middleware.mjs +11 -0
  73. package/dist/{previewAuthStore-oVttoRDO.mjs → previewAuthStore-JA6-I_sL.mjs} +11 -0
  74. package/dist/{sdk-runtime-DhmuRhIX.mjs → sdk-runtime-CDKl0Fr7.mjs} +2 -2
  75. package/dist/{separator-C3hlg9LH.mjs → separator-BTp96X32.mjs} +1 -1
  76. package/dist/server/components.mjs +12 -2
  77. package/dist/server/config-validation.mjs +12 -0
  78. package/dist/server/config.mjs +12 -0
  79. package/dist/server/data.mjs +12 -0
  80. package/dist/server/index.mjs +12 -1
  81. package/dist/server/next.mjs +13 -3
  82. package/dist/server/page-converter.mjs +1 -0
  83. package/dist/server/prebuild.mjs +1 -1
  84. package/dist/server/rendering/server.mjs +12 -0
  85. package/dist/server/rendering.mjs +12 -2
  86. package/dist/server/routing.mjs +12 -0
  87. package/dist/server/server.mjs +13 -1
  88. package/package.json +1 -1
  89. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +0 -14
  90. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +0 -8
@@ -32591,6 +32591,18 @@ var init_wizardSteps$1 = __esmMin((() => {
32591
32591
  }));
32592
32592
  //#endregion
32593
32593
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationDerivations.ts
32594
+ /** Public requests share subject identity without copying the run's display sessions. */
32595
+ function toRegistrationRequestSubject(subject, attendanceMode) {
32596
+ return subject.kind === "occurrence" ? {
32597
+ kind: "occurrence",
32598
+ occurrenceId: subject.occurrenceId,
32599
+ attendanceMode: attendanceMode ?? void 0
32600
+ } : {
32601
+ kind: "wholeSeries",
32602
+ eventSeriesId: subject.eventSeriesId,
32603
+ attendanceMode: attendanceMode ?? void 0
32604
+ };
32605
+ }
32594
32606
  function eventMatchesOccurrenceId(event, occurrenceId) {
32595
32607
  return event.registrationSubject.kind === "occurrence" && (event.registrationSubject.occurrenceId === occurrenceId || event.selectionId === occurrenceId);
32596
32608
  }
@@ -32820,6 +32832,7 @@ function shellLabelForRegistrationStep(step, events) {
32820
32832
  case "redirecting":
32821
32833
  case "verifying-payment":
32822
32834
  case "verifying-timeout":
32835
+ case "payment-status":
32823
32836
  case "payment-failed": return "Details";
32824
32837
  }
32825
32838
  }
@@ -35947,6 +35960,17 @@ const NEWSLETTER_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
35947
35960
  //#region ../api/src/publicEventEndpointDefinitions.ts
35948
35961
  init_src$2();
35949
35962
  const PUBLIC_EVENT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
35963
+ checkPublicEventRegistrationNextStep: {
35964
+ path: "/public/sites/{siteId}/events/registration-next-step",
35965
+ method: "POST",
35966
+ auth: "public",
35967
+ responseKind: "json",
35968
+ errors: [
35969
+ "validation:invalid_input",
35970
+ "auth:forbidden",
35971
+ "server:internal_error"
35972
+ ]
35973
+ },
35950
35974
  listPublicEventCalendarWindow: {
35951
35975
  path: "/public/sites/{siteId}/events/calendar-window",
35952
35976
  method: "GET",
@@ -145566,6 +145590,10 @@ var init_endpoints = __esmMin((() => {
145566
145590
  method: "POST",
145567
145591
  authScope: "portal"
145568
145592
  },
145593
+ registrationNextStep: {
145594
+ path: "/public/sites/{siteId}/events/registration-next-step",
145595
+ method: "POST"
145596
+ },
145569
145597
  registrationStatus: {
145570
145598
  path: "/public/sites/{siteId}/events/registration-status",
145571
145599
  method: "GET"
@@ -146148,6 +146176,13 @@ function createBlockApi(config) {
146148
146176
  body: data
146149
146177
  });
146150
146178
  },
146179
+ async checkRegistrationNextStep(data) {
146180
+ const path = buildPath(EVENTS.registrationNextStep.path, { siteId: requireSiteId() });
146181
+ return request(EVENTS.registrationNextStep, {
146182
+ path,
146183
+ body: data
146184
+ });
146185
+ },
146151
146186
  async getEventRegistrationStatus(params) {
146152
146187
  const sid = requireSiteId();
146153
146188
  const path = buildPath(EVENTS.registrationStatus.path, { siteId: sid });
@@ -154056,7 +154091,7 @@ var init_eventPaymentOptions = __esmMin((() => {
154056
154091
  //#endregion
154057
154092
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.ts
154058
154093
  function hasBlockingExistingRegistration(input) {
154059
- return !input.hasWaitlistClaim && input.isAuthenticated && input.registration.kind !== "none";
154094
+ return !input.hasWaitlistClaim && input.isAuthenticated && input.registration.kind === "waitlisted";
154060
154095
  }
154061
154096
  function createInitialRegistrationFlowState(hasPreSelectedContext) {
154062
154097
  return {
@@ -154108,7 +154143,7 @@ function computeAutoSelection(input) {
154108
154143
  return { method: null };
154109
154144
  }
154110
154145
  function computeDirectPaymentSelection(eligibility) {
154111
- if (!eligibility?.canPayDirectly) return { method: null };
154146
+ if (!eligibility?.requiresPayment) return { method: null };
154112
154147
  const approvedKinds = getApprovedDirectPaymentCollectionOptionKinds(eligibility.paymentOptions);
154113
154148
  const collectionOptionKind = approvedKinds.includes("upfront") ? "upfront" : approvedKinds[0];
154114
154149
  return collectionOptionKind ? {
@@ -154122,7 +154157,7 @@ function isSelectionValid(input) {
154122
154157
  if (!eligibility) return selection.method === "stripe" || selection.method === "pass_bundle" || selection.method === "membership_bundle";
154123
154158
  switch (selection.method) {
154124
154159
  case "free": return eligibility.isFree;
154125
- case "stripe": return Boolean(eligibility.canPayDirectly && eligibility.price);
154160
+ case "stripe": return Boolean(eligibility.requiresPayment && eligibility.price);
154126
154161
  case "pass": return isAuthenticated && ticketsCount === 1 && !!selection.passId && eligibility.eligiblePasses.some((pass) => pass.id === selection.passId);
154127
154162
  case "membership": return isAuthenticated && ticketsCount === 1 && !!selection.membershipId && eligibility.eligibleMemberships.some((membership) => membership.id === selection.membershipId);
154128
154163
  case "pass_bundle": return ticketsCount === 1 && !!selection.bundlePassId && eligibility.availablePasses.some((pass) => pass.id === selection.bundlePassId);
@@ -154141,7 +154176,7 @@ function normalizeRegistrationFlowState(state) {
154141
154176
  ticketsCount: state.ticketsCount,
154142
154177
  passOptOut: nextPassOptOut
154143
154178
  });
154144
- const canKeepManualSelection = state.step === "select-payment" && state.selectionSource === "manual" && isSelectionValid({
154179
+ const canKeepManualSelection = state.step !== "select-tickets" && state.selectionSource === "manual" && isSelectionValid({
154145
154180
  selection: state.paymentSelection,
154146
154181
  isAuthenticated: state.isAuthenticated,
154147
154182
  eligibility: state.eligibility,
@@ -154233,7 +154268,7 @@ function resolveEventRegistrationSubmitPlan(input) {
154233
154268
  const selection = input.paymentSelection.method ? input.paymentSelection : void 0;
154234
154269
  if (input.canJoinWaitlist) return {
154235
154270
  ok: true,
154236
- args: withOptionalSelection({ method: "free" }, selection)
154271
+ args: { method: "free" }
154237
154272
  };
154238
154273
  switch (input.paymentSelection.method) {
154239
154274
  case "pass": return input.paymentSelection.passId ? {
@@ -154302,92 +154337,55 @@ var init_event_registration_headless_state = __esmMin((() => {
154302
154337
  init_event_registration_headless_planning();
154303
154338
  }));
154304
154339
  //#endregion
154305
- //#region ../blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.ts
154306
- /** Recovery may select held places; checkout still owns admission and payment validation. */
154307
- function checkoutRecoveryOptionAvailability(availability) {
154308
- if (availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable") return {
154309
- kind: "available",
154310
- remainingPlaces: null
154311
- };
154312
- return availability;
154340
+ //#region ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
154341
+ /** Ticket selection requests a quote; only the server admits a booking. */
154342
+ function canRequestTicketOption(availability) {
154343
+ return availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable";
154313
154344
  }
154314
- /**
154315
- * A form-only projection for the explicit existing-checkout path. It permits
154316
- * collecting the original selection without claiming a new place is available.
154317
- * The public checkout service identifies the customer and remains the admission
154318
- * authority; no reservation/customer data is exposed through this projection.
154319
- */
154320
- function getCheckoutRecoveryFormEligibility(eligibility) {
154321
- 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;
154322
- const amountCents = eligibility.price ?? 0;
154323
- if (amountCents <= 0 || !eligibility.currency || eligibility.availability.kind === "unavailable" && eligibility.availability.reason === "selectionRequired") return eligibility.registration.kind === "pending_payment" ? {
154324
- ...eligibility,
154325
- registration: { kind: "none" },
154326
- ticketTypes: eligibility.ticketTypes.map((option) => ({
154327
- ...option,
154328
- availability: checkoutRecoveryOptionAvailability(option.availability)
154329
- }))
154330
- } : eligibility;
154331
- const currency = eligibility.currency;
154332
- const paymentOptions = eligibility.paymentTerms.allowedOptions.map((option) => {
154333
- switch (option.kind) {
154334
- case "upfront": return {
154335
- kind: "payInFull",
154336
- amountCents,
154337
- currency
154338
- };
154339
- case "deferred_manual": return {
154340
- kind: "deferredManual",
154341
- amountCents,
154342
- currency
154343
- };
154344
- case "instalment_plan": return {
154345
- kind: "instalmentPlan",
154346
- amountCents,
154347
- currency
154348
- };
154349
- case "flexible_balance": return {
154350
- kind: "flexibleBalance",
154351
- amountCents,
154352
- currency
154353
- };
154354
- }
154355
- });
154356
- return {
154357
- ...eligibility,
154358
- registration: { kind: "none" },
154359
- availability: {
154360
- kind: "available",
154361
- remainingPlaces: null,
154362
- waitlistEnabled: eligibility.waitlistEnabled
154363
- },
154364
- eligible: paymentOptions.length > 0,
154365
- isFull: false,
154366
- canJoinWaitlist: false,
154367
- isFree: false,
154368
- requiresPayment: true,
154369
- canPayDirectly: paymentOptions.length > 0,
154370
- paymentOptions,
154371
- eligiblePasses: [],
154372
- eligibleMemberships: [],
154373
- ticketTypes: eligibility.ticketTypes.map((option) => ({
154374
- ...option,
154375
- availability: checkoutRecoveryOptionAvailability(option.availability)
154376
- }))
154377
- };
154345
+ function normalizeTicketSelectionLines(lines) {
154346
+ const quantitiesByTicketType = /* @__PURE__ */ new Map();
154347
+ for (const line of lines) {
154348
+ const quantity = Math.floor(line.quantity);
154349
+ if (quantity <= 0) continue;
154350
+ const key = line.pricingOptionId ?? null;
154351
+ quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
154352
+ }
154353
+ return [...quantitiesByTicketType.entries()].map(([pricingOptionId, quantity]) => ({
154354
+ pricingOptionId,
154355
+ quantity
154356
+ }));
154378
154357
  }
154379
- function isSoldOutEventSelectable(event, waitlistAvailable) {
154380
- return waitlistAvailable || canRecoverEventCheckout(event);
154358
+ function getTicketSelectionTotal(lines) {
154359
+ return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
154381
154360
  }
154382
- function canJoinWaitlistOutsideRecovery(event, attendanceMode, checkoutRecovery) {
154383
- return !checkoutRecovery && event !== null && canJoinEventWaitlist(event, { attendanceMode });
154361
+ function getTicketLineQuantity(lines, pricingOptionId) {
154362
+ return normalizeTicketSelectionLines(lines).find((line) => line.pricingOptionId === pricingOptionId)?.quantity ?? 0;
154384
154363
  }
154385
- function canRecoverEventCheckout(event) {
154386
- return event !== null && (event.registrationSubject.kind === "wholeSeries" || event.pricing.kind !== "free" && event.pricing.kind !== "external");
154364
+ function getSingleSelectedPricingOptionId(lines) {
154365
+ const normalized = normalizeTicketSelectionLines(lines);
154366
+ return normalized.length === 1 ? normalized[0]?.pricingOptionId ?? null : null;
154387
154367
  }
154388
- var init_checkoutRecovery = __esmMin((() => {
154389
- init_domain();
154390
- }));
154368
+ function hasValidPricingOptionSelection(input) {
154369
+ if (!input.selectionRequired) return true;
154370
+ if (input.lines.length === 0) return false;
154371
+ const availableOptionIds = new Set(input.visibleOptions.filter((option) => canRequestTicketOption(option.availability)).map((option) => option.pricingOptionId));
154372
+ return input.lines.every((line) => line.pricingOptionId !== null && availableOptionIds.has(line.pricingOptionId));
154373
+ }
154374
+ function setTicketLineQuantity(input) {
154375
+ const nextQuantity = Math.max(0, Math.floor(input.quantity));
154376
+ const normalized = normalizeTicketSelectionLines(input.lines).filter((line) => line.pricingOptionId !== input.pricingOptionId);
154377
+ if (nextQuantity <= 0) return normalized;
154378
+ return [...normalized, {
154379
+ pricingOptionId: input.pricingOptionId,
154380
+ quantity: nextQuantity
154381
+ }];
154382
+ }
154383
+ function getTicketTypeLineMax(input) {
154384
+ const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
154385
+ const maxByBlock = input.maxTickets - otherSelectedQuantity;
154386
+ return Math.max(0, maxByBlock);
154387
+ }
154388
+ var init_ticketSelectionLines = __esmMin((() => {}));
154391
154389
  //#endregion
154392
154390
  //#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
154393
154391
  function getPortalSubjectEmail(profile) {
@@ -154451,8 +154449,6 @@ function formatPassCreditUsageLabel(creditsRemaining) {
154451
154449
  return `Uses 1 of ${creditsRemaining} credits`;
154452
154450
  }
154453
154451
  function transformRegistrationOptionsResponse(response) {
154454
- const canJoinWaitlist = response.availability.kind === "waitlist";
154455
- const isFull = response.availability.remainingPlaces === 0 || response.availability.kind === "unavailable" && response.availability.reason === "full";
154456
154452
  const eligiblePasses = response.entitlements.passes.map((pass) => ({
154457
154453
  id: pass.customerPassId,
154458
154454
  passName: pass.passName,
@@ -154465,7 +154461,6 @@ function transformRegistrationOptionsResponse(response) {
154465
154461
  const eventAcceptsPasses = response.entitlements.requiresLoginForPasses || eligiblePasses.length > 0 || response.entitlements.availableForPurchase.passes.length > 0;
154466
154462
  const eventAcceptsMemberships = response.entitlements.requiresLoginForMemberships || eligibleMemberships.length > 0 || response.entitlements.availableForPurchase.memberships.length > 0;
154467
154463
  const monetaryPaymentAvailable = hasMonetaryPaymentOption(response);
154468
- const registrationAvailable = response.availability.kind === "available" || response.availability.kind === "waitlist";
154469
154464
  return {
154470
154465
  availability: response.availability,
154471
154466
  registration: response.registration,
@@ -154480,7 +154475,6 @@ function transformRegistrationOptionsResponse(response) {
154480
154475
  },
154481
154476
  transactions: []
154482
154477
  } : null,
154483
- eligible: response.registration.kind === "none" && registrationAvailable,
154484
154478
  requiresPayment: monetaryPaymentAvailable,
154485
154479
  pricingStrategy: response.pricing.strategy,
154486
154480
  paymentTerms: response.pricing.paymentTerms,
@@ -154495,16 +154489,12 @@ function transformRegistrationOptionsResponse(response) {
154495
154489
  currency: response.pricing.currency
154496
154490
  })),
154497
154491
  ticketTypes: response.pricing.options,
154498
- isFull,
154499
- waitlistEnabled: response.availability.waitlistEnabled,
154500
- canJoinWaitlist,
154501
154492
  price: response.pricing.subtotalCents,
154502
154493
  currency: response.pricing.currency,
154503
154494
  requiresAuthForPasses: response.entitlements.requiresLoginForPasses,
154504
154495
  requiresAuthForMemberships: response.entitlements.requiresLoginForMemberships,
154505
154496
  eligiblePasses,
154506
154497
  eligibleMemberships,
154507
- canPayDirectly: monetaryPaymentAvailable,
154508
154498
  eventAcceptsPasses,
154509
154499
  eventAcceptsMemberships,
154510
154500
  availablePasses: [...response.entitlements.availableForPurchase.passes],
@@ -154534,8 +154524,8 @@ function getVisibleTicketTypes(input) {
154534
154524
  })) : [];
154535
154525
  return (input.eligibility?.ticketTypes ?? eventTicketTypes).filter((ticketType) => ticketType.isActive && (!input.selectedAttendanceMode || (ticketType.attendanceScope ?? "both") === "both" || (ticketType.attendanceScope ?? "both") === input.selectedAttendanceMode));
154536
154526
  }
154537
- function getImplicitSingleAvailableTicketType(ticketTypes) {
154538
- return ticketTypes.length === 1 && ticketTypes[0]?.availability.kind === "available" ? ticketTypes[0] : null;
154527
+ function getImplicitSingleTicketType(ticketTypes) {
154528
+ return ticketTypes.length === 1 && ticketTypes[0] && canRequestTicketOption(ticketTypes[0].availability) ? ticketTypes[0] : null;
154539
154529
  }
154540
154530
  function findSelectedTicketType(input) {
154541
154531
  if (!input.selectedPricingOptionId) return null;
@@ -154548,6 +154538,7 @@ function findSelectedTicketType(input) {
154548
154538
  var ENTITLEMENT_SINGLE_TICKET_TOOLTIP;
154549
154539
  var init_utils = __esmMin((() => {
154550
154540
  init_src$2();
154541
+ init_ticketSelectionLines();
154551
154542
  init_shared();
154552
154543
  ENTITLEMENT_SINGLE_TICKET_TOOLTIP = "Only available for single-ticket bookings";
154553
154544
  }));
@@ -154560,7 +154551,6 @@ function getEventSelectionMode(events) {
154560
154551
  }
154561
154552
  var EventSelectionStep;
154562
154553
  var init_EventSelectionStep = __esmMin((() => {
154563
- init_checkoutRecovery();
154564
154554
  init_utils();
154565
154555
  init_domain();
154566
154556
  EventSelectionStep = ({ events, selectedEvent, onSelect, showVenue, showCapacity }) => {
@@ -154577,25 +154567,19 @@ var init_EventSelectionStep = __esmMin((() => {
154577
154567
  const remaining = getRemainingPlaces(selectMostOpenCapacitySource(event));
154578
154568
  const isSoldOut = isEventFull(event);
154579
154569
  const canJoinWaitlist = canJoinEventWaitlistOnAnyMode(event);
154580
- const isUnavailable = isSoldOut && !isSoldOutEventSelectable(event, canJoinWaitlist);
154581
154570
  const isLowCapacity = remaining.kind === "low";
154582
154571
  const capacityLabel = formatEventRemainingPlaces(event, { full: "Sold out" });
154583
154572
  const timeZone = event.timeZone ?? null;
154584
- const cardClasses = [
154585
- "er-event-card",
154586
- isSelected && "er-event-card--selected",
154587
- isUnavailable && "er-event-card--disabled"
154588
- ].filter(Boolean).join(" ");
154573
+ const cardClasses = ["er-event-card", isSelected && "er-event-card--selected"].filter(Boolean).join(" ");
154589
154574
  const badgeClasses = [
154590
154575
  "er-capacity-badge",
154591
- isUnavailable && "er-capacity-badge--soldout",
154576
+ isSoldOut && "er-capacity-badge--soldout",
154592
154577
  isLowCapacity && "er-capacity-badge--low",
154593
- (canJoinWaitlist || !isUnavailable && !isLowCapacity) && "er-capacity-badge--available"
154578
+ (canJoinWaitlist || !isSoldOut && !isLowCapacity) && "er-capacity-badge--available"
154594
154579
  ].filter(Boolean).join(" ");
154595
154580
  return /* @__PURE__ */ jsx("button", {
154596
154581
  type: "button",
154597
- onClick: () => !isUnavailable && onSelect(event),
154598
- disabled: isUnavailable,
154582
+ onClick: () => onSelect(event),
154599
154583
  className: cardClasses,
154600
154584
  children: /* @__PURE__ */ jsxs("div", {
154601
154585
  className: "er-event-option",
@@ -154623,44 +154607,15 @@ var init_EventSelectionStep = __esmMin((() => {
154623
154607
  };
154624
154608
  }));
154625
154609
  //#endregion
154626
- //#region ../blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.ts
154627
- /** Recovery belongs to the selected booking subject; changing events resets its scope. */
154628
- function useCheckoutRecovery(event, setStep) {
154629
- const [recoveryEventId, setRecoveryEventId] = useState(null);
154630
- return {
154631
- checkoutRecovery: event !== null && recoveryEventId === event.selectionId,
154632
- startCheckoutRecovery: useCallback(() => {
154633
- if (!event) return;
154634
- setRecoveryEventId(event.selectionId);
154635
- setStep("select-tickets");
154636
- }, [event, setStep])
154637
- };
154638
- }
154639
- /** Authenticated pending bookings enter the same form-only recovery path as guests. */
154640
- function useCheckoutRecoveryEligibility(eligibility, step, checkoutRecovery, startCheckoutRecovery) {
154641
- const registrationKind = eligibility?.registration.kind;
154642
- useEffect(() => {
154643
- if ((step === "select-event" || step === "select-tickets" || step === "enter-details" || step === "select-payment") && registrationKind === "pending_payment" && !checkoutRecovery) startCheckoutRecovery();
154644
- }, [
154645
- registrationKind,
154646
- step,
154647
- checkoutRecovery,
154648
- startCheckoutRecovery
154649
- ]);
154650
- return useMemo(() => checkoutRecovery ? getCheckoutRecoveryFormEligibility(eligibility) : eligibility, [checkoutRecovery, eligibility]);
154651
- }
154652
- var init_useCheckoutRecovery = __esmMin((() => {
154653
- init_checkoutRecovery();
154654
- }));
154655
- //#endregion
154656
154610
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.ts
154657
154611
  function resolveRegistrationRecoveryAction(step, action) {
154658
154612
  if (step === "payment-failed") return "payment-options";
154659
- if (step === "verifying-payment" || step === "verifying-timeout" || step === "redirecting") return "payment-status";
154613
+ if (step === "payment-status") return "none";
154614
+ if (step === "verifying-payment" || step === "verifying-timeout" || step === "redirecting") return "none";
154660
154615
  return action;
154661
154616
  }
154662
154617
  function canRecoverToWaitlist(eligibility) {
154663
- return Boolean(eligibility?.isFull && eligibility.canJoinWaitlist);
154618
+ return eligibility?.availability.kind === "waitlist" && eligibility.registration.kind !== "pending_payment";
154664
154619
  }
154665
154620
  function shouldRefreshAfterRegistrationError(step, action, enabled) {
154666
154621
  return enabled || step === "error" && action === "places";
@@ -154677,19 +154632,19 @@ function resetRegistrationAfterExpiry(input) {
154677
154632
  input.setErrorMessage("");
154678
154633
  input.setPendingRegistrationReference(null);
154679
154634
  }
154680
- /** Recovery never starts another payment. Unknown payment outcomes go to the portal. */
154635
+ /** Retry the retained submission in place; explicit payment uncertainty stays status-only. */
154681
154636
  function recoverRegistrationError(action, handlers) {
154682
154637
  switch (action) {
154683
154638
  case "none": return;
154684
154639
  case "portal":
154685
- case "payment-status":
154686
154640
  window.location.assign("/portal");
154687
154641
  return;
154688
154642
  case "event":
154689
154643
  window.location.assign(window.location.pathname);
154690
154644
  return;
154691
154645
  case "retry":
154692
- window.location.reload();
154646
+ handlers.clearError();
154647
+ handlers.setStep("select-payment");
154693
154648
  return;
154694
154649
  case "details":
154695
154650
  handlers.clearError();
@@ -154729,54 +154684,6 @@ function validateFormData(formData, requiresConsent = false) {
154729
154684
  }
154730
154685
  var init_validation = __esmMin((() => {}));
154731
154686
  //#endregion
154732
- //#region ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
154733
- function normalizeTicketSelectionLines(lines) {
154734
- const quantitiesByTicketType = /* @__PURE__ */ new Map();
154735
- for (const line of lines) {
154736
- const quantity = Math.floor(line.quantity);
154737
- if (quantity <= 0) continue;
154738
- const key = line.pricingOptionId ?? null;
154739
- quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
154740
- }
154741
- return [...quantitiesByTicketType.entries()].map(([pricingOptionId, quantity]) => ({
154742
- pricingOptionId,
154743
- quantity
154744
- }));
154745
- }
154746
- function getTicketSelectionTotal(lines) {
154747
- return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
154748
- }
154749
- function getTicketLineQuantity(lines, pricingOptionId) {
154750
- return normalizeTicketSelectionLines(lines).find((line) => line.pricingOptionId === pricingOptionId)?.quantity ?? 0;
154751
- }
154752
- function getSingleSelectedPricingOptionId(lines) {
154753
- const normalized = normalizeTicketSelectionLines(lines);
154754
- return normalized.length === 1 ? normalized[0]?.pricingOptionId ?? null : null;
154755
- }
154756
- function hasValidPricingOptionSelection(input) {
154757
- if (!input.selectionRequired) return true;
154758
- if (input.lines.length === 0) return false;
154759
- const availableOptionIds = new Set(input.visibleOptions.filter((option) => option.availability.kind === "available").map((option) => option.pricingOptionId));
154760
- return input.lines.every((line) => line.pricingOptionId !== null && availableOptionIds.has(line.pricingOptionId));
154761
- }
154762
- function setTicketLineQuantity(input) {
154763
- const nextQuantity = Math.max(0, Math.floor(input.quantity));
154764
- const normalized = normalizeTicketSelectionLines(input.lines).filter((line) => line.pricingOptionId !== input.pricingOptionId);
154765
- if (nextQuantity <= 0) return normalized;
154766
- return [...normalized, {
154767
- pricingOptionId: input.pricingOptionId,
154768
- quantity: nextQuantity
154769
- }];
154770
- }
154771
- function getTicketTypeLineMax(input) {
154772
- const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
154773
- const maxByBlock = input.maxTickets - otherSelectedQuantity;
154774
- const maxByEvent = input.availableSpots == null ? input.maxTickets : input.availableSpots - otherSelectedQuantity;
154775
- const maxByTicketType = input.ticketTypeRemainingCapacity ?? input.maxTickets;
154776
- return Math.max(0, Math.min(maxByBlock, maxByEvent, maxByTicketType));
154777
- }
154778
- var init_ticketSelectionLines = __esmMin((() => {}));
154779
- //#endregion
154780
154687
  //#region ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
154781
154688
  function eligibilityLookupReducer(state, action) {
154782
154689
  switch (action.type) {
@@ -154888,17 +154795,6 @@ function usePortalAuthWithDeps(deps) {
154888
154795
  logout
154889
154796
  };
154890
154797
  }
154891
- function toRegistrationOptionsSubject(subject, attendanceMode) {
154892
- return subject.kind === "occurrence" ? {
154893
- kind: "occurrence",
154894
- occurrenceId: subject.occurrenceId,
154895
- attendanceMode: attendanceMode ?? void 0
154896
- } : {
154897
- kind: "wholeSeries",
154898
- eventSeriesId: subject.eventSeriesId,
154899
- attendanceMode: attendanceMode ?? void 0
154900
- };
154901
- }
154902
154798
  function useEligibility(params) {
154903
154799
  return useEligibilityWithDeps(params, eventRegistrationHooksDeps);
154904
154800
  }
@@ -154939,7 +154835,7 @@ function useEligibilityWithDeps(params, deps) {
154939
154835
  requestIdRef.current = requestId;
154940
154836
  dispatch({ type: "loading-started" });
154941
154837
  try {
154942
- const subject = toRegistrationOptionsSubject(params.subject, params.attendanceMode);
154838
+ const subject = toRegistrationRequestSubject(params.subject, params.attendanceMode);
154943
154839
  const result = await api.getRegistrationOptions({
154944
154840
  subject,
154945
154841
  selections: ticketSelections.map((selection) => ({
@@ -155061,6 +154957,7 @@ var init_hooks = __esmMin((() => {
155061
154957
  init_api();
155062
154958
  init_utils();
155063
154959
  init_ticketSelectionLines();
154960
+ init_registrationDerivations();
155064
154961
  init_hooks_state();
155065
154962
  eventRegistrationHooksDeps = { useBlockApi };
155066
154963
  REGISTRATION_OPTIONS_DEBOUNCE_MS = 150;
@@ -155527,7 +155424,6 @@ var init_stripeMinimumCharge = __esmMin((() => {
155527
155424
  var init_stripeCheckoutReturnUrl = __esmMin((() => {}));
155528
155425
  var init_stateTransitions = __esmMin((() => {
155529
155426
  init_src$2();
155530
- init_assertNever();
155531
155427
  }));
155532
155428
  //#endregion
155533
155429
  //#region ../commerce/src/purchase/event-registration-errors.ts
@@ -155541,9 +155437,9 @@ var init_event_registration_errors = __esmMin((() => {
155541
155437
  message: "Booking is currently closed for this event. Please contact the organiser if you’d like to find out more.",
155542
155438
  action: "none"
155543
155439
  },
155544
- paymentUncertain: {
155545
- message: "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.",
155546
- action: "payment-status"
155440
+ paymentInvestigationRequired: {
155441
+ message: "We still can’t confirm your payment. Please don’t make another payment. Contact the organiser so they can check your booking.",
155442
+ action: "none"
155547
155443
  },
155548
155444
  paymentProviderUnavailable: {
155549
155445
  message: "We couldn’t reach the payment provider. Please try again in a minute.",
@@ -155595,6 +155491,7 @@ var init_event_registration_errors = __esmMin((() => {
155595
155491
  }
155596
155492
  };
155597
155493
  }));
155494
+ var init_eventCheckoutRecoveryWindow = __esmMin((() => {}));
155598
155495
  //#endregion
155599
155496
  //#region ../commerce/src/purchase/index.ts
155600
155497
  var init_purchase = __esmMin((() => {
@@ -155656,6 +155553,7 @@ var init_purchase = __esmMin((() => {
155656
155553
  init_stripeCheckoutReturnUrl();
155657
155554
  init_stateTransitions();
155658
155555
  init_event_registration_errors();
155556
+ init_eventCheckoutRecoveryWindow();
155659
155557
  init_stripeCommissionMetadata();
155660
155558
  }));
155661
155559
  //#endregion
@@ -156094,7 +155992,30 @@ function checkoutReturnCommand(params) {
156094
155992
  };
156095
155993
  return null;
156096
155994
  }
156097
- async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
155995
+ function handleCheckoutReturnOutcome(options, deps, context, outcome) {
155996
+ const { pending, params } = context;
155997
+ if (outcome.kind === "resolved") {
155998
+ deps.clearReturnParams();
155999
+ options.setPendingRegistrationReference(outcome.reference);
156000
+ options.setStep("verifying-payment");
156001
+ return "settled";
156002
+ }
156003
+ if (outcome.kind === "abandoned") {
156004
+ deps.clearReturnParams();
156005
+ options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
156006
+ options.setStep("select-payment");
156007
+ return "settled";
156008
+ }
156009
+ if (outcome.kind === "notFound" && params.registration === "cancelled" && (options.registrationSubject?.kind === "occurrence" || pending?.reference.scope === "occurrence")) {
156010
+ deps.clearReturnParams();
156011
+ options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
156012
+ options.setStep("select-payment");
156013
+ return "settled";
156014
+ }
156015
+ 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.");
156016
+ return outcome.kind === "notFound" ? "settled" : "retryable";
156017
+ }
156018
+ async function handleCheckoutReturn(options, deps, returnContextRef) {
156098
156019
  deps.cleanupStaleRegistrations();
156099
156020
  const params = deps.readReturnParams();
156100
156021
  if (params.registration !== "cancelled" && params.registration !== "success") return "settled";
@@ -156108,34 +156029,15 @@ async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
156108
156029
  }
156109
156030
  const { checkoutAttemptId } = command;
156110
156031
  const pending = deps.getPendingRegistration(siteId, checkoutAttemptId);
156111
- checkoutAttemptIdRef.current = checkoutAttemptId;
156032
+ returnContextRef.current = { checkoutAttemptId };
156112
156033
  if (pending) restorePendingPresentation(options, pending);
156113
156034
  options.setStep("verifying-payment");
156114
156035
  try {
156115
156036
  const outcome = await options.api.resolveEventCheckoutReturn(command);
156116
- switch (outcome.kind) {
156117
- case "resolved":
156118
- deps.clearReturnParams();
156119
- options.setPendingRegistrationReference(outcome.reference);
156120
- options.setStep("verifying-payment");
156121
- return "settled";
156122
- case "abandoned":
156123
- deps.clearReturnParams();
156124
- options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
156125
- options.setStep("select-payment");
156126
- return "settled";
156127
- case "notFound":
156128
- if (params.registration === "cancelled" && (options.registrationSubject?.kind === "occurrence" || pending?.reference.scope === "occurrence")) {
156129
- deps.clearReturnParams();
156130
- options.setErrorMessage("Your payment was cancelled. You can choose a payment option and try again.");
156131
- options.setStep("select-payment");
156132
- return "settled";
156133
- }
156134
- 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.");
156135
- return "settled";
156136
- case "reconciliationRequired": break;
156137
- }
156138
- 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.");
156037
+ return handleCheckoutReturnOutcome(options, deps, {
156038
+ pending,
156039
+ params
156040
+ }, outcome);
156139
156041
  } catch {
156140
156042
  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.");
156141
156043
  }
@@ -156144,9 +156046,16 @@ async function handleCheckoutReturn(options, deps, checkoutAttemptIdRef) {
156144
156046
  function useEventRegistrationStripeReturn(options) {
156145
156047
  return useEventRegistrationStripeReturnWithDeps(options, eventRegistrationStripeReturnDeps);
156146
156048
  }
156049
+ function completeVerifiedRegistration(options, deps, returnContext) {
156050
+ const siteId = options.api.config.siteId;
156051
+ const checkoutAttemptId = returnContext?.checkoutAttemptId;
156052
+ if (siteId && checkoutAttemptId) deps.clearPendingRegistration(siteId, checkoutAttemptId);
156053
+ options.setRegistrationResult({ status: "confirmed" });
156054
+ options.setStep("success");
156055
+ }
156147
156056
  function useEventRegistrationStripeReturnWithDeps(options, deps) {
156148
156057
  const { api, pendingRegistrationReference, setErrorMessage, setRegistrationResult, setStep, step } = options;
156149
- const checkoutAttemptIdRef = useRef(null);
156058
+ const returnContextRef = useRef(null);
156150
156059
  const lookupInFlightRef = useRef(false);
156151
156060
  const [lookupState, setLookupState] = useState("settled");
156152
156061
  const resolveReturn = useCallback(async () => {
@@ -156154,7 +156063,7 @@ function useEventRegistrationStripeReturnWithDeps(options, deps) {
156154
156063
  lookupInFlightRef.current = true;
156155
156064
  setLookupState("loading");
156156
156065
  try {
156157
- setLookupState(await handleCheckoutReturn(options, deps, checkoutAttemptIdRef));
156066
+ setLookupState(await handleCheckoutReturn(options, deps, returnContextRef));
156158
156067
  } finally {
156159
156068
  lookupInFlightRef.current = false;
156160
156069
  }
@@ -156177,13 +156086,8 @@ function useEventRegistrationStripeReturnWithDeps(options, deps) {
156177
156086
  resolveReturn();
156178
156087
  }, []);
156179
156088
  useEffect(() => {
156180
- if (verification.status === "completed") {
156181
- const siteId = api.config.siteId;
156182
- const checkoutAttemptId = checkoutAttemptIdRef.current;
156183
- if (siteId && checkoutAttemptId) deps.clearPendingRegistration(siteId, checkoutAttemptId);
156184
- setRegistrationResult({ status: "confirmed" });
156185
- setStep("success");
156186
- } else if (verification.status === "failed") {
156089
+ if (verification.status === "completed") completeVerifiedRegistration(options, deps, returnContextRef.current);
156090
+ else if (verification.status === "failed") {
156187
156091
  setErrorMessage("Please try again or choose another payment option. If this keeps happening, contact the organiser for help.");
156188
156092
  setStep("payment-failed");
156189
156093
  } else if (verification.status === "timeout") setStep("verifying-timeout");
@@ -156242,7 +156146,10 @@ function registrationErrorPresentation(error) {
156242
156146
  const reason = error instanceof BlockApiError ? parseEventRegistrationErrorReason(error.tag) : null;
156243
156147
  if (reason) return eventRegistrationErrors[reason];
156244
156148
  if (error instanceof BlockApiError && error.status < 500) return eventRegistrationErrors.invalidCommitInput;
156245
- return eventRegistrationErrors.paymentUncertain;
156149
+ return {
156150
+ message: "Something went wrong. Please try again.",
156151
+ action: "retry"
156152
+ };
156246
156153
  }
156247
156154
  var init_registrationErrorPresentation = __esmMin((() => {
156248
156155
  init_purchase();
@@ -156271,26 +156178,6 @@ function useEventRegistrationSubmit(options) {
156271
156178
  * and the balance left, which the block's copy cannot. Every other method keeps
156272
156179
  * whatever success message the site configured.
156273
156180
  */
156274
- function toRegistrationResult(result) {
156275
- if (result.alreadyRegistered) {
156276
- const waitlisted = result.status === "waitlist";
156277
- return {
156278
- status: result.status,
156279
- variant: "info",
156280
- title: waitlisted ? "Already waitlisted" : "Already registered",
156281
- message: result.message ?? (waitlisted ? "You are already on the waitlist for this event." : "You are already registered for this event.")
156282
- };
156283
- }
156284
- if (result.status === "waitlist") return {
156285
- status: "waitlist",
156286
- title: "Added to waitlist",
156287
- message: result.message ?? (typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.")
156288
- };
156289
- return {
156290
- status: result.status,
156291
- message: result.paymentMethod === "pass" ? result.message : void 0
156292
- };
156293
- }
156294
156181
  function useEventRegistrationSubmitWithDeps(options, deps) {
156295
156182
  /**
156296
156183
  * The command identity for the submission currently in progress.
@@ -156304,7 +156191,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
156304
156191
  * Identical retries retain the command after a lost response. Changed form
156305
156192
  * details get a new command so the server applies the new booking intent.
156306
156193
  */
156307
- const commandRef = useRef(null);
156194
+ const { commandRef } = options;
156308
156195
  const inFlightRef = useRef(null);
156309
156196
  const submit = async (method, passId, membershipId, selection, submitOptions) => {
156310
156197
  const target = options.registrationTarget;
@@ -156317,19 +156204,15 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
156317
156204
  const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
156318
156205
  try {
156319
156206
  let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
156320
- if (prepared.subject.kind === "wholeSeries" && method === "stripe") {
156321
- commandRef.current = null;
156322
- return await submitWholeSeriesCheckout(options, deps, {
156207
+ let request = buildRegistrationRequest(options, prepared, method, passId, membershipId);
156208
+ const intentKey = registrationRequestIntentKey(request);
156209
+ if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) {
156210
+ prepared = {
156323
156211
  ...prepared,
156324
- subject: prepared.subject
156325
- }, submitOptions);
156212
+ registrationCommandId: deps.createClientCommandId()
156213
+ };
156214
+ request = buildRegistrationRequest(options, prepared, method, passId, membershipId);
156326
156215
  }
156327
- const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
156328
- const intentKey = registrationRequestIntentKey(request);
156329
- if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
156330
- ...prepared,
156331
- registrationCommandId: deps.createClientCommandId()
156332
- };
156333
156216
  commandRef.current = {
156334
156217
  id: prepared.registrationCommandId,
156335
156218
  intentKey
@@ -156338,8 +156221,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
156338
156221
  ...request,
156339
156222
  registrationCommandId: prepared.registrationCommandId
156340
156223
  });
156341
- commandRef.current = null;
156342
- return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
156224
+ return await completeRegistrationSubmission(options, deps, prepared, result, submitOptions);
156343
156225
  } catch (error) {
156344
156226
  if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
156345
156227
  const { message, action } = registrationErrorPresentation(error);
@@ -156363,9 +156245,40 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
156363
156245
  return pending;
156364
156246
  };
156365
156247
  }
156366
- async function completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions) {
156367
- if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
156368
- options.setRegistrationResult(toRegistrationResult(result));
156248
+ async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
156249
+ switch (result.kind) {
156250
+ case "paymentStatusRequired":
156251
+ options.setPaymentStatusRecovery({
156252
+ kind: "ready",
156253
+ subject: result.subject
156254
+ });
156255
+ options.setStep("payment-status");
156256
+ return {
156257
+ ok: true,
156258
+ outcome: { kind: "payment_status" }
156259
+ };
156260
+ case "checkoutRequired":
156261
+ options.setPendingRegistrationReference(result.reference);
156262
+ savePendingCheckout(options, deps, prepared, result.submissionId, result.reference);
156263
+ options.setStep("redirecting");
156264
+ return redirectToCheckout(result.checkoutUrl, submitOptions);
156265
+ case "waitlisted":
156266
+ options.setRegistrationResult({
156267
+ status: "waitlist",
156268
+ title: "Added to waitlist",
156269
+ message: result.waitlist.message
156270
+ });
156271
+ break;
156272
+ case "bookingComplete":
156273
+ case "paymentDeferred":
156274
+ options.setPendingRegistrationReference(result.reference);
156275
+ options.setRegistrationResult({
156276
+ status: "confirmed",
156277
+ message: result.summary.paymentMethod === "pass" ? result.summary.message : void 0
156278
+ });
156279
+ break;
156280
+ }
156281
+ options.commandRef.current = null;
156369
156282
  options.setStep("success");
156370
156283
  return {
156371
156284
  ok: true,
@@ -156396,15 +156309,7 @@ function prepareSubmitContext(options, registrationCommandId, target, method, pa
156396
156309
  email: guest.email?.trim().toLowerCase() || void 0,
156397
156310
  phone: guest.phone?.trim() || void 0
156398
156311
  })) : void 0,
156399
- subject: target.subject.kind === "occurrence" ? {
156400
- kind: "occurrence",
156401
- occurrenceId: target.subject.occurrenceId,
156402
- attendanceMode: options.selectedAttendanceMode ?? void 0
156403
- } : {
156404
- kind: "wholeSeries",
156405
- eventSeriesId: target.subject.eventSeriesId,
156406
- attendanceMode: options.selectedAttendanceMode ?? void 0
156407
- }
156312
+ subject: toRegistrationRequestSubject(target.subject, options.selectedAttendanceMode)
156408
156313
  };
156409
156314
  }
156410
156315
  function resolveSelectionSnapshot(method, passId, membershipId, bundleProductId, selection) {
@@ -156428,85 +156333,6 @@ function resolveSelectionSnapshot(method, passId, membershipId, bundleProductId,
156428
156333
  if (method === "free") return { method };
156429
156334
  throw new Error("Choose an available payment option.");
156430
156335
  }
156431
- async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions) {
156432
- options.setStep("redirecting");
156433
- if (prepared.selectionSnapshot.method !== "stripe") throw new Error("Choose an available payment option.");
156434
- const checkoutAttemptId = deps.createClientCommandId();
156435
- const urls = buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: checkoutAttemptId });
156436
- const result = await options.api.createEventCheckout({
156437
- subject: prepared.subject,
156438
- ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
156439
- selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
156440
- email: options.formData.email.trim().toLowerCase(),
156441
- name: options.formData.name.trim(),
156442
- phone: options.formData.phone.trim() || void 0,
156443
- formData: options.formData,
156444
- consentAccepted: options.formData.consentAccepted,
156445
- altchaSolution: options.altchaSolution,
156446
- guests: prepared.guestsPayload,
156447
- claimToken: options.claimToken ?? void 0,
156448
- waitlistEntryId: options.waitlistEntryId ?? void 0,
156449
- discountCode: options.discountCode.trim() || void 0,
156450
- collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
156451
- checkoutAttemptId,
156452
- ...urls
156453
- });
156454
- if (result.scope !== "wholeSeries") throw new Error("Unexpected registration scope for event checkout.");
156455
- if ("waitlistEntryId" in result) {
156456
- options.setRegistrationResult({
156457
- status: "waitlist",
156458
- variant: result.alreadyRegistered ? "info" : void 0,
156459
- title: result.alreadyRegistered ? "Already waitlisted" : "Added to waitlist",
156460
- message: result.alreadyRegistered ? "You are already on the waitlist for this event." : "You've been added to the waitlist."
156461
- });
156462
- options.setStep("success");
156463
- return {
156464
- ok: true,
156465
- outcome: { kind: "completed" }
156466
- };
156467
- }
156468
- if (result.bypassed) return completeBypassedCheckout(options);
156469
- if (!result.checkoutUrl) throw new Error("Checkout URL missing");
156470
- savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
156471
- scope: "wholeSeries",
156472
- registrationId: result.registrationId
156473
- });
156474
- return redirectToCheckout(result.checkoutUrl, submitOptions);
156475
- }
156476
- function needsOccurrenceCheckout(result, method) {
156477
- return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
156478
- "stripe",
156479
- "pass_bundle",
156480
- "membership_bundle"
156481
- ].includes(method);
156482
- }
156483
- async function submitOccurrenceCheckout(options, deps, prepared, registration, method, submitOptions) {
156484
- const reference = {
156485
- scope: "occurrence",
156486
- attendeeId: registration.attendeeId
156487
- };
156488
- options.setPendingRegistrationReference(reference);
156489
- options.setStep("redirecting");
156490
- const checkoutAttemptId = deps.createClientCommandId();
156491
- const urls = buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: checkoutAttemptId });
156492
- const result = await options.api.createEventCheckout({
156493
- subject: {
156494
- kind: "occurrence",
156495
- attendeeId: registration.attendeeId
156496
- },
156497
- registrationCommandId: prepared.registrationCommandId,
156498
- checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
156499
- productId: prepared.bundleProductId,
156500
- discountCode: options.discountCode.trim() || void 0,
156501
- collectionOptionKind: prepared.selectionSnapshot.method === "stripe" ? prepared.selectionSnapshot.collectionOptionKind : void 0,
156502
- ...urls
156503
- });
156504
- if (result.scope !== "occurrence") throw new Error("Unexpected registration scope for event checkout.");
156505
- if (result.bypassed) return completeBypassedCheckout(options);
156506
- if (!result.checkoutUrl) throw new Error("Checkout URL missing");
156507
- if (prepared.subject.kind === "occurrence") savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference);
156508
- return redirectToCheckout(result.checkoutUrl, submitOptions);
156509
- }
156510
156336
  function savePendingCheckout(options, deps, prepared, checkoutAttemptId, reference) {
156511
156337
  const siteId = options.api.config.siteId;
156512
156338
  if (!siteId) return;
@@ -156519,14 +156345,6 @@ function savePendingCheckout(options, deps, prepared, checkoutAttemptId, referen
156519
156345
  paymentSelection: prepared.selectionSnapshot
156520
156346
  });
156521
156347
  }
156522
- function completeBypassedCheckout(options) {
156523
- options.setRegistrationResult({ status: "confirmed" });
156524
- options.setStep("success");
156525
- return {
156526
- ok: true,
156527
- outcome: { kind: "completed" }
156528
- };
156529
- }
156530
156348
  function redirectToCheckout(checkoutUrl, submitOptions) {
156531
156349
  if (submitOptions?.redirect !== "manual") window.location.href = checkoutUrl;
156532
156350
  return {
@@ -156538,12 +156356,23 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
156538
156356
  };
156539
156357
  }
156540
156358
  function registrationRequestIntentKey(request) {
156541
- const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
156542
- return JSON.stringify(intent);
156359
+ const { registrationCommandId: _command, altchaSolution: _proof, checkout, ...intent } = request;
156360
+ return JSON.stringify({
156361
+ ...intent,
156362
+ checkout: checkout ? {
156363
+ discountCode: checkout.discountCode,
156364
+ collectionOptionKind: checkout.collectionOptionKind
156365
+ } : void 0
156366
+ });
156543
156367
  }
156544
- function buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId) {
156368
+ function buildRegistrationRequest(options, prepared, method, passId, membershipId) {
156545
156369
  return {
156546
156370
  registrationCommandId: prepared.registrationCommandId,
156371
+ checkout: {
156372
+ ...buildCheckoutReturnUrls("registration", EVENT_REGISTRATION_ANCHOR_ID, { [EVENT_REGISTRATION_CHECKOUT_ATTEMPT_PARAM]: prepared.registrationCommandId }),
156373
+ discountCode: options.discountCode.trim() || void 0,
156374
+ collectionOptionKind: prepared.selectionSnapshot.method === "stripe" ? prepared.selectionSnapshot.collectionOptionKind : void 0
156375
+ },
156547
156376
  subject: prepared.subject,
156548
156377
  ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
156549
156378
  selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
@@ -156568,6 +156397,7 @@ var init_useEventRegistrationSubmit = __esmMin((() => {
156568
156397
  init_shared();
156569
156398
  init_registrationErrorPresentation();
156570
156399
  init_constants();
156400
+ init_registrationDerivations();
156571
156401
  init_sessionStorage();
156572
156402
  init_ticketSelectionLines();
156573
156403
  eventRegistrationSubmitDeps = {
@@ -156785,23 +156615,128 @@ var init_useWaitlistClaimRestoration = __esmMin((() => {
156785
156615
  }));
156786
156616
  //#endregion
156787
156617
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationCompletion.ts
156618
+ function isSelectionSoldOut(availability) {
156619
+ return availability?.kind === "unavailable" && availability.reason === "full";
156620
+ }
156788
156621
  function resolveRegistrationAvailabilityBlocker(input) {
156789
156622
  if (input.hasWaitlistClaim) return null;
156790
156623
  if (input.eligibilityError) return input.eligibilityError;
156791
156624
  if (!input.eligibility) return "Registration is not available for this event.";
156625
+ if (input.eligibility.registration.kind === "pending_payment") return null;
156626
+ if (isSelectionSoldOut(input.eligibility.availability)) return null;
156792
156627
  if (input.eligibility.availability.kind === "unavailable" && input.eligibility.availability.reason === "paymentUnavailable") return "Payment options are not available for this event.";
156793
- if (input.eligibility.availability.kind === "unavailable" || !input.eligibility.eligible) return "Registration is not available for this event.";
156628
+ if (input.eligibility.availability.kind === "unavailable" || input.eligibility.registration.kind === "waitlisted") return "Registration is not available for this event.";
156794
156629
  return null;
156795
156630
  }
156796
156631
  function resolvePricingSelectionBlocker(input) {
156797
156632
  if (input.selectionRequired && !input.hasValidSelection) return "Choose at least one available ticket to continue.";
156798
156633
  return input.slidingScaleSelectionMessage;
156799
156634
  }
156800
- function isSoldOutWithoutWaitlist(input) {
156801
- return Boolean(!input.hasWaitlistClaim && input.eligibility?.isFull && !input.eligibility.canJoinWaitlist);
156802
- }
156803
156635
  var init_registrationCompletion = __esmMin((() => {}));
156804
156636
  //#endregion
156637
+ //#region ../blocks/src/system/runtime/nodes/event-registration/usePaymentStatusRecovery.ts
156638
+ function isCheckableRecovery(state) {
156639
+ return state.kind === "ready" || state.kind === "processing" || state.kind === "temporarilyUnavailable";
156640
+ }
156641
+ function assistanceRequired(recovery) {
156642
+ return {
156643
+ kind: "assistanceRequired",
156644
+ subject: recovery.subject
156645
+ };
156646
+ }
156647
+ function applyStatusOutcome(outcome, recovery, setters, setRecovery) {
156648
+ if (outcome.kind === "resolved") {
156649
+ setters.setPendingRegistrationReference(outcome.reference);
156650
+ setters.setRegistrationResult({ status: "confirmed" });
156651
+ setRecovery(null);
156652
+ setters.setStep("success");
156653
+ return;
156654
+ }
156655
+ switch (outcome.kind) {
156656
+ case "paymentProcessing":
156657
+ setRecovery({
156658
+ ...recovery,
156659
+ kind: "processing"
156660
+ });
156661
+ return;
156662
+ case "paymentAvailable":
156663
+ setRecovery({
156664
+ ...recovery,
156665
+ kind: "paymentAvailable",
156666
+ checkoutUrl: outcome.checkoutUrl
156667
+ });
156668
+ return;
156669
+ case "paymentCheckUnavailable":
156670
+ setRecovery({
156671
+ ...recovery,
156672
+ kind: "temporarilyUnavailable"
156673
+ });
156674
+ return;
156675
+ case "paymentRetryAvailable":
156676
+ setRecovery({
156677
+ ...recovery,
156678
+ kind: "retryAvailable"
156679
+ });
156680
+ return;
156681
+ case "abandoned":
156682
+ case "notFound":
156683
+ case "reconciliationRequired":
156684
+ case "paymentAssistanceRequired":
156685
+ setRecovery(assistanceRequired(recovery));
156686
+ return;
156687
+ }
156688
+ }
156689
+ function usePaymentStatusRecovery(options) {
156690
+ const [recovery, setRecovery] = useState(null);
156691
+ const checkRef = useRef(null);
156692
+ return {
156693
+ recovery,
156694
+ showRecovery: useCallback((next) => setRecovery(next), []),
156695
+ check: useCallback(() => {
156696
+ if (!recovery || !isCheckableRecovery(recovery) || checkRef.current) return;
156697
+ const pending = (async () => {
156698
+ setRecovery({
156699
+ ...recovery,
156700
+ kind: "checking"
156701
+ });
156702
+ try {
156703
+ applyStatusOutcome(await options.api.resolveEventCheckoutReturn({
156704
+ kind: "checkStatus",
156705
+ subject: recovery.subject
156706
+ }), recovery, options, setRecovery);
156707
+ } catch {
156708
+ setRecovery({
156709
+ ...recovery,
156710
+ kind: "temporarilyUnavailable"
156711
+ });
156712
+ }
156713
+ })();
156714
+ checkRef.current = pending;
156715
+ pending.finally(() => {
156716
+ if (checkRef.current === pending) checkRef.current = null;
156717
+ });
156718
+ }, [options, recovery]),
156719
+ continuePayment: useCallback(() => {
156720
+ if (recovery?.kind === "paymentAvailable") window.location.assign(recovery.checkoutUrl);
156721
+ }, [recovery]),
156722
+ returnToPayment: useCallback(() => {
156723
+ if (recovery?.kind !== "retryAvailable") return;
156724
+ options.beginNewSubmission();
156725
+ setRecovery(null);
156726
+ options.setOptionsRefreshKey((value) => value + 1);
156727
+ options.setStep("select-payment");
156728
+ }, [options, recovery]),
156729
+ returnToBooking: useCallback(() => {
156730
+ if (recovery?.kind !== "assistanceRequired") return;
156731
+ options.beginNewSubmission();
156732
+ setRecovery(null);
156733
+ options.setOptionsRefreshKey((value) => value + 1);
156734
+ options.setStep("select-tickets");
156735
+ }, [options, recovery])
156736
+ };
156737
+ }
156738
+ var init_usePaymentStatusRecovery = __esmMin((() => {}));
156739
+ //#endregion
156805
156740
  //#region ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
156806
156741
  function usesTieredPricing(event) {
156807
156742
  return event !== null && event !== void 0 ? publicEventPricingStrategy(event.pricing) === "tiered" : false;
@@ -156848,6 +156783,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156848
156783
  const [errorAction, setErrorAction] = useState("retry");
156849
156784
  const [optionsRefreshKey, setOptionsRefreshKey] = useState(0);
156850
156785
  const [altchaSolution, setAltchaSolution] = useState(null);
156786
+ const [checkingNextStep, setCheckingNextStep] = useState(false);
156851
156787
  const { authState: portalAuthState, profile: portalProfile } = deps.usePortalAuth();
156852
156788
  const waitlistClaim = deps.useWaitlistClaim();
156853
156789
  const [showMagicLinkModal, setShowMagicLinkModal] = useState(false);
@@ -156874,28 +156810,29 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156874
156810
  }), [options.occurrenceContext, selectedEvent]);
156875
156811
  const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
156876
156812
  const currentEvent = selectedEvent ?? preSelectedEvent;
156813
+ const commandRef = useRef(null);
156877
156814
  const setStep = useCallback((nextStep) => {
156878
156815
  dispatchFlow({
156879
156816
  type: "set-step",
156880
156817
  step: nextStep
156881
156818
  });
156882
156819
  }, []);
156883
- const { checkoutRecovery, startCheckoutRecovery } = useCheckoutRecovery(currentEvent, setStep);
156884
- const currentEventUsesTicketTypes = usesTieredPricing(currentEvent);
156885
- const currentCanJoinWaitlist = canJoinWaitlistOutsideRecovery(currentEvent, selectedAttendanceMode, checkoutRecovery);
156886
- const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
156820
+ const { recovery: paymentStatusRecovery, showRecovery: setPaymentStatusRecovery, check: handleCheckPaymentStatus, continuePayment: handleContinueExistingPayment, returnToPayment: handleReturnToPayment, returnToBooking: handleReturnToBooking } = usePaymentStatusRecovery({
156821
+ api,
156822
+ beginNewSubmission: () => {
156823
+ commandRef.current = null;
156824
+ },
156825
+ setPendingRegistrationReference,
156826
+ setRegistrationResult,
156827
+ setOptionsRefreshKey,
156828
+ setStep
156829
+ });
156830
+ const usesTicketTypeSelections = usesTieredPricing(currentEvent);
156887
156831
  const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
156888
156832
  event: currentEvent,
156889
156833
  eligibility: null,
156890
156834
  selectedAttendanceMode
156891
- }).map((option) => checkoutRecovery ? {
156892
- ...option,
156893
- availability: checkoutRecoveryOptionAvailability(option.availability)
156894
- } : option), [
156895
- currentEvent,
156896
- selectedAttendanceMode,
156897
- checkoutRecovery
156898
- ]);
156835
+ }), [currentEvent, selectedAttendanceMode]);
156899
156836
  const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
156900
156837
  const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
156901
156838
  const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
@@ -156933,7 +156870,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156933
156870
  isAuthenticated: portalAuthState === "authenticated",
156934
156871
  occurrenceId: registrationOccurrenceId
156935
156872
  });
156936
- const eligibility = useCheckoutRecoveryEligibility(eligibilityResult.eligibility, step, checkoutRecovery, startCheckoutRecovery);
156873
+ const eligibility = eligibilityResult.eligibility;
156937
156874
  const eligibilityLoading = eligibilityResult.isLoading;
156938
156875
  const eligibilityError = eligibilityResult.error;
156939
156876
  const portalCreditState = eligibilityResult.creditState;
@@ -157045,14 +156982,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157045
156982
  event: currentEvent,
157046
156983
  eligibility,
157047
156984
  selectedAttendanceMode
157048
- }).map((option) => checkoutRecovery ? {
157049
- ...option,
157050
- availability: checkoutRecoveryOptionAvailability(option.availability)
157051
- } : option), [
156985
+ }), [
157052
156986
  currentEvent,
157053
156987
  selectedAttendanceMode,
157054
- eligibility,
157055
- checkoutRecovery
156988
+ eligibility
157056
156989
  ]);
157057
156990
  const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
157058
156991
  const selectedTicketType = useMemo(() => findSelectedTicketType({
@@ -157076,12 +157009,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157076
157009
  const event = currentEvent;
157077
157010
  if (!usesTieredPricing(event)) return false;
157078
157011
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
157079
- return checkoutRecovery || !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
157080
- }, [
157081
- currentEvent,
157082
- selectedAttendanceMode,
157083
- checkoutRecovery
157084
- ]);
157012
+ return true;
157013
+ }, [currentEvent, selectedAttendanceMode]);
157085
157014
  const hasValidTicketSelection = hasValidPricingOptionSelection({
157086
157015
  selectionRequired: ticketTypeSelectionRequired,
157087
157016
  lines: normalizedSelectedTicketLines,
@@ -157092,8 +157021,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157092
157021
  if (selectedTicketLines.length > 0) setSelectedTicketLines([]);
157093
157022
  return;
157094
157023
  }
157095
- const availableTicketTypes = eventTicketTypesForSelection.filter((ticketType) => ticketType.availability.kind === "available");
157096
- const implicitTicketType = getImplicitSingleAvailableTicketType(eventTicketTypesForSelection);
157024
+ const availableTicketTypes = eventTicketTypesForSelection.filter((ticketType) => canRequestTicketOption(ticketType.availability));
157025
+ const implicitTicketType = getImplicitSingleTicketType(eventTicketTypesForSelection);
157097
157026
  if (implicitTicketType && normalizedSelectedTicketLines.length === 0) {
157098
157027
  setSelectedTicketLines([{
157099
157028
  pricingOptionId: implicitTicketType.pricingOptionId,
@@ -157160,6 +157089,26 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157160
157089
  selectedEventSlidingScale,
157161
157090
  selectedSlidingAmount
157162
157091
  ]);
157092
+ const checkDetailsNextStep = async () => {
157093
+ if (portalAuthState === "authenticated" || waitlistClaim.claim || eligibility?.availability.kind === "available" || !registrationTarget) return { kind: canRecoverToWaitlist(eligibility) ? "waitlist" : "continue" };
157094
+ setCheckingNextStep(true);
157095
+ try {
157096
+ return await api.checkRegistrationNextStep({
157097
+ subject: toRegistrationRequestSubject(registrationTarget.subject, selectedAttendanceMode),
157098
+ selections: ticketSelections,
157099
+ selectedSlidingAmount: selectedSlidingAmount ?? void 0,
157100
+ email: formData.email,
157101
+ altchaSolution
157102
+ });
157103
+ } catch {
157104
+ return {
157105
+ kind: "unavailable",
157106
+ message: "We could not check availability. Please try again."
157107
+ };
157108
+ } finally {
157109
+ setCheckingNextStep(false);
157110
+ }
157111
+ };
157163
157112
  const handleDetailsComplete = async () => {
157164
157113
  const blockDetailsCompletion = (message) => {
157165
157114
  setErrorAction("places");
@@ -157191,11 +157140,10 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157191
157140
  message: "Check the highlighted fields and try again."
157192
157141
  };
157193
157142
  }
157194
- if (isSoldOutWithoutWaitlist({
157195
- hasWaitlistClaim: waitlistClaim.claim !== null,
157196
- eligibility
157197
- })) return blockDetailsCompletion("Sorry, there aren’t enough places left for your selection. Please check the available places and choose again.");
157198
- if (!eligibility?.canJoinWaitlist && requiresPaymentStep({
157143
+ const next = await checkDetailsNextStep();
157144
+ if (next.kind === "unavailable") return blockDetailsCompletion(next.message);
157145
+ const canJoinWaitlist = next.kind === "waitlist";
157146
+ if (!canJoinWaitlist && requiresPaymentStep({
157199
157147
  eventRequiresPayment,
157200
157148
  paymentSelection
157201
157149
  })) {
@@ -157208,7 +157156,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157208
157156
  const submitPlan = resolveEventRegistrationSubmitPlan({
157209
157157
  paymentSelection,
157210
157158
  eventRequiresPayment,
157211
- canJoinWaitlist: eligibility?.canJoinWaitlist
157159
+ canJoinWaitlist
157212
157160
  });
157213
157161
  if (!submitPlan.ok) return blockDetailsCompletion(submitPlan.message);
157214
157162
  const submitResult = await handleSubmit(submitPlan.args.method, submitPlan.args.passId, submitPlan.args.membershipId, submitPlan.args.selection);
@@ -157226,7 +157174,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157226
157174
  const submitPlan = resolveEventRegistrationSubmitPlan({
157227
157175
  paymentSelection,
157228
157176
  eventRequiresPayment,
157229
- canJoinWaitlist: eligibility?.canJoinWaitlist
157177
+ canJoinWaitlist: false
157230
157178
  });
157231
157179
  if (!submitPlan.ok) {
157232
157180
  setErrorMessage(submitPlan.message);
@@ -157258,6 +157206,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157258
157206
  const selectionMethod = paymentSelection.method;
157259
157207
  const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
157260
157208
  const handleSubmit = deps.useEventRegistrationSubmit({
157209
+ commandRef,
157261
157210
  setErrorAction,
157262
157211
  api,
157263
157212
  registrationTarget,
@@ -157274,7 +157223,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157274
157223
  setPendingRegistrationReference,
157275
157224
  setStep,
157276
157225
  setRegistrationResult: (result) => setRegistrationResult(result),
157277
- setErrorMessage
157226
+ setErrorMessage,
157227
+ setPaymentStatusRecovery
157278
157228
  });
157279
157229
  const handleEventSelect = (event) => {
157280
157230
  setSelectedEvent(event);
@@ -157333,8 +157283,6 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157333
157283
  scopedEvents,
157334
157284
  preSelectedEvent,
157335
157285
  hasPreSelectedContext,
157336
- checkoutRecovery,
157337
- startCheckoutRecovery,
157338
157286
  step,
157339
157287
  setStep,
157340
157288
  selectedEvent,
@@ -157388,7 +157336,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157388
157336
  waitlistClaim,
157389
157337
  eligibility,
157390
157338
  registrationOptionsState: eligibilityResult.state,
157391
- eligibilityLoading,
157339
+ eligibilityLoading: eligibilityLoading || checkingNextStep,
157392
157340
  eligibilityError,
157393
157341
  existingRegistration: existingRegistrationResult.registration,
157394
157342
  existingRegistrationLoading: existingRegistrationResult.isLoading || portalAuthState === "authenticated" && eligibilityLoading,
@@ -157408,6 +157356,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157408
157356
  discountContext,
157409
157357
  shouldShowDiscountToggle,
157410
157358
  verification,
157359
+ paymentStatusRecovery,
157360
+ handleCheckPaymentStatus,
157361
+ handleContinueExistingPayment,
157362
+ handleReturnToPayment,
157363
+ handleReturnToBooking,
157411
157364
  handleDetailsComplete,
157412
157365
  handlePaymentSelect,
157413
157366
  handleUseCardInsteadOfPass,
@@ -157419,12 +157372,9 @@ function useEventRegistrationWizardWithDeps(options, deps) {
157419
157372
  }
157420
157373
  var eventRegistrationWizardDeps;
157421
157374
  var init_useEventRegistrationWizard = __esmMin((() => {
157422
- init_checkoutRecovery();
157423
- init_useCheckoutRecovery();
157424
157375
  init_src$2();
157425
157376
  init_registrationErrorRecovery();
157426
157377
  init_api();
157427
- init_domain();
157428
157378
  init_validation();
157429
157379
  init_hooks();
157430
157380
  init_portalLogout();
@@ -157444,6 +157394,7 @@ var init_useEventRegistrationWizard = __esmMin((() => {
157444
157394
  init_waitlistClaimRestoration();
157445
157395
  init_useWaitlistClaimRestoration();
157446
157396
  init_registrationCompletion();
157397
+ init_usePaymentStatusRecovery();
157447
157398
  eventRegistrationWizardDeps = {
157448
157399
  usePortalAuth,
157449
157400
  useEligibility,
@@ -157627,7 +157578,6 @@ var init_ErrorStep = __esmMin((() => {
157627
157578
  start: "Start again",
157628
157579
  details: "Check my details",
157629
157580
  "payment-options": "View payment options",
157630
- "payment-status": "Check payment status",
157631
157581
  portal: "View my bookings",
157632
157582
  event: "View event"
157633
157583
  };
@@ -157646,7 +157596,7 @@ var init_ErrorStep = __esmMin((() => {
157646
157596
  className: "er-text--muted er-message",
157647
157597
  children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
157648
157598
  }),
157649
- actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
157599
+ actions: action === "none" ? void 0 : action === "portal" ? /* @__PURE__ */ jsx("a", {
157650
157600
  href: "/portal",
157651
157601
  className: "er-retry-btn",
157652
157602
  children: labels[action]
@@ -157907,8 +157857,11 @@ var init_EventRegistrationSummaryBar = __esmMin((() => {
157907
157857
  */
157908
157858
  function resolveDetailsButtonText(input) {
157909
157859
  const { wizard } = input;
157910
- if (wizard.eligibility?.canJoinWaitlist) return "Join waitlist";
157911
- if (!input.hasWaitlistClaim && wizard.eligibility?.isFull) return "Sold out";
157860
+ const availability = wizard.eligibility?.availability;
157861
+ const full = availability?.kind === "waitlist" || isSelectionSoldOut(availability);
157862
+ if (wizard.portalAuthState !== "authenticated" && full) return "Continue";
157863
+ if (canRecoverToWaitlist(wizard.eligibility)) return "Join waitlist";
157864
+ if (!input.hasWaitlistClaim && full && wizard.eligibility?.registration.kind !== "pending_payment") return "Sold out";
157912
157865
  if (wizard.paymentSelection.method === "pass") return "Book using class pass";
157913
157866
  if (wizard.paymentSelection.method === "membership") return input.fallbackText;
157914
157867
  return wizard.eventRequiresPayment ? "Continue to payment" : input.fallbackText;
@@ -157923,44 +157876,28 @@ function isExistingRegistrationBlocking$1(wizard) {
157923
157876
  hasWaitlistClaim: wizard.waitlistClaim.claim !== null
157924
157877
  });
157925
157878
  }
157926
- /**
157927
- * Full for the visitor's selected attendance mode (or the whole event when no
157928
- * mode is chosen) with no waitlist to fall back on. Reads the same capacity
157929
- * source as the steps above the action bar so the button never disagrees
157930
- * with them on a hybrid event.
157931
- */
157932
- function isFullWithNoWaitlist(event, attendanceMode) {
157933
- if (!event) return false;
157934
- const source = selectEventCapacitySource(event, attendanceMode);
157935
- return getEventAvailability(source).isFull && !source.waitlistEnabled;
157936
- }
157937
157879
  function resolveTicketSelectionContinueLabel(input) {
157938
157880
  if (input.isCheckingExistingRegistration) return "Checking registration...";
157939
157881
  if (input.registrationOptionsPending) return "Checking availability...";
157940
157882
  if (input.registrationOptionsFailed) return "Availability unavailable";
157941
157883
  if (input.hasExistingRegistration) return resolveExistingRegistrationLabel(input.wizard);
157942
- if (input.isSoldOutWithoutWaitlist) return "Sold out";
157943
157884
  if (input.ticketTypeSelectionBlocked) return "Choose a ticket";
157944
157885
  return "Continue";
157945
157886
  }
157946
157887
  function SelectTicketsActions(props) {
157947
157888
  const { wizard } = props;
157948
- const hasWaitlistClaim = wizard.waitlistClaim.claim !== null;
157949
- const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
157950
157889
  const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
157951
157890
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
157952
- const isSoldOutWithoutWaitlist = !wizard.checkoutRecovery && !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
157953
157891
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
157954
157892
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
157955
157893
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
157956
- const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
157894
+ const isContinueDisabled = registrationOptionsPending || registrationOptionsFailed || isCheckingExistingRegistration || hasExistingRegistration || ticketTypeSelectionBlocked;
157957
157895
  const continueLabel = resolveTicketSelectionContinueLabel({
157958
157896
  wizard,
157959
157897
  registrationOptionsPending,
157960
157898
  registrationOptionsFailed,
157961
157899
  isCheckingExistingRegistration,
157962
157900
  hasExistingRegistration,
157963
- isSoldOutWithoutWaitlist,
157964
157901
  ticketTypeSelectionBlocked
157965
157902
  });
157966
157903
  return /* @__PURE__ */ jsxs("div", {
@@ -157991,8 +157928,12 @@ function EnterDetailsActions(props) {
157991
157928
  const { wizard } = props;
157992
157929
  const hasWaitlistClaim = wizard.waitlistClaim.claim !== null;
157993
157930
  const isCheckingEligibility = wizard.eligibilityLoading;
157994
- const eligibilityUnavailable = !hasWaitlistClaim && (Boolean(wizard.eligibilityError) || !wizard.eligibility || wizard.eligibility.availability.kind === "unavailable" || !wizard.eligibility.eligible);
157995
- const isSoldOut = !hasWaitlistClaim && wizard.eligibility?.isFull === true && wizard.eligibility.canJoinWaitlist !== true;
157931
+ const eligibilityUnavailable = Boolean(resolveRegistrationAvailabilityBlocker({
157932
+ hasWaitlistClaim,
157933
+ eligibility: wizard.eligibility,
157934
+ eligibilityError: wizard.eligibilityError
157935
+ }));
157936
+ const isSoldOut = !hasWaitlistClaim && wizard.portalAuthState === "authenticated" && wizard.eligibility?.registration.kind !== "pending_payment" && isSelectionSoldOut(wizard.eligibility?.availability);
157996
157937
  const isContinueDisabled = isCheckingEligibility || eligibilityUnavailable || isSoldOut;
157997
157938
  const continueLabel = isCheckingEligibility ? "Checking availability..." : wizard.eligibilityError ? "Availability unavailable" : eligibilityUnavailable ? "Registration unavailable" : resolveDetailsButtonText({
157998
157939
  wizard,
@@ -158043,6 +157984,7 @@ function EventRegistrationWizardActions(props) {
158043
157984
  case "redirecting":
158044
157985
  case "verifying-payment":
158045
157986
  case "verifying-timeout":
157987
+ case "payment-status":
158046
157988
  case "payment-failed": return null;
158047
157989
  case "select-event": return null;
158048
157990
  case "select-tickets": return /* @__PURE__ */ jsx(SelectTicketsActions, { ...props });
@@ -158054,7 +157996,8 @@ function EventRegistrationWizardActions(props) {
158054
157996
  var init_EventRegistrationWizardActions = __esmMin((() => {
158055
157997
  init_registrationStateMachine();
158056
157998
  init_spinner();
158057
- init_domain();
157999
+ init_registrationCompletion();
158000
+ init_registrationErrorRecovery();
158058
158001
  }));
158059
158002
  //#endregion
158060
158003
  //#region ../blocks/src/system/runtime/nodes/event-registration/siteCreditPreview.ts
@@ -158135,7 +158078,7 @@ var init_siteCreditPreview = __esmMin((() => {
158135
158078
  function resolvePaymentStepStatus(input) {
158136
158079
  if (input.loading) return "loading";
158137
158080
  if (input.error || !input.eligibility) return "error";
158138
- if (input.eligibility.registration.kind !== "none" || !input.eligibility.eligible && !input.eligibility.isFree) return "not-eligible";
158081
+ if (input.eligibility.registration.kind === "waitlisted" || input.eligibility.paymentOptions.length === 0) return "not-eligible";
158139
158082
  return "ready";
158140
158083
  }
158141
158084
  function shouldPromptForLogin(status, isAuthenticated, eligibility) {
@@ -158170,7 +158113,7 @@ function UnavailableEntitlementMessage(props) {
158170
158113
  ] });
158171
158114
  }
158172
158115
  function IneligiblePaymentPanel(props) {
158173
- if (props.eligibility.isFull && !props.eligibility.canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
158116
+ if (isSelectionSoldOut(props.eligibility.availability)) return /* @__PURE__ */ jsxs("div", {
158174
158117
  className: "rb-reg-stack er-stack",
158175
158118
  children: [/* @__PURE__ */ jsx("h3", {
158176
158119
  className: "er-title",
@@ -158239,26 +158182,23 @@ function PaymentBlockingPanel(props) {
158239
158182
  })
158240
158183
  });
158241
158184
  if (!props.eligibility) return /* @__PURE__ */ jsx(MissingEligibilityPanel, {});
158242
- if (props.eligibility.registration.kind !== "none") {
158243
- const isBooked = props.eligibility.registration.kind === "booked";
158244
- return /* @__PURE__ */ jsxs("div", {
158245
- className: "rb-reg-stack er-stack",
158246
- children: [/* @__PURE__ */ jsx("h3", {
158247
- className: "er-title",
158248
- children: isBooked ? "Already booked" : "Already on the waitlist"
158249
- }), /* @__PURE__ */ jsxs("div", {
158250
- className: "er-center",
158251
- children: [/* @__PURE__ */ jsx("p", {
158252
- className: "er-text er-text--muted",
158253
- children: isBooked ? "You already have a booking for this event. Please check your bookings to see its status. If you need help, contact the organiser." : "You're already on the waitlist for this event."
158254
- }), /* @__PURE__ */ jsx("a", {
158255
- href: "/portal",
158256
- className: "er-retry-btn",
158257
- children: "View my bookings"
158258
- })]
158185
+ if (props.eligibility.registration.kind === "waitlisted") return /* @__PURE__ */ jsxs("div", {
158186
+ className: "rb-reg-stack er-stack",
158187
+ children: [/* @__PURE__ */ jsx("h3", {
158188
+ className: "er-title",
158189
+ children: "Already on the waitlist"
158190
+ }), /* @__PURE__ */ jsxs("div", {
158191
+ className: "er-center",
158192
+ children: [/* @__PURE__ */ jsx("p", {
158193
+ className: "er-text er-text--muted",
158194
+ children: "You're already on the waitlist for this event."
158195
+ }), /* @__PURE__ */ jsx("a", {
158196
+ href: "/portal",
158197
+ className: "er-retry-btn",
158198
+ children: "View my bookings"
158259
158199
  })]
158260
- });
158261
- }
158200
+ })]
158201
+ });
158262
158202
  if (props.eligibility.isFree) return /* @__PURE__ */ jsxs("div", {
158263
158203
  className: "rb-reg-stack er-stack",
158264
158204
  children: [/* @__PURE__ */ jsx("h3", {
@@ -158279,7 +158219,7 @@ function PaymentBlockingPanel(props) {
158279
158219
  })]
158280
158220
  })]
158281
158221
  });
158282
- return props.eligibility.eligible ? null : /* @__PURE__ */ jsx(IneligiblePaymentPanel, {
158222
+ return props.eligibility.paymentOptions.length > 0 ? null : /* @__PURE__ */ jsx(IneligiblePaymentPanel, {
158283
158223
  eligibility: props.eligibility,
158284
158224
  email: props.email,
158285
158225
  isAuthenticated: props.isAuthenticated,
@@ -158289,6 +158229,7 @@ function PaymentBlockingPanel(props) {
158289
158229
  var init_PaymentBlockingPanel = __esmMin((() => {
158290
158230
  init_buttons();
158291
158231
  init_spinner();
158232
+ init_registrationCompletion();
158292
158233
  }));
158293
158234
  //#endregion
158294
158235
  //#region ../blocks/src/system/runtime/nodes/event-registration/types.ts
@@ -158418,7 +158359,7 @@ function SlidingScaleAmountField(props) {
158418
158359
  }
158419
158360
  function TicketTypeQuantityRows(props) {
158420
158361
  const totalSelectedQuantity = getTicketSelectionTotal(props.ticketSelections);
158421
- const effectiveMaxTickets = props.availableSpots == null ? props.maxTickets : Math.min(props.maxTickets, props.availableSpots);
158362
+ const effectiveMaxTickets = props.maxTickets;
158422
158363
  return /* @__PURE__ */ jsxs("div", {
158423
158364
  className: "er-ticket-lines",
158424
158365
  children: [
@@ -158428,16 +158369,14 @@ function TicketTypeQuantityRows(props) {
158428
158369
  "aria-label": props.bookingUnit === "place" ? "Places" : "Tickets",
158429
158370
  children: props.ticketTypes.map((ticketType) => {
158430
158371
  const quantity = getTicketLineQuantity(props.ticketSelections, ticketType.pricingOptionId);
158431
- const disabled = ticketType.availability.kind === "unavailable";
158372
+ const disabled = !canRequestTicketOption(ticketType.availability);
158432
158373
  const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
158433
158374
  const ticketTypeRemainingLabel = formatTicketTypeRemaining(ticketType.availability.remainingPlaces);
158434
158375
  const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, props.currency) : "Free";
158435
158376
  const maxAllowed = disabled ? 0 : getTicketTypeLineMax({
158436
158377
  currentQuantity: quantity,
158437
158378
  totalSelectedQuantity,
158438
- maxTickets: props.maxTickets,
158439
- availableSpots: props.availableSpots,
158440
- ticketTypeRemainingCapacity: ticketType.availability.remainingPlaces
158379
+ maxTickets: props.maxTickets
158441
158380
  });
158442
158381
  return /* @__PURE__ */ jsxs("div", {
158443
158382
  className: `er-ticket-line${disabled ? " er-ticket-line--disabled" : ""}`,
@@ -158542,33 +158481,13 @@ function AttendanceModeTiles(props) {
158542
158481
  })
158543
158482
  });
158544
158483
  }
158545
- function getMaxAllowedTicketCount(input) {
158546
- if (input.canJoinWaitlist) return input.maxTickets;
158547
- if (!input.usesTicketTypes) return Math.min(input.maxTickets, input.availableSpots ?? input.maxTickets);
158548
- if (!input.hasSelectedTicketType) return 1;
158549
- return Math.max(1, Math.min(input.maxTickets, input.selectedTicketTypeRemainingCapacity ?? input.maxTickets, input.availableSpots ?? input.maxTickets));
158550
- }
158551
158484
  function resolveTicketSelectionPricing(event) {
158552
158485
  return {
158553
158486
  mode: event ? publicEventPricingStrategy(event.pricing) : void 0,
158554
158487
  currency: event ? publicEventPricingCurrency(event.pricing) : null
158555
158488
  };
158556
158489
  }
158557
- function CheckoutRecoveryEntry(props) {
158558
- return props.onContinue ? /* @__PURE__ */ jsx("button", {
158559
- type: "button",
158560
- className: "er-back-btn",
158561
- onClick: props.onContinue,
158562
- children: "Continue an existing booking"
158563
- }) : null;
158564
- }
158565
- function getTicketSelectionCapacity(event, attendanceMode, checkoutRecovery) {
158566
- if (checkoutRecovery) return {
158567
- availableSpots: null,
158568
- isSoldOut: false,
158569
- canJoinWaitlist: false,
158570
- eventAvailabilityLabel: null
158571
- };
158490
+ function getTicketSelectionCapacity(event, attendanceMode) {
158572
158491
  const source = event ? selectEventCapacitySource(event, attendanceMode) : null;
158573
158492
  const availability = source ? getEventAvailability(source) : null;
158574
158493
  const canJoinWaitlist = source ? canJoinEventWaitlist(source) : false;
@@ -158585,29 +158504,21 @@ var init_TicketSelectionStep = __esmMin((() => {
158585
158504
  init_domain();
158586
158505
  init_utils();
158587
158506
  init_ticketSelectionLines();
158588
- TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" }, checkoutRecovery = false, onCheckoutRecovery }) => {
158507
+ TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" } }) => {
158589
158508
  const unit = bookingUnit.kind;
158590
158509
  const deliveryMode = event?.deliveryMode ?? "in_person";
158591
158510
  const attendanceModes = event?.attendanceModes ?? [];
158592
- const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode, checkoutRecovery);
158511
+ const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode);
158593
158512
  const { mode: eventPricingMode, currency: eventPricingCurrency } = resolveTicketSelectionPricing(event);
158594
- const usesTicketTypes = eventPricingMode === "tiered" && !canJoinWaitlist;
158513
+ const usesTicketTypes = eventPricingMode === "tiered";
158595
158514
  const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
158596
158515
  event,
158597
158516
  eligibility: null,
158598
158517
  selectedAttendanceMode
158599
158518
  }) : [];
158600
- const implicitTicketType = usesTicketTypes ? getImplicitSingleAvailableTicketType(visibleTicketTypes) : null;
158601
158519
  const noVisibleTicketTypes = usesTicketTypes && visibleTicketTypes.length === 0;
158602
- const hasAvailableTicketTypes = usesTicketTypes && visibleTicketTypes.some((ticketType) => ticketType.availability.kind === "available");
158603
- const maxAllowed = getMaxAllowedTicketCount({
158604
- canJoinWaitlist,
158605
- usesTicketTypes,
158606
- maxTickets,
158607
- availableSpots,
158608
- selectedTicketTypeRemainingCapacity: implicitTicketType?.availability.remainingPlaces ?? null,
158609
- hasSelectedTicketType: implicitTicketType !== null
158610
- });
158520
+ const hasAvailableTicketTypes = usesTicketTypes && visibleTicketTypes.some((ticketType) => canRequestTicketOption(ticketType.availability));
158521
+ const maxAllowed = maxTickets;
158611
158522
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) return /* @__PURE__ */ jsxs("div", {
158612
158523
  className: "rb-reg-stack er-stack",
158613
158524
  children: [
@@ -158626,20 +158537,6 @@ var init_TicketSelectionStep = __esmMin((() => {
158626
158537
  })
158627
158538
  ]
158628
158539
  });
158629
- if (isSoldOut && !canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
158630
- className: "rb-reg-stack er-stack",
158631
- children: [
158632
- /* @__PURE__ */ jsx("h3", {
158633
- className: "er-title",
158634
- children: "Sold out"
158635
- }),
158636
- /* @__PURE__ */ jsx("p", {
158637
- className: "er-text er-text--muted",
158638
- children: "Sorry you missed out! This event is fully booked."
158639
- }),
158640
- /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })
158641
- ]
158642
- });
158643
158540
  if (!eventPricingCurrency) return /* @__PURE__ */ jsx("div", {
158644
158541
  className: "rb-reg-stack er-stack",
158645
158542
  children: /* @__PURE__ */ jsx("p", {
@@ -158706,14 +158603,14 @@ var init_TicketSelectionStep = __esmMin((() => {
158706
158603
  })]
158707
158604
  })
158708
158605
  ] }),
158709
- canJoinWaitlist && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
158606
+ isSoldOut && !canJoinWaitlist && /* @__PURE__ */ jsx("p", {
158710
158607
  className: "er-text er-text--muted",
158711
- children: "This event is currently full. Continue to join the waitlist if a place opens up."
158712
- }), /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })] }),
158713
- checkoutRecovery && /* @__PURE__ */ jsx("p", {
158608
+ children: "This event is fully booked."
158609
+ }),
158610
+ canJoinWaitlist && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("p", {
158714
158611
  className: "er-text er-text--muted",
158715
- children: "Enter the details from your earlier booking. We’ll check your checkout before continuing to payment."
158716
- })
158612
+ children: "This event is currently full. Continue to join the waitlist if a place opens up."
158613
+ }) })
158717
158614
  ]
158718
158615
  });
158719
158616
  };
@@ -159301,7 +159198,7 @@ var init_PaymentSelectionStep = __esmMin((() => {
159301
159198
  const occurrenceId = occurrenceContext?.id ?? (event?.registrationSubject.kind === "occurrence" ? event.registrationSubject.occurrenceId : "");
159302
159199
  const selectedMethod = selectedSelection.method;
159303
159200
  const totalPrice = directPaymentTotalCents;
159304
- const canShowDirectPaymentOptions = Boolean(eligibility?.eligible && eligibility.canPayDirectly && eligibility.price);
159201
+ const canShowDirectPaymentOptions = Boolean(eligibility?.requiresPayment && eligibility.price);
159305
159202
  const directPaymentOptions = eligibility && canShowDirectPaymentOptions ? buildEventRegistrationPaymentOptionsViewModel({
159306
159203
  eventTitle: event?.title ?? "Event",
159307
159204
  approvedPaymentOptions: eligibility.paymentOptions,
@@ -159364,7 +159261,7 @@ var init_PaymentSelectionStep = __esmMin((() => {
159364
159261
  onRequestLogin
159365
159262
  });
159366
159263
  if (eligibilityLoading || eligibilityError || !eligibility) return blockingPanel;
159367
- if (eligibility.isFree || !eligibility.eligible) return blockingPanel;
159264
+ if (eligibility.isFree || paymentStepStatus !== "ready") return blockingPanel;
159368
159265
  const isMultiTicket = areEntitlementsDisabledForTicketCount(ticketsCount);
159369
159266
  return /* @__PURE__ */ jsxs("div", {
159370
159267
  className: "rb-reg-stack er-stack",
@@ -159583,7 +159480,7 @@ var init_VerifyingTimeoutStep = __esmMin((() => {
159583
159480
  title,
159584
159481
  body: /* @__PURE__ */ jsx("p", {
159585
159482
  className: "er-text--muted er-message",
159586
- children: message
159483
+ children: onCheckAgain ? message : "We still can’t confirm your payment. Please don’t make another payment. Contact the organiser so they can check your booking."
159587
159484
  }),
159588
159485
  actionsClassName: "er-button-group",
159589
159486
  actions: onCheckAgain ? /* @__PURE__ */ jsx("button", {
@@ -159591,11 +159488,7 @@ var init_VerifyingTimeoutStep = __esmMin((() => {
159591
159488
  onClick: onCheckAgain,
159592
159489
  className: "er-btn er-btn--primary",
159593
159490
  children: "Check payment status"
159594
- }) : /* @__PURE__ */ jsx("a", {
159595
- href: "/portal",
159596
- className: "er-btn er-btn--primary",
159597
- children: "Check payment status"
159598
- }),
159491
+ }) : void 0,
159599
159492
  secondaryBody: supportEmail ? /* @__PURE__ */ jsxs("p", {
159600
159493
  className: "er-text--sm er-text--muted er-message",
159601
159494
  children: [
@@ -159785,6 +159678,7 @@ function EventRegistrationWizardContent(props) {
159785
159678
  case "redirecting":
159786
159679
  case "verifying-payment":
159787
159680
  case "verifying-timeout":
159681
+ case "payment-status":
159788
159682
  case "payment-failed": return null;
159789
159683
  case "select-event": return /* @__PURE__ */ jsx(EventSelectionStep, {
159790
159684
  events: wizard.scopedEvents,
@@ -159800,8 +159694,6 @@ function EventRegistrationWizardContent(props) {
159800
159694
  onBookForSomeoneElse: wizard.handleBookForSomeoneElse
159801
159695
  }), /* @__PURE__ */ jsx(TicketSelectionStep, {
159802
159696
  event: wizard.selectedEvent,
159803
- checkoutRecovery: wizard.checkoutRecovery,
159804
- onCheckoutRecovery: canRecoverEventCheckout(wizard.selectedEvent) ? wizard.startCheckoutRecovery : void 0,
159805
159697
  occurrenceContext: wizard.occurrenceContext,
159806
159698
  selectedAttendanceMode: wizard.selectedAttendanceMode,
159807
159699
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
@@ -159829,13 +159721,90 @@ var init_EventRegistrationWizardContent = __esmMin((() => {
159829
159721
  init_client();
159830
159722
  init_src();
159831
159723
  init_shared();
159832
- init_checkoutRecovery();
159833
159724
  init_registrationStateMachine();
159834
159725
  init_siteCreditPreview();
159835
159726
  init_PaymentBlockingPanel();
159836
159727
  init_event_registration();
159837
159728
  }));
159838
159729
  //#endregion
159730
+ //#region ../blocks/src/system/runtime/nodes/event-registration/PaymentStatusStep.tsx
159731
+ function presentation(state) {
159732
+ switch (state.kind) {
159733
+ case "ready": return {
159734
+ title: "We haven’t confirmed your payment yet",
159735
+ message: "We’ve saved your booking details, but we haven’t been able to confirm that your payment was successful. Please don’t make another payment. Select Check payment status to get the latest update.",
159736
+ action: { label: "Check payment status" }
159737
+ };
159738
+ case "checking": return {
159739
+ title: "We haven’t confirmed your payment yet",
159740
+ message: "We’ve saved your booking details, but we haven’t been able to confirm that your payment was successful. Please don’t make another payment.",
159741
+ action: {
159742
+ label: "Checking payment…",
159743
+ disabled: true
159744
+ }
159745
+ };
159746
+ case "processing": return {
159747
+ title: "Your payment is still being processed",
159748
+ message: "Please don’t make another payment. You can check its status again in a moment.",
159749
+ action: { label: "Check payment status" }
159750
+ };
159751
+ case "paymentAvailable": return {
159752
+ title: "Your payment hasn’t been completed",
159753
+ message: "Your booking details are still saved. Continue to payment to finish your booking.",
159754
+ action: { label: "Continue to payment" }
159755
+ };
159756
+ case "retryAvailable": return {
159757
+ title: "Continue your booking",
159758
+ message: "You can return to payment. We’ll check your booking, any existing payment and availability before starting another checkout.",
159759
+ action: { label: "Return to payment" }
159760
+ };
159761
+ case "temporarilyUnavailable": return {
159762
+ title: "We couldn’t check your payment",
159763
+ message: "Please don’t make another payment yet. Try checking again in a moment.",
159764
+ action: { label: "Check payment status" }
159765
+ };
159766
+ case "assistanceRequired": return {
159767
+ title: "We still can’t confirm your payment",
159768
+ message: "Please don’t make another payment. Contact the organiser so they can check your booking.",
159769
+ action: { label: "Return to booking" }
159770
+ };
159771
+ }
159772
+ }
159773
+ function PaymentStatusStep(props) {
159774
+ const view = presentation(props.state);
159775
+ const onClick = props.state.kind === "paymentAvailable" ? props.onContinuePayment : props.state.kind === "retryAvailable" ? props.onReturnToPayment : props.state.kind === "assistanceRequired" ? props.onReturnToBooking : props.onCheck;
159776
+ return /* @__PURE__ */ jsx(TerminalPanel, {
159777
+ tone: "warning",
159778
+ className: "er-center",
159779
+ titleClassName: "er-title--lg er-message",
159780
+ icon: /* @__PURE__ */ jsx(StateIcon, {
159781
+ variant: "warning",
159782
+ children: /* @__PURE__ */ jsx(ClockIcon, {})
159783
+ }),
159784
+ title: view.title,
159785
+ body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
159786
+ className: "er-text--muted er-message",
159787
+ children: view.message
159788
+ }), /* @__PURE__ */ jsx("span", {
159789
+ className: "rb-sr-only",
159790
+ "aria-live": "polite",
159791
+ "aria-atomic": "true",
159792
+ children: props.state.kind === "checking" ? "Checking payment…" : view.title
159793
+ })] }),
159794
+ actionsClassName: "er-button-group",
159795
+ actions: view.action ? /* @__PURE__ */ jsx("button", {
159796
+ type: "button",
159797
+ onClick,
159798
+ disabled: view.action.disabled,
159799
+ className: "er-btn er-btn--primary",
159800
+ children: /* @__PURE__ */ jsx("span", { children: view.action.label })
159801
+ }) : void 0
159802
+ });
159803
+ }
159804
+ var init_PaymentStatusStep = __esmMin((() => {
159805
+ init_shared();
159806
+ }));
159807
+ //#endregion
159839
159808
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.tsx
159840
159809
  function EventPortalAuthPrompt(props) {
159841
159810
  return /* @__PURE__ */ jsxs("div", {
@@ -159920,6 +159889,13 @@ function EventRegistrationTerminalState(props) {
159920
159889
  message: wizard.verification.status === "timeout" ? void 0 : wizard.errorMessage,
159921
159890
  supportEmail: props.supportEmail
159922
159891
  });
159892
+ case "payment-status": return wizard.paymentStatusRecovery ? /* @__PURE__ */ jsx(PaymentStatusStep, {
159893
+ state: wizard.paymentStatusRecovery,
159894
+ onCheck: wizard.handleCheckPaymentStatus,
159895
+ onContinuePayment: wizard.handleContinueExistingPayment,
159896
+ onReturnToPayment: wizard.handleReturnToPayment,
159897
+ onReturnToBooking: wizard.handleReturnToBooking
159898
+ }) : null;
159923
159899
  case "success": return wizard.registrationResult ? /* @__PURE__ */ jsx(SuccessStep, {
159924
159900
  title: wizard.registrationResult.title,
159925
159901
  variant: wizard.registrationResult.variant,
@@ -159928,7 +159904,7 @@ function EventRegistrationTerminalState(props) {
159928
159904
  case "error": return /* @__PURE__ */ jsx(ErrorStep, {
159929
159905
  message: wizard.errorMessage,
159930
159906
  action: wizard.errorAction,
159931
- canJoinWaitlist: wizard.eligibility?.isFull && wizard.eligibility.canJoinWaitlist,
159907
+ canJoinWaitlist: wizard.eligibility?.availability.kind === "waitlist" && wizard.eligibility.registration.kind !== "pending_payment",
159932
159908
  onRetry: wizard.handleRetry
159933
159909
  });
159934
159910
  case "select-event":
@@ -159990,6 +159966,7 @@ var init_EventRegistrationSurface = __esmMin((() => {
159990
159966
  init_EventRegistrationWizardActions();
159991
159967
  init_EventRegistrationWizardContent();
159992
159968
  init_PaymentFailedStep();
159969
+ init_PaymentStatusStep();
159993
159970
  init_StepIndicator();
159994
159971
  init_SuccessStep();
159995
159972
  init_VerifyingPaymentStep();
@@ -160127,6 +160104,7 @@ function getWizardStepLabel(input) {
160127
160104
  case "redirecting":
160128
160105
  case "verifying-payment":
160129
160106
  case "verifying-timeout":
160107
+ case "payment-status":
160130
160108
  case "payment-failed": return "";
160131
160109
  }
160132
160110
  }
@@ -165910,7 +165888,7 @@ var SimpleCache = class {
165910
165888
  * 1. This constant
165911
165889
  * 2. The "version" field in package.json
165912
165890
  */
165913
- const SDK_VERSION = "0.142.0";
165891
+ const SDK_VERSION = "0.143.0";
165914
165892
  //#endregion
165915
165893
  //#region src/client/error.ts
165916
165894
  let _Symbol$for;