@riverbankcms/sdk 0.134.0 → 0.135.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 (258) hide show
  1. package/CHANGELOG.md +4 -3
  2. package/README.md +1 -1
  3. package/dist/{PreviewEditorSidebar-DfRhJPFQ.mjs → PreviewEditorSidebar-roNY0GVy.mjs} +4 -4
  4. package/dist/{PreviewEditorUI-Dppxcr_g.mjs → PreviewEditorUI-KboDbEh_.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-D51gQaG3.mjs → PreviewQueryProvider-DcgaESkm.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-8CyGCXir.mjs → SdkPreviewModeRuntime-DBrF7Caa.mjs} +5 -5
  7. package/dist/{SiteChromeCustomizeContext-DVMTMvqA.mjs → SiteChromeCustomizeContext-DrIEpJKn.mjs} +4070 -8011
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +165 -165
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +15 -15
  10. package/dist/_dts/api/src/bookingConfig.d.ts +1 -1
  11. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +25 -60
  12. package/dist/_dts/api/src/bookingOperations.d.ts +111 -161
  13. package/dist/_dts/api/src/bookingPaymentTermSchemas.d.ts +123 -0
  14. package/dist/_dts/api/src/bookingRecords.d.ts +13 -13
  15. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +4 -4
  16. package/dist/_dts/api/src/bookingSessionSummaryTypes.d.ts +34 -0
  17. package/dist/_dts/api/src/bookings.d.ts +5 -9
  18. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -7
  19. package/dist/_dts/api/src/communications.d.ts +1 -1
  20. package/dist/_dts/api/src/endpoints.d.ts +29 -109
  21. package/dist/_dts/api/src/eventManagementContracts.d.ts +1 -1
  22. package/dist/_dts/api/src/eventSeriesRegistrationEndpointDefinitions.d.ts +43 -0
  23. package/dist/_dts/api/src/index.d.ts +3 -4
  24. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  25. package/dist/_dts/api/src/participantMessaging.d.ts +2 -2
  26. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +8 -0
  27. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +32 -28
  28. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +85 -5
  29. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +1 -1
  30. package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +9 -100
  31. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +7 -6
  32. package/dist/_dts/api/src/publicWholeSeriesEndpointDefinitions.d.ts +0 -32
  33. package/dist/_dts/api/src/sdk-event-payment-terms.d.ts +1 -1
  34. package/dist/_dts/api/src/sdk-event-upsert.d.ts +1 -1
  35. package/dist/_dts/api/src/siteOperations.d.ts +2 -2
  36. package/dist/_dts/api/src/types.d.ts +1 -1
  37. package/dist/_dts/api/src/{courses.d.ts → wholeSeriesOfferings.d.ts} +43 -95
  38. package/dist/_dts/blocks/src/client.d.ts +0 -5
  39. package/dist/_dts/blocks/src/contracts/index.d.ts +1 -1
  40. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +5 -94
  41. package/dist/_dts/blocks/src/portal/dateFormatting.d.ts +3 -0
  42. package/dist/_dts/blocks/src/portal/types.d.ts +17 -20
  43. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +147 -42
  44. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +10 -10
  45. package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +3 -0
  46. package/dist/_dts/blocks/src/system/blocks/index.d.ts +0 -2
  47. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +3 -3
  48. package/dist/_dts/blocks/src/system/blocks/offerings-preview/scheduleSummary.d.ts +3 -3
  49. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  50. package/dist/_dts/blocks/src/system/node/builder.d.ts +0 -1
  51. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +9 -12
  52. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +2 -44
  53. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  54. package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +1 -1
  55. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +99 -59
  56. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  57. package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +19 -16
  58. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -0
  59. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +1 -1
  60. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -247
  61. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +13 -126
  62. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +0 -1
  63. package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -3
  64. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/WholeSeriesPricingDisplay.d.ts +8 -0
  65. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.d.ts +17 -0
  66. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +24 -0
  67. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentBlockingPanel.d.ts +18 -0
  68. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +5 -0
  69. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/constants.d.ts +1 -0
  70. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +1 -3
  71. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +7 -4
  72. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +0 -1
  73. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +7 -8
  74. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/index.d.ts +1 -1
  75. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +4 -4
  76. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.d.ts +3 -0
  77. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.d.ts +5 -0
  78. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.d.ts +28 -0
  79. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +12 -11
  80. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +53 -45
  81. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +10 -6
  82. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +9 -1
  83. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +20 -5
  84. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useWaitlistClaimRestoration.d.ts +20 -0
  85. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +5 -56
  86. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/waitlistClaimRestoration.d.ts +20 -0
  87. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +6 -22
  88. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DateTimeTile.d.ts +1 -1
  89. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +6 -6
  90. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +2 -2
  91. package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptions.d.ts +6 -1
  92. package/dist/_dts/blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.d.ts +1 -13
  93. package/dist/_dts/blocks/src/system/runtime/shared/components/LoggedInAsUser.d.ts +1 -1
  94. package/dist/_dts/blocks/src/system/runtime/shared/components/MembershipHero.d.ts +1 -1
  95. package/dist/_dts/blocks/src/system/runtime/shared/components/StateIcon.d.ts +1 -1
  96. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +1 -1
  97. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +1 -1
  98. package/dist/_dts/blocks/src/system/runtime/shared/utils/checkoutUrls.d.ts +2 -2
  99. package/dist/_dts/commerce/src/index.d.ts +16 -0
  100. package/dist/_dts/commerce/src/money.d.ts +122 -0
  101. package/dist/_dts/commerce/src/moneyContracts.d.ts +178 -0
  102. package/dist/_dts/commerce/src/moneyDateUtils.d.ts +22 -0
  103. package/dist/_dts/commerce/src/moneyPayments.d.ts +59 -0
  104. package/dist/_dts/commerce/src/moneyPlanningTime.d.ts +4 -0
  105. package/dist/_dts/commerce/src/moneyReceiptReadModel.d.ts +68 -0
  106. package/dist/_dts/commerce/src/moneyReport.d.ts +105 -0
  107. package/dist/_dts/commerce/src/moneyReportBreakdowns.d.ts +3 -0
  108. package/dist/_dts/commerce/src/moneyReportKindFilter.d.ts +4 -0
  109. package/dist/_dts/commerce/src/moneyReportPage.d.ts +132 -0
  110. package/dist/_dts/commerce/src/purchase/checkoutCollectionPlan.d.ts +1 -1
  111. package/dist/_dts/commerce/src/purchase/confirmationEmailPayment.d.ts +1 -1
  112. package/dist/_dts/commerce/src/purchase/orderCompletionEmailPlan.d.ts +3 -3
  113. package/dist/_dts/commerce/src/purchase/orderFulfillmentPlan.d.ts +6 -25
  114. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +4 -4
  115. package/dist/_dts/commerce/src/purchase/orderPlanningTypes.d.ts +11 -11
  116. package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +1 -1
  117. package/dist/_dts/commerce/src/purchase/persistedCheckoutLines.d.ts +1 -1
  118. package/dist/_dts/commerce/src/purchase/types.d.ts +12 -8
  119. package/dist/_dts/commerce/src/shop/digitalFulfillment.d.ts +111 -0
  120. package/dist/_dts/commerce/src/shop/fulfillmentStatus.d.ts +10 -0
  121. package/dist/_dts/commerce/src/shop/inventoryRestore.d.ts +13 -0
  122. package/dist/_dts/commerce/src/shop/shippingAddress.d.ts +18 -0
  123. package/dist/_dts/commerce/src/types/json.d.ts +3 -0
  124. package/dist/_dts/commerce/src/utils/isPlainRecord.d.ts +1 -0
  125. package/dist/_dts/commerce/src/waitlists.d.ts +172 -0
  126. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +0 -30
  127. package/dist/_dts/content-model/src/content-types/builtins.d.ts +2 -39
  128. package/dist/_dts/content-model/src/metadataConfig.d.ts +0 -1
  129. package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -68
  130. package/dist/_dts/core/src/branded.d.ts +3 -3
  131. package/dist/_dts/core/src/event-pricing.d.ts +6 -6
  132. package/dist/_dts/core/src/participants.d.ts +17 -17
  133. package/dist/_dts/core/src/rectification.d.ts +1 -1
  134. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +890 -2154
  135. package/dist/_dts/sdk/src/bookings/index.d.ts +4 -5
  136. package/dist/_dts/sdk/src/bookings/types.d.ts +34 -4
  137. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +4 -6
  138. package/dist/_dts/sdk/src/version.d.ts +1 -1
  139. package/dist/_dts/theme-core/src/blocks/vars/index.d.ts +0 -2
  140. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  141. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +1 -1
  142. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +1 -1
  143. package/dist/client/{usePolling-UN4WKnaM.mjs → BookingConsentAgreement-BQqwi8Oa.mjs} +180 -4
  144. package/dist/client/{DiscountCodeDisclosure-CfuPOHD0.mjs → DiscountCodeDisclosure-B97aMo0V.mjs} +13 -27
  145. package/dist/client/{EventCombined.client-DB8Qfzi-.mjs → EventCombined.client-Bs2Iw9Q6.mjs} +3 -3
  146. package/dist/client/{EventListing.client-DD4X8hp4.mjs → EventListing.client-C4QUQdmg.mjs} +2 -2
  147. package/dist/client/{LeafletStaticMap-QhgIBQbv.mjs → LeafletStaticMap-CwWRk69M.mjs} +1 -1
  148. package/dist/client/{accordion-DFXpLvwg.mjs → accordion-BA0j8Mpw.mjs} +1 -1
  149. package/dist/client/{bookingForm-sI05d3lk.mjs → bookingForm-Br2e41H0.mjs} +6 -7
  150. package/dist/client/bookings.mjs +912 -1906
  151. package/dist/client/{carousel-wjyWTZCh.mjs → carousel-B4dmwnpD.mjs} +1 -1
  152. package/dist/client/{cart-DCwdpA4i.mjs → cart-B_ckGW4b.mjs} +3 -3
  153. package/dist/client/{checkout-DTDW3l0R.mjs → checkout-DAyspHdf.mjs} +3 -3
  154. package/dist/client/{checkoutUrls-DQYC_Br-.mjs → checkoutUrls-BuseL0dw.mjs} +4 -2
  155. package/dist/client/client.mjs +5074 -9309
  156. package/dist/client/{context-TSK1CGx8.mjs → context-DljQn8L5.mjs} +15 -69
  157. package/dist/client/{eventCalendar-B0Zg-i_w.mjs → eventCalendar-pJu3FUod.mjs} +5 -5
  158. package/dist/client/{eventCombined-B8Y2wizd.mjs → eventCombined-B6Kacm9F.mjs} +3 -3
  159. package/dist/client/{eventDetails-DPDOwURJ.mjs → eventDetails-CaX9z1pv.mjs} +8 -8
  160. package/dist/client/{eventListing-CjBcmSLn.mjs → eventListing-B9aXPO-I.mjs} +3 -3
  161. package/dist/client/{eventRegistration-CK30HsAq.mjs → eventRegistration-CBSovBkg.mjs} +4522 -3690
  162. package/dist/client/{form-CUXfsABE.mjs → form-Cm0tu_7o.mjs} +2 -2
  163. package/dist/client/{headerSection-N-mN3rjr.mjs → headerSection-OgRtHeKS.mjs} +2 -2
  164. package/dist/client/hooks.mjs +430 -692
  165. package/dist/client/{locationMap-oiIDQMBt.mjs → locationMap-DmjcYqNM.mjs} +2 -2
  166. package/dist/client/{newsletterForm-CkQ2tTrM.mjs → newsletterForm-D08OZQAC.mjs} +2 -2
  167. package/dist/client/{productDetail-CnidyrsN.mjs → productDetail-BqZeu2P4.mjs} +3 -3
  168. package/dist/client/{productList-CttYcS_S.mjs → productList-mNyIF9FG.mjs} +3 -3
  169. package/dist/client/{propsDecoder-CeUMxI9a.mjs → propsDecoder-DwHXRm9X.mjs} +4656 -4419
  170. package/dist/client/rendering/client.mjs +59504 -62158
  171. package/dist/client/rendering/islands.mjs +17 -19
  172. package/dist/client/rendering.mjs +5354 -9683
  173. package/dist/client/{scrollToBlock-lPr1oqxB.mjs → scrollToBlock-DtmdM3v-.mjs} +2 -2
  174. package/dist/client/{shop-DXQtMo2O.mjs → shop-CNjZK16F.mjs} +6 -6
  175. package/dist/client/{shop-commerce-quDL411J.mjs → shop-commerce-DkNNao1J.mjs} +6 -6
  176. package/dist/client/{shop-commerce-store-Dnu-8Iub.mjs → shop-commerce-store-9WA--zuW.mjs} +1 -1
  177. package/dist/client/{shopShared-BWPUURvG.mjs → shopShared-CHCVfccY.mjs} +3 -3
  178. package/dist/client/{useEventFilters-DRhWp2_5.mjs → useEventFilters-DvuaB4ZN.mjs} +3 -3
  179. package/dist/preview-next/before-render.mjs +40 -161
  180. package/dist/preview-next/client/runtime.mjs +4 -4
  181. package/dist/preview-next/keepAlive.mjs +40 -161
  182. package/dist/preview-next/middleware.mjs +40 -161
  183. package/dist/{previewAuthStore-BFKd4LrN.mjs → previewAuthStore-C7ksxt5b.mjs} +40 -161
  184. package/dist/{sdk-runtime-Ca5RD78X.mjs → sdk-runtime-3GhW4knb.mjs} +2 -2
  185. package/dist/{separator-CMhj6BTi.mjs → separator-D3bCWYYb.mjs} +1 -1
  186. package/dist/server/components.mjs +535 -2950
  187. package/dist/server/config-validation.mjs +430 -692
  188. package/dist/server/config.mjs +430 -692
  189. package/dist/server/data.mjs +430 -692
  190. package/dist/server/index.mjs +41 -162
  191. package/dist/server/next.mjs +549 -2964
  192. package/dist/server/page-converter.mjs +331 -560
  193. package/dist/server/prebuild.mjs +1 -1
  194. package/dist/server/rendering/server.mjs +534 -2855
  195. package/dist/server/rendering.mjs +535 -2950
  196. package/dist/server/routing.mjs +574 -1065
  197. package/dist/server/server.mjs +444 -706
  198. package/dist/server/theme-bridge.mjs +41 -1524
  199. package/dist/styles/index.css +41 -1348
  200. package/package.json +1 -1
  201. package/dist/_dts/api/src/courseEndpointDefinitions.d.ts +0 -99
  202. package/dist/_dts/blocks/src/client/course-registration.d.ts +0 -5
  203. package/dist/_dts/blocks/src/system/blocks/course-details.d.ts +0 -134
  204. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +0 -130
  205. package/dist/_dts/blocks/src/system/blocks/courses/shared/index.d.ts +0 -3
  206. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +0 -2
  207. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +0 -1
  208. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +0 -1
  209. package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +0 -135
  210. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +0 -28
  211. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/logic.d.ts +0 -11
  212. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/runs.d.ts +0 -10
  213. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/view.d.ts +0 -15
  214. package/dist/_dts/blocks/src/system/runtime/nodes/course-details.server.d.ts +0 -20
  215. package/dist/_dts/blocks/src/system/runtime/nodes/course-page-surface-scope.d.ts +0 -14
  216. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.client.d.ts +0 -10
  217. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +0 -181
  218. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.server.d.ts +0 -12
  219. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/CoursePricingDisplay.d.ts +0 -8
  220. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/BookingModeStep.d.ts +0 -32
  221. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/CheckIcon.d.ts +0 -4
  222. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/ErrorStep.d.ts +0 -17
  223. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/MembershipHero.d.ts +0 -12
  224. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/PaymentFailedStep.d.ts +0 -17
  225. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/PortalAuthSidebar.d.ts +0 -9
  226. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.d.ts +0 -6
  227. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/SuccessStep.d.ts +0 -14
  228. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/VerifyingTimeoutStep.d.ts +0 -17
  229. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WaitlistStep.d.ts +0 -12
  230. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.d.ts +0 -9
  231. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.d.ts +0 -25
  232. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.d.ts +0 -8
  233. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.d.ts +0 -8
  234. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/components.d.ts +0 -46
  235. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/index.d.ts +0 -18
  236. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.d.ts +0 -7
  237. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.d.ts +0 -14
  238. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/types.d.ts +0 -105
  239. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesEligibility.d.ts +0 -24
  240. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.d.ts +0 -10
  241. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.d.ts +0 -35
  242. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.d.ts +0 -7
  243. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.d.ts +0 -35
  244. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.d.ts +0 -185
  245. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.d.ts +0 -14
  246. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/utils.d.ts +0 -43
  247. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.contract.d.ts +0 -325
  248. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.planning.d.ts +0 -27
  249. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.d.ts +0 -17
  250. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesRegistrationViewState.d.ts +0 -21
  251. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wizardSteps.d.ts +0 -30
  252. package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +0 -3
  253. package/dist/_dts/theme-core/src/blocks/vars/course-details.d.ts +0 -16
  254. package/dist/_dts/theme-core/src/blocks/vars/course-registration.d.ts +0 -21
  255. package/dist/client/BookingConsentAgreement-BxgpGEFD.mjs +0 -160
  256. package/dist/client/WholeSeriesRegistrationWizard-DwtC7bCs.mjs +0 -2546
  257. package/dist/client/courseRegistration-A-Tg7qw_.mjs +0 -52
  258. package/dist/client/pricing-Caa0QWzh.mjs +0 -195
@@ -1,2546 +0,0 @@
1
- "use client";
2
- import { $ as themeButtonClassName, Et as assertNever, Ht as toBookingTimeZone, Lt as formatBookingTime, Pt as formatBookingDate, Qt as assertNever$1, Ut as toScheduledBookingDateTime, Wt as parseEventPageSurfaceSubject } from "./propsDecoder-CeUMxI9a.mjs";
3
- import { n as formatWholeSeriesPriceDisplay, r as resolveWholeSeriesPricingState, t as formatWholeSeriesPriceAmount } from "./pricing-Caa0QWzh.mjs";
4
- import { n as useBlockApi } from "./context-TSK1CGx8.mjs";
5
- import { n as isSpamProtectionEnabled, r as AltchaWidget, t as getChallengeUrl } from "./src-B833rYRr.mjs";
6
- import { a as CheckIcon, i as StateIcon, n as useDiscountCodeUi, r as TerminalPanel, t as scrollToBlock } from "./scrollToBlock-lPr1oqxB.mjs";
7
- import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-CfuPOHD0.mjs";
8
- import { i as formatPrice, n as StepIndicator$1, r as SpinnerNode, t as BookingConsentAgreement } from "./BookingConsentAgreement-BxgpGEFD.mjs";
9
- import { t as FeedbackMessage } from "./FeedbackMessage-CtLvvS_d.mjs";
10
- import { n as getFieldValidationControlProps, t as FieldValidationMessage } from "./FieldValidationMessage-AYanWFb-.mjs";
11
- import { t as buildCheckoutReturnUrls } from "./checkoutUrls-DQYC_Br-.mjs";
12
- import { t as CrossIcon } from "./CrossIcon-Dn1KRKW5.mjs";
13
- import { t as ModalShell } from "./ModalShell-CqkBvBIC.mjs";
14
- import React, { Component, useCallback, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
15
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
- //#region ../blocks/src/system/runtime/shared/utils/validation.ts
17
- const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
18
- /**
19
- * Validate registration form data.
20
- *
21
- * Only `name` and `email` are required fields. The `phone` and `notes` fields
22
- * are optional and not validated by this function.
23
- *
24
- * @param data - Form data to validate
25
- * @returns Object with field errors (empty if valid)
26
- */
27
- function validateFormData(data) {
28
- const errors = {};
29
- if (!data.name.trim()) errors.name = "Name is required";
30
- if (!data.email.trim()) errors.email = "Email is required";
31
- else if (!EMAIL_REGEX.test(data.email.trim())) errors.email = "Please enter a valid email";
32
- return errors;
33
- }
34
- //#endregion
35
- //#region ../blocks/src/system/runtime/shared/utils/wizardSteps.ts
36
- /**
37
- * Shared Wizard Step Utilities
38
- *
39
- * Helpers for wizard step navigation in registration blocks.
40
- */
41
- /**
42
- * Get the 1-based step number for a step in the wizard.
43
- *
44
- * @param step - The step to find
45
- * @param wizardSteps - Array of wizard steps
46
- * @returns 1-based step number, or 1 if step not found
47
- */
48
- function getStepNumber(step, wizardSteps) {
49
- const index = wizardSteps.indexOf(step);
50
- return index >= 0 ? index + 1 : 1;
51
- }
52
- //#endregion
53
- //#region ../blocks/src/system/runtime/shared/components/ClockIcon.tsx
54
- function ClockIcon({ className, strokeWidth = 2 }) {
55
- return /* @__PURE__ */ jsx("svg", {
56
- fill: "none",
57
- strokeLinecap: "round",
58
- strokeLinejoin: "round",
59
- strokeWidth,
60
- viewBox: "0 0 24 24",
61
- stroke: "currentColor",
62
- className,
63
- width: "1em",
64
- height: "1em",
65
- "aria-hidden": "true",
66
- children: /* @__PURE__ */ jsx("path", { d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" })
67
- });
68
- }
69
- //#endregion
70
- //#region ../blocks/src/system/runtime/shared/components/MembershipHero.tsx
71
- /**
72
- * Celebratory UI shown when user's membership covers the course/event.
73
- * Displays confirmation that no payment is required.
74
- *
75
- * Supports both course-registration (cr-*) and event-registration (er-*) class prefixes.
76
- */
77
- function MembershipHero$1({ membershipName, classPrefix, onBookForSomeoneElse }) {
78
- return /* @__PURE__ */ jsxs(FeedbackMessage, {
79
- tone: "success",
80
- className: `${classPrefix}-membership-hero`,
81
- role: "status",
82
- children: [
83
- /* @__PURE__ */ jsx("div", {
84
- className: `${classPrefix}-membership-hero__icon`,
85
- "aria-hidden": "true",
86
- children: "✨"
87
- }),
88
- /* @__PURE__ */ jsxs("h3", {
89
- className: `${classPrefix}-membership-hero__title`,
90
- children: ["Included with your ", membershipName]
91
- }),
92
- /* @__PURE__ */ jsx("p", {
93
- className: `${classPrefix}-membership-hero__subtitle`,
94
- children: "No payment required"
95
- }),
96
- onBookForSomeoneElse && /* @__PURE__ */ jsx("button", {
97
- type: "button",
98
- className: `${classPrefix}-membership-hero__link`,
99
- onClick: onBookForSomeoneElse,
100
- children: "Booking for someone else?"
101
- })
102
- ]
103
- });
104
- }
105
- //#endregion
106
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.ts
107
- function resolveWholeSeriesRegistrationPresentation(kind) {
108
- switch (kind) {
109
- case "event": return {
110
- dataBlock: "event-registration",
111
- anchorId: "event-registration",
112
- rootClass: "event-registration"
113
- };
114
- case "temporary-course-adapter": return {
115
- dataBlock: "course-registration",
116
- anchorId: "course-registration",
117
- rootClass: "course-registration"
118
- };
119
- }
120
- }
121
- //#endregion
122
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.tsx
123
- /**
124
- * Error boundary wrapper for run registration.
125
- * Catches render errors and displays a fallback UI.
126
- */
127
- var WholeSeriesRegistrationErrorBoundary = class extends Component {
128
- constructor(props) {
129
- super(props);
130
- this.state = { hasError: false };
131
- }
132
- static getDerivedStateFromError(error) {
133
- return {
134
- hasError: true,
135
- error
136
- };
137
- }
138
- componentDidCatch(error, errorInfo) {
139
- console.error("Run registration error:", error, errorInfo);
140
- }
141
- render() {
142
- if (this.state.hasError) {
143
- const presentation = resolveWholeSeriesRegistrationPresentation(this.props.presentationKind ?? "event");
144
- return /* @__PURE__ */ jsx("div", {
145
- id: presentation.anchorId,
146
- "data-block": presentation.dataBlock,
147
- className: `${presentation.rootClass} ${this.props.className || ""}`,
148
- children: /* @__PURE__ */ jsxs("div", {
149
- className: "er-whole-series-error",
150
- children: [
151
- /* @__PURE__ */ jsx("div", {
152
- className: "er-whole-series-error__icon",
153
- children: "✕"
154
- }),
155
- /* @__PURE__ */ jsx("h3", {
156
- className: "er-whole-series-error__title",
157
- children: "Something went wrong"
158
- }),
159
- /* @__PURE__ */ jsx("p", {
160
- className: "er-whole-series-error__message",
161
- children: "Unable to load the booking form. Please refresh the page and try again."
162
- })
163
- ]
164
- })
165
- });
166
- }
167
- return this.props.children;
168
- }
169
- };
170
- //#endregion
171
- //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.ts
172
- const initialMagicLinkSubmissionState = Object.freeze({ tag: "idle" });
173
- function magicLinkSubmissionReducer(state, action) {
174
- switch (action.type) {
175
- case "submit-started":
176
- if (state.tag === "submitting") return state;
177
- return { tag: "submitting" };
178
- case "submit-succeeded":
179
- if (state.tag !== "submitting") return state;
180
- return { tag: "success" };
181
- case "submit-failed":
182
- if (state.tag !== "submitting") return state;
183
- return {
184
- tag: "error",
185
- message: action.message
186
- };
187
- case "reset": return initialMagicLinkSubmissionState;
188
- default: return assertNever(action);
189
- }
190
- }
191
- function isMagicLinkSubmitting(state) {
192
- return state.tag === "submitting";
193
- }
194
- function getMagicLinkError(state) {
195
- return state.tag === "error" ? state.message : null;
196
- }
197
- //#endregion
198
- //#region ../blocks/src/system/runtime/nodes/shared/MagicLinkForm.tsx
199
- /**
200
- * Reusable magic link login form.
201
- * Used by Customer Portal and Event Registration blocks.
202
- */
203
- function MagicLinkForm({ initialEmail = "", title, subtitle, buttonText = "Send login link", successMessage = "Check your email for a login link to sign in.", onSuccess, classPrefix = "er", compact = false }) {
204
- const api = useBlockApi();
205
- const [email, setEmail] = useState(initialEmail);
206
- const [submissionState, dispatchSubmission] = useReducer(magicLinkSubmissionReducer, initialMagicLinkSubmissionState);
207
- const loading = isMagicLinkSubmitting(submissionState);
208
- const error = getMagicLinkError(submissionState);
209
- const handleSubmit = async (e) => {
210
- e.preventDefault();
211
- const normalizedEmail = email.trim().toLowerCase();
212
- if (!normalizedEmail || loading) return;
213
- dispatchSubmission({ type: "submit-started" });
214
- try {
215
- const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
216
- await api.sendMagicLink({
217
- email: normalizedEmail,
218
- redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
219
- });
220
- dispatchSubmission({ type: "submit-succeeded" });
221
- onSuccess?.();
222
- } catch (err) {
223
- console.error("Magic link error:", err);
224
- dispatchSubmission({
225
- type: "submit-failed",
226
- message: getMagicLinkErrorMessage(err)
227
- });
228
- }
229
- };
230
- const handleReset = () => {
231
- setEmail("");
232
- dispatchSubmission({ type: "reset" });
233
- };
234
- if (submissionState.tag === "success") return /* @__PURE__ */ jsxs("div", {
235
- className: `${classPrefix}-magic-link-success`,
236
- children: [/* @__PURE__ */ jsx("p", {
237
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`,
238
- children: successMessage
239
- }), !compact && /* @__PURE__ */ jsx("button", {
240
- type: "button",
241
- className: classPrefix === "cp" ? themeButtonClassName({
242
- variant: "secondary",
243
- size: "md"
244
- }) : `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
245
- onClick: handleReset,
246
- children: "Try a different email"
247
- })]
248
- });
249
- return /* @__PURE__ */ jsxs("form", {
250
- onSubmit: handleSubmit,
251
- className: `${classPrefix}-magic-link-form`,
252
- children: [
253
- title && /* @__PURE__ */ jsx("h3", {
254
- className: `${classPrefix}-magic-link-title`,
255
- children: title
256
- }),
257
- subtitle && /* @__PURE__ */ jsx("p", {
258
- className: `${classPrefix}-portal-auth-text`,
259
- children: subtitle
260
- }),
261
- /* @__PURE__ */ jsx("input", {
262
- type: "email",
263
- className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
264
- placeholder: "your@email.com",
265
- value: email,
266
- onChange: (e) => setEmail(e.target.value),
267
- autoFocus: !compact,
268
- required: true,
269
- disabled: loading
270
- }),
271
- error && /* @__PURE__ */ jsx("p", {
272
- className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`,
273
- children: error
274
- }),
275
- /* @__PURE__ */ jsx("button", {
276
- type: "submit",
277
- className: classPrefix === "cp" ? themeButtonClassName({
278
- variant: "primary",
279
- size: "md"
280
- }) : `${classPrefix}-modal-btn`,
281
- disabled: !email.trim() || loading,
282
- children: loading ? "Sending..." : buttonText
283
- })
284
- ]
285
- });
286
- }
287
- function getMagicLinkErrorMessage(error) {
288
- return error instanceof Error ? error.message : "Failed to send. Please try again.";
289
- }
290
- //#endregion
291
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/PortalAuthSidebar.tsx
292
- /**
293
- * Portal authentication sidebar.
294
- * Shows login prompt for unauthenticated users who might have memberships.
295
- */
296
- const PORTAL_AUTH_COPY = {
297
- membership: {
298
- title: "Have a membership?",
299
- description: "Log in to use your membership to book for free",
300
- buttonText: "Log in with email",
301
- modalTitle: "Log in",
302
- modalHeading: "Log in to your account",
303
- modalSubtitle: "Enter your email to receive a magic link",
304
- successMessage: "Check your email for a login link. After clicking, refresh this page."
305
- },
306
- "waitlist-claim": {
307
- title: "Log in to claim your waitlist spot",
308
- description: "",
309
- buttonText: "Log in with email to continue",
310
- modalTitle: "Log in to continue",
311
- modalHeading: "Log in to your account to continue",
312
- modalSubtitle: "Enter your email to receive a login link and continue your waitlist claim",
313
- successMessage: "Check your email for a login link. After clicking it, return here to continue your claim."
314
- }
315
- };
316
- function PortalAuthSidebar({ onMagicLinkSent, autoOpen = false, variant = "membership", loginMessage }) {
317
- const [showModal, setShowModal] = useState(false);
318
- const copy = PORTAL_AUTH_COPY[variant];
319
- const description = variant === "waitlist-claim" ? loginMessage ?? "Log in to continue with your waitlist claim." : copy.description;
320
- useEffect(() => {
321
- if (!autoOpen) return;
322
- setShowModal(true);
323
- }, [autoOpen]);
324
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
325
- className: "er-whole-series-portal-sidebar",
326
- children: [
327
- /* @__PURE__ */ jsx("div", {
328
- className: "er-whole-series-portal-sidebar__icon",
329
- "aria-hidden": "true",
330
- children: "👤"
331
- }),
332
- /* @__PURE__ */ jsx("h3", {
333
- className: "er-whole-series-portal-sidebar__title",
334
- children: copy.title
335
- }),
336
- /* @__PURE__ */ jsx("p", {
337
- className: "er-whole-series-portal-sidebar__text",
338
- children: description
339
- }),
340
- /* @__PURE__ */ jsx("div", {
341
- className: "er-whole-series-portal-sidebar__action",
342
- children: /* @__PURE__ */ jsx("button", {
343
- type: "button",
344
- className: "er-whole-series-portal-sidebar__link",
345
- onClick: () => setShowModal(true),
346
- children: copy.buttonText
347
- })
348
- })
349
- ]
350
- }), showModal && /* @__PURE__ */ jsx(ModalShell, {
351
- title: copy.modalTitle,
352
- titleId: "er-whole-series-portal-auth-modal-title",
353
- onClose: () => setShowModal(false),
354
- overlayClassName: "er-whole-series-modal-overlay",
355
- modalClassName: "er-whole-series-modal",
356
- renderSrOnlyTitle: true,
357
- renderHeader: ({ closeButtonRef, onClose }) => /* @__PURE__ */ jsx("button", {
358
- ref: closeButtonRef,
359
- type: "button",
360
- className: "er-whole-series-modal-close",
361
- onClick: onClose,
362
- "aria-label": "Close",
363
- children: /* @__PURE__ */ jsx("svg", {
364
- width: "20",
365
- height: "20",
366
- viewBox: "0 0 24 24",
367
- fill: "none",
368
- stroke: "currentColor",
369
- strokeWidth: "2",
370
- "aria-hidden": "true",
371
- children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
372
- })
373
- }),
374
- children: /* @__PURE__ */ jsx(MagicLinkForm, {
375
- classPrefix: "er-whole-series",
376
- title: copy.modalHeading,
377
- subtitle: copy.modalSubtitle,
378
- buttonText: "Send login link",
379
- successMessage: copy.successMessage,
380
- onSuccess: () => {
381
- onMagicLinkSent?.();
382
- }
383
- })
384
- })] });
385
- }
386
- //#endregion
387
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.tsx
388
- /**
389
- * Step indicator component for the run registration wizard.
390
- * Thin wrapper around the shared StepIndicator with the canonical Event class prefix.
391
- */
392
- function StepIndicator(props) {
393
- return /* @__PURE__ */ jsx(StepIndicator$1, {
394
- ...props,
395
- classPrefix: "er-whole-series"
396
- });
397
- }
398
- //#endregion
399
- //#region ../blocks/src/system/runtime/shared/useWaitlistClaim.state.ts
400
- const DEFAULT_WAITLIST_CLAIM_ERROR = "Failed to resolve waitlist claim";
401
- function createInitialWaitlistClaimState(hasToken) {
402
- return hasToken ? { kind: "resolving" } : { kind: "idle" };
403
- }
404
- function waitlistClaimReducer(_state, action) {
405
- switch (action.type) {
406
- case "cleared": return { kind: "idle" };
407
- case "started": return { kind: "resolving" };
408
- case "resolved": return {
409
- kind: "resolved",
410
- claim: action.claim
411
- };
412
- case "failed": return action.failure;
413
- }
414
- }
415
- function toWaitlistClaimResolveFailure(error) {
416
- const message = error instanceof Error ? error.message : DEFAULT_WAITLIST_CLAIM_ERROR;
417
- if (isUnauthorizedBlockApiError(error)) return {
418
- kind: "portal-login-required",
419
- message
420
- };
421
- return {
422
- kind: "error",
423
- message
424
- };
425
- }
426
- function isUnauthorizedBlockApiError(error) {
427
- return error instanceof Error && error.name === "BlockApiError" && hasStatus(error) && error.status === 401;
428
- }
429
- function hasStatus(value) {
430
- return typeof value === "object" && value !== null && "status" in value;
431
- }
432
- function getWaitlistClaim(state) {
433
- return state.kind === "resolved" ? state.claim : null;
434
- }
435
- function getWaitlistClaimError(state) {
436
- return state.kind === "error" ? state.message : null;
437
- }
438
- function getWaitlistClaimLoginMessage(state) {
439
- return state.kind === "portal-login-required" ? state.message : null;
440
- }
441
- function requiresWaitlistClaimPortalLogin(state) {
442
- return state.kind === "portal-login-required";
443
- }
444
- function isWaitlistClaimLoading(state) {
445
- return state.kind === "resolving";
446
- }
447
- //#endregion
448
- //#region ../blocks/src/system/runtime/shared/useWaitlistClaim.ts
449
- const WAITLIST_CLAIM_LOCATION_EVENT = "riverbank:waitlist-claim-location-change";
450
- let historyPatched = false;
451
- function emitWaitlistClaimLocationChange() {
452
- if (typeof window === "undefined") return;
453
- window.dispatchEvent(new Event(WAITLIST_CLAIM_LOCATION_EVENT));
454
- }
455
- function ensureWaitlistClaimLocationTracking() {
456
- if (typeof window === "undefined" || historyPatched) return;
457
- historyPatched = true;
458
- const history = window.history;
459
- if (history.__riverbankWaitlistClaimPatched__) return;
460
- const wrapHistoryMethod = (method) => {
461
- return function patched(...args) {
462
- method.apply(this, args);
463
- emitWaitlistClaimLocationChange();
464
- };
465
- };
466
- try {
467
- history.pushState = wrapHistoryMethod(history.pushState);
468
- history.replaceState = wrapHistoryMethod(history.replaceState);
469
- history.__riverbankWaitlistClaimPatched__ = true;
470
- } catch {}
471
- window.addEventListener("popstate", emitWaitlistClaimLocationChange);
472
- }
473
- function getWaitlistClaimTokenFromUrl() {
474
- if (typeof window === "undefined") return null;
475
- const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
476
- return token.length > 0 ? token : null;
477
- }
478
- const useWaitlistClaimDeps = { useBlockApi };
479
- function subscribeToWaitlistClaimToken(callback) {
480
- if (typeof window === "undefined") return () => {};
481
- ensureWaitlistClaimLocationTracking();
482
- window.addEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
483
- return () => {
484
- window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
485
- };
486
- }
487
- function getWaitlistClaimTokenSnapshot() {
488
- return getWaitlistClaimTokenFromUrl();
489
- }
490
- function useWaitlistClaim() {
491
- return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
492
- }
493
- function useWaitlistClaimForToken(token) {
494
- return useResolvedWaitlistClaim(useWaitlistClaimDeps, token);
495
- }
496
- function useWaitlistClaimWithDeps(deps) {
497
- return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
498
- }
499
- function useResolvedWaitlistClaim(deps, token) {
500
- const api = deps.useBlockApi();
501
- const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
502
- useEffect(() => {
503
- let cancelled = false;
504
- async function resolveClaim() {
505
- if (!token) {
506
- dispatch({ type: "cleared" });
507
- return;
508
- }
509
- dispatch({ type: "started" });
510
- try {
511
- const result = await api.resolveWaitlistClaim({ claimToken: token });
512
- if (cancelled) return;
513
- dispatch({
514
- type: "resolved",
515
- claim: result
516
- });
517
- } catch (claimError) {
518
- if (cancelled) return;
519
- dispatch({
520
- type: "failed",
521
- failure: toWaitlistClaimResolveFailure(claimError)
522
- });
523
- }
524
- }
525
- resolveClaim();
526
- return () => {
527
- cancelled = true;
528
- };
529
- }, [api, token]);
530
- return {
531
- token,
532
- claim: getWaitlistClaim(state),
533
- error: getWaitlistClaimError(state),
534
- loginMessage: getWaitlistClaimLoginMessage(state),
535
- requiresPortalLogin: requiresWaitlistClaimPortalLogin(state),
536
- isLoading: isWaitlistClaimLoading(state)
537
- };
538
- }
539
- //#endregion
540
- //#region ../blocks/src/system/runtime/shared/utils/portalLogout.ts
541
- /**
542
- * Portal Logout Utility
543
- *
544
- * Logout from the customer portal by POSTing to the logout endpoint.
545
- * Uses a hidden form because the httpOnly cookie can only be cleared server-side.
546
- */
547
- /**
548
- * Logout from the customer portal.
549
- *
550
- * @param anchorId - The anchor ID to redirect back to after logout
551
- */
552
- function logoutPortal(anchorId) {
553
- const form = document.createElement("form");
554
- form.method = "POST";
555
- form.action = "/api/portal/logout";
556
- const redirectInput = document.createElement("input");
557
- redirectInput.type = "hidden";
558
- redirectInput.name = "redirect_to";
559
- redirectInput.value = `${window.location.pathname}#${anchorId}`;
560
- form.appendChild(redirectInput);
561
- document.body.appendChild(form);
562
- form.submit();
563
- }
564
- //#endregion
565
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/utils.ts
566
- /**
567
- * Run Registration Utilities
568
- *
569
- * Formatting and validation helpers for run registration.
570
- */
571
- /**
572
- * Format a date string to a localized date.
573
- *
574
- * @param dateString - ISO 8601 date string
575
- * @param locale - Optional locale for formatting (defaults to browser locale)
576
- * @returns Formatted date string (e.g., "Sat, Feb 1, 2026")
577
- */
578
- function formatDate(dateString, options) {
579
- return formatBookingDate(toScheduledBookingDateTime({
580
- startsAt: dateString,
581
- locale: options?.locale,
582
- timeZone: toBookingTimeZone(options?.timeZone)
583
- }), {
584
- weekday: "short",
585
- month: "short",
586
- day: "numeric",
587
- year: "numeric"
588
- });
589
- }
590
- /**
591
- * Format a date string to a localized time.
592
- *
593
- * @param dateString - ISO 8601 date string
594
- * @param locale - Optional locale for formatting (defaults to browser locale)
595
- * @returns Formatted time string (e.g., "10:00 AM")
596
- */
597
- function formatTime(dateString, options) {
598
- return formatBookingTime(toScheduledBookingDateTime({
599
- startsAt: dateString,
600
- locale: options?.locale,
601
- timeZone: toBookingTimeZone(options?.timeZone)
602
- }), {
603
- hour: "numeric",
604
- minute: "2-digit"
605
- });
606
- }
607
- /**
608
- * Anchor ID for the registration block, used for scroll targeting.
609
- */
610
- const WHOLE_SERIES_REGISTRATION_ANCHOR_ID = "event-registration";
611
- //#endregion
612
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.ts
613
- function parseCurrencyInputToCents(value) {
614
- const trimmed = value.trim();
615
- if (!trimmed) return null;
616
- const amount = Number(trimmed);
617
- if (!Number.isFinite(amount) || amount < 0) return null;
618
- return Math.round(amount * 100);
619
- }
620
- function formatCentsAsCurrencyInput(amount) {
621
- const major = amount / 100;
622
- return Number.isInteger(major) ? String(major) : major.toFixed(2);
623
- }
624
- function getMissingWholeSeriesPricingSelectionMessage(pricing) {
625
- if (pricing?.requiresSelection && !pricing.selectedOption) return pricing.slidingScale ? "Choose an amount to continue." : "Choose a pricing option to continue.";
626
- const selectedAmount = pricing?.selectedSlidingAmount;
627
- const scale = pricing?.slidingScale;
628
- if (scale && selectedAmount !== null && selectedAmount !== void 0 && (selectedAmount < scale.minAmount || selectedAmount > scale.maxAmount)) return "Choose an amount within the sliding scale.";
629
- return null;
630
- }
631
- function buildWholeSeriesPricingOptionPayload(pricing) {
632
- if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
633
- if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
634
- return {};
635
- }
636
- function defaultWholeSeriesPricingSelection(pricing, previousOptionId) {
637
- return {
638
- pricingOptionId: previousOptionId && pricing.selectableOptions.some((option) => option.id === previousOptionId) ? previousOptionId : pricing.selectedOption?.id ?? null,
639
- slidingAmountInput: pricing.slidingScale?.suggestedAmount !== null && pricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(pricing.slidingScale.suggestedAmount) : ""
640
- };
641
- }
642
- //#endregion
643
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wizardSteps.ts
644
- /**
645
- * Steps that are part of the main wizard and should show the step indicator.
646
- * Terminal states (success, error, etc.) are not included.
647
- */
648
- const WIZARD_STEPS = [
649
- "select-run",
650
- "enter-details",
651
- "booking-mode",
652
- "select-payment"
653
- ];
654
- /**
655
- * Step labels for the wizard indicator
656
- */
657
- const STEP_LABELS = {
658
- "select-run": "Run",
659
- "enter-details": "Details",
660
- "booking-mode": "Method",
661
- "select-payment": "Payment",
662
- submitting: "Booking",
663
- redirecting: "Redirecting",
664
- "verifying-payment": "Verifying",
665
- "verifying-timeout": "Timeout",
666
- "payment-failed": "Failed",
667
- success: "Complete",
668
- waitlist: "Waitlist",
669
- error: "Error"
670
- };
671
- /**
672
- * Determine which wizard steps to show based on context and eligibility.
673
- *
674
- * @param hasPreSelectedRun - Whether run is pre-selected (skips run selection)
675
- * @param requiresPayment - Whether the run requires payment
676
- * @param hasEligibleMemberships - Whether user has eligible memberships
677
- * @param bookingMode - Current booking mode selection
678
- * @param isMembershipFastTrack - Whether user qualifies for single-step membership flow
679
- * @returns Array of wizard steps to display
680
- */
681
- function getWizardStepsForContext(hasPreSelectedRun, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
682
- if (isMembershipFastTrack) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
683
- if (!requiresPayment) return hasPreSelectedRun ? ["enter-details"] : ["select-run", "enter-details"];
684
- if (hasEligibleMemberships) {
685
- const skipPayment = bookingMode === "membership";
686
- if (hasPreSelectedRun) return skipPayment ? ["enter-details", "booking-mode"] : [
687
- "enter-details",
688
- "booking-mode",
689
- "select-payment"
690
- ];
691
- return skipPayment ? [
692
- "select-run",
693
- "enter-details",
694
- "booking-mode"
695
- ] : [
696
- "select-run",
697
- "enter-details",
698
- "booking-mode",
699
- "select-payment"
700
- ];
701
- }
702
- return hasPreSelectedRun ? ["enter-details", "select-payment"] : [
703
- "select-run",
704
- "enter-details",
705
- "select-payment"
706
- ];
707
- }
708
- /**
709
- * Get labels for a list of wizard steps
710
- */
711
- function getStepLabels(steps) {
712
- return steps.map((step) => STEP_LABELS[step] ?? step);
713
- }
714
- //#endregion
715
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesRegistrationViewState.ts
716
- function deriveWholeSeriesRegistrationViewState(input) {
717
- const hasRunPayment = resolveWholeSeriesPaymentRequirement(input.pricing);
718
- const canUseMembership = hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
719
- const hasPreSelectedRun = input.scopedRuns.length === 1;
720
- const fastTrack = canUseMembership && input.eligibleMembershipCount === 1 && input.bookingMode === "membership";
721
- const wizardSteps = getWizardStepsForContext(hasPreSelectedRun, hasRunPayment, canUseMembership, input.bookingMode, fastTrack);
722
- const showPortalAuthSidebar = shouldShowPortalAuthSidebar({
723
- ...input,
724
- hasRunPayment
725
- });
726
- return {
727
- hasRunPayment,
728
- canUseMembership,
729
- hasPreSelectedRun,
730
- wizardSteps,
731
- currentStepNumber: getStepNumber(input.step, wizardSteps),
732
- totalSteps: wizardSteps.length,
733
- stepLabels: getStepLabels(wizardSteps),
734
- showPortalAuthSidebar
735
- };
736
- }
737
- function resolveWholeSeriesPaymentRequirement(pricing) {
738
- if (!pricing) return false;
739
- return pricing.selectedOption ? pricing.selectedRequiresPayment : pricing.hasPaidSelection;
740
- }
741
- function shouldShowPortalAuthSidebar(input) {
742
- if (input.portalAuthState !== "unauthenticated") return false;
743
- if (input.step === "success" || input.step === "waitlist" || input.step === "error") return false;
744
- return input.waitlistRequiresPortalLogin || input.hasRunPayment && input.selectedRun?.acceptsMemberships === true && input.step !== "select-run";
745
- }
746
- //#endregion
747
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesEligibility.ts
748
- function shouldFetchEligibility(input) {
749
- if (!input.run || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
750
- const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.run.acceptsMemberships;
751
- const capacityCheck = input.run.availableSpots !== null && input.run.availableSpots <= 0;
752
- return membershipCheck || capacityCheck;
753
- }
754
- function useWholeSeriesEligibility(input) {
755
- const [loading, setLoading] = useState(false);
756
- const [error, setError] = useState(null);
757
- const [eligibility, setEligibility] = useState(null);
758
- const [memberships, setMemberships] = useState([]);
759
- const [paymentChoice, setPaymentChoice] = useState("checkout");
760
- const [selectedMembershipId, setSelectedMembershipId] = useState(null);
761
- const choosePaymentChoice = useCallback((choice) => {
762
- setPaymentChoice(choice);
763
- }, []);
764
- const chooseMembership = useCallback((membershipId) => {
765
- setSelectedMembershipId(membershipId);
766
- }, []);
767
- useEffect(() => {
768
- let cancelled = false;
769
- setEligibility(null);
770
- setMemberships([]);
771
- setSelectedMembershipId(null);
772
- setError(null);
773
- setPaymentChoice("checkout");
774
- const eligibilityInput = {
775
- run: input.selectedRun,
776
- hasPaidSelection: input.hasPaidSelection,
777
- portalAuthState: input.portalAuthState,
778
- hasWaitlistClaimToken: input.waitlistClaimToken !== null
779
- };
780
- if (!shouldFetchEligibility(eligibilityInput)) return;
781
- const run = eligibilityInput.run;
782
- setLoading(true);
783
- input.api.checkWholeSeriesEligibility({ eventSeriesId: run.eventSeriesId }).then((result) => {
784
- if (cancelled) return;
785
- const eligibleMemberships = result.eligibleMemberships ?? [];
786
- setEligibility(result);
787
- setMemberships(eligibleMemberships);
788
- if (input.portalAuthState === "authenticated" && eligibleMemberships.length > 0) {
789
- setPaymentChoice("membership");
790
- if (eligibleMemberships.length === 1) setSelectedMembershipId(eligibleMemberships[0]?.customerMembershipId ?? null);
791
- }
792
- }).catch((cause) => {
793
- if (!cancelled) setError(cause instanceof Error ? cause.message : "Failed to check membership eligibility");
794
- }).finally(() => {
795
- if (!cancelled) setLoading(false);
796
- });
797
- return () => {
798
- cancelled = true;
799
- };
800
- }, [
801
- input.api,
802
- input.hasPaidSelection,
803
- input.portalAuthState,
804
- input.selectedRun,
805
- input.waitlistClaimToken
806
- ]);
807
- return {
808
- eligibilityLoading: loading,
809
- eligibilityError: error,
810
- runEligibility: eligibility,
811
- eligibleMemberships: memberships,
812
- paymentChoice,
813
- choosePaymentChoice,
814
- selectedMembershipId,
815
- chooseMembership
816
- };
817
- }
818
- //#endregion
819
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.ts
820
- /**
821
- * Resolves native run-page ownership without falling back to entry or slug
822
- * coincidence when a page-surface subject is present but invalid.
823
- */
824
- function resolveWholeSeriesPageSurfaceScope(runs, subjectValue) {
825
- if (subjectValue === null || subjectValue === void 0) return { kind: "absent" };
826
- const parsed = parseEventPageSurfaceSubject(subjectValue);
827
- if (!parsed.ok) return {
828
- kind: "unsupported",
829
- reason: parsed.error.kind
830
- };
831
- const seriesIds = eventSeriesIdsForSubject(parsed.value);
832
- const allowedSeriesIds = new Set(seriesIds);
833
- return {
834
- kind: "scoped",
835
- subject: parsed.value,
836
- runs: runs.filter((run) => allowedSeriesIds.has(run.eventSeriesId))
837
- };
838
- }
839
- function eventSeriesIdsForSubject(subject) {
840
- switch (subject.kind) {
841
- case "eventSeries": return [subject.eventSeriesId];
842
- case "eventOffering": return subject.availableEventSeriesIds;
843
- default: return assertNever$1(subject);
844
- }
845
- }
846
- //#endregion
847
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.ts
848
- function selectScopedRuns(props) {
849
- const surfaceScope = resolveWholeSeriesPageSurfaceScope(props.runs ?? [], props.subject);
850
- if (surfaceScope.kind === "unsupported") return [];
851
- if (surfaceScope.kind === "scoped") return surfaceScope.runs;
852
- return [];
853
- }
854
- function getWholeSeriesCheckoutSessionId(location = window.location) {
855
- const fromSearch = new URLSearchParams(location.search).get("session_id");
856
- if (fromSearch) return fromSearch;
857
- return location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
858
- }
859
- function initialStep(runs, location) {
860
- if (new URLSearchParams(location.search).get("enrollment") === "success" && getWholeSeriesCheckoutSessionId(location)) return "verifying-payment";
861
- return runs.length === 1 ? "enter-details" : "select-run";
862
- }
863
- function useWholeSeriesRegistrationSelection(props, location = window.location) {
864
- const scopeSnapshot = JSON.stringify({
865
- runs: props.runs ?? [],
866
- subject: props.subject ?? null
867
- });
868
- const stableScope = useRef(null);
869
- if (stableScope.current?.snapshot !== scopeSnapshot) stableScope.current = {
870
- snapshot: scopeSnapshot,
871
- runs: selectScopedRuns(props)
872
- };
873
- const scopedRuns = stableScope.current.runs;
874
- const [step, setStep] = useState(() => initialStep(scopedRuns, location));
875
- const [selectedRunId, setSelectedRunId] = useState(scopedRuns.length === 1 ? scopedRuns[0]?.eventSeriesId ?? null : null);
876
- const selectedRun = useMemo(() => scopedRuns.find((run) => run.eventSeriesId === selectedRunId) ?? (scopedRuns.length === 1 ? scopedRuns[0] ?? null : null), [scopedRuns, selectedRunId]);
877
- const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
878
- const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
879
- const goToStep = useCallback((nextStep) => {
880
- setStep(nextStep);
881
- }, []);
882
- const chooseRun = useCallback((run) => {
883
- setSelectedRunId(run.eventSeriesId);
884
- }, []);
885
- const choosePricingOption = useCallback((pricingOptionId) => {
886
- setSelectedPricingOptionId(pricingOptionId);
887
- }, []);
888
- const changeSlidingAmount = useCallback((amount) => {
889
- setSelectedSlidingAmountInput(amount);
890
- }, []);
891
- const selectedRunPricing = useMemo(() => selectedRun ? resolveWholeSeriesPricingState(selectedRun, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
892
- selectedRun,
893
- selectedPricingOptionId,
894
- selectedSlidingAmountInput
895
- ]);
896
- useEffect(() => {
897
- if (!selectedRun) {
898
- setSelectedPricingOptionId(null);
899
- setSelectedSlidingAmountInput("");
900
- return;
901
- }
902
- const selection = defaultWholeSeriesPricingSelection(resolveWholeSeriesPricingState(selectedRun, null), selectedPricingOptionId);
903
- setSelectedPricingOptionId(selection.pricingOptionId);
904
- setSelectedSlidingAmountInput(selection.slidingAmountInput);
905
- }, [selectedRun?.eventSeriesId]);
906
- return {
907
- scopedRuns,
908
- step,
909
- goToStep,
910
- selectedRun,
911
- chooseRun,
912
- selectedPricingOptionId,
913
- choosePricingOption,
914
- selectedSlidingAmountInput,
915
- changeSlidingAmount,
916
- selectedRunPricing
917
- };
918
- }
919
- //#endregion
920
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.ts
921
- function applyTerminalStatus(status, setters) {
922
- if (status === "enrolled" || status === "completed") {
923
- setters.setEnrollmentResult({
924
- status: "enrolled",
925
- usedMembership: false
926
- });
927
- setters.setStep("success");
928
- return true;
929
- }
930
- if (status === "waitlist") {
931
- setters.setEnrollmentResult({
932
- status: "waitlist",
933
- usedMembership: false
934
- });
935
- setters.setStep("waitlist");
936
- return true;
937
- }
938
- setters.setErrorMessage("Payment did not complete. Please try again.");
939
- setters.setStep("error");
940
- return true;
941
- }
942
- async function pollWholeSeriesRegistrationStatus(api, sessionId, setters, isCancelled) {
943
- const startedAt = Date.now();
944
- while (!isCancelled()) {
945
- try {
946
- const result = await api.getWholeSeriesRegistrationStatus({ sessionId });
947
- if (isCancelled()) return;
948
- if (result.status !== "pending_payment") {
949
- applyTerminalStatus(result.status, setters);
950
- return;
951
- }
952
- } catch (cause) {
953
- setters.setErrorMessage(cause instanceof Error ? cause.message : "Failed to verify payment");
954
- }
955
- if (Date.now() - startedAt > 3e4) {
956
- setters.setErrorMessage("Payment is still processing. Please check your email for confirmation.");
957
- setters.setStep("error");
958
- return;
959
- }
960
- await new Promise((resolve) => setTimeout(resolve, 1500));
961
- }
962
- }
963
- function useWholeSeriesPaymentVerification(api, setters, anchorId = WHOLE_SERIES_REGISTRATION_ANCHOR_ID, location = window.location) {
964
- useEffect(() => {
965
- let cancelled = false;
966
- const enrollment = new URLSearchParams(location.search).get("enrollment");
967
- const sessionId = getWholeSeriesCheckoutSessionId(location);
968
- if (enrollment === "cancelled") {
969
- scrollToBlock(anchorId);
970
- setters.setErrorMessage("Payment was cancelled. You can try again.");
971
- setters.setStep("error");
972
- return;
973
- }
974
- if (enrollment !== "success" || !sessionId) return;
975
- scrollToBlock(anchorId);
976
- setters.setStep("verifying-payment");
977
- pollWholeSeriesRegistrationStatus(api, sessionId, setters, () => cancelled);
978
- return () => {
979
- cancelled = true;
980
- };
981
- }, [
982
- api,
983
- setters.setEnrollmentResult,
984
- setters.setErrorMessage,
985
- setters.setStep,
986
- anchorId,
987
- location
988
- ]);
989
- }
990
- //#endregion
991
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.ts
992
- function blocked(message, setters) {
993
- setters.setErrorMessage(message);
994
- setters.setStep("error");
995
- return {
996
- kind: "blocked",
997
- message
998
- };
999
- }
1000
- function validateSubmission(state, setters) {
1001
- if (!state.selectedRun) return {
1002
- kind: "blocked",
1003
- message: "Choose an available set of dates to continue."
1004
- };
1005
- const errors = validateFormData(state.formData);
1006
- if (state.selectedRun.consent && state.formData.consentAccepted !== true) errors.consentAccepted = "Please read and accept the agreement before continuing.";
1007
- setters.setErrors(errors);
1008
- if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
1009
- const pricingMessage = getMissingWholeSeriesPricingSelectionMessage(state.pricing);
1010
- if (pricingMessage) return blocked(pricingMessage, setters);
1011
- if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This run is fully booked.", setters);
1012
- if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
1013
- return null;
1014
- }
1015
- function enrollmentPayload(state, payment) {
1016
- return {
1017
- ...registrantPayload(state),
1018
- paymentMethod: payment.method,
1019
- ...payment.method === "membership" ? { customerMembershipId: payment.membershipId } : {}
1020
- };
1021
- }
1022
- function registrantPayload(state) {
1023
- return {
1024
- eventSeriesId: state.selectedRun.eventSeriesId,
1025
- ...buildWholeSeriesPricingOptionPayload(state.pricing),
1026
- email: state.formData.email.trim().toLowerCase(),
1027
- name: state.formData.name.trim(),
1028
- phone: state.formData.phone.trim() || void 0,
1029
- formData: { notes: state.formData.notes.trim() || void 0 },
1030
- consentAccepted: state.formData.consentAccepted,
1031
- altchaSolution: state.altchaSolution,
1032
- claimToken: state.claimToken ?? void 0
1033
- };
1034
- }
1035
- async function enroll(state, setters, payment) {
1036
- setters.setStep("submitting");
1037
- try {
1038
- const result = await state.api.registerForWholeSeries(enrollmentPayload(state, payment));
1039
- setters.setEnrollmentResult({
1040
- status: result.status,
1041
- waitlistPosition: result.waitlistPosition ?? void 0,
1042
- usedMembership: payment.method === "membership"
1043
- });
1044
- setters.setStep(result.status === "waitlist" ? "waitlist" : "success");
1045
- return { kind: "state-updated" };
1046
- } catch (cause) {
1047
- const message = cause instanceof Error ? cause.message : "Booking failed";
1048
- setters.setErrorMessage(message);
1049
- setters.setStep("error");
1050
- return {
1051
- kind: "failed",
1052
- message
1053
- };
1054
- }
1055
- }
1056
- async function checkout(state, setters) {
1057
- setters.setStep("submitting");
1058
- try {
1059
- const urls = buildCheckoutReturnUrls("enrollment", state.options.anchorId ?? "event-registration");
1060
- const result = await state.api.createWholeSeriesCheckout({
1061
- ...registrantPayload(state),
1062
- discountCode: state.discountCode.trim() || void 0,
1063
- successUrl: urls.successUrl,
1064
- cancelUrl: urls.cancelUrl
1065
- });
1066
- if (result.bypassed) {
1067
- setters.setEnrollmentResult({
1068
- status: "enrolled",
1069
- usedMembership: false
1070
- });
1071
- setters.setStep("success");
1072
- return { kind: "state-updated" };
1073
- }
1074
- if (!result.checkoutUrl) throw new Error("Checkout URL missing");
1075
- setters.setStep("redirecting");
1076
- if (state.options.onCheckoutRedirect) state.options.onCheckoutRedirect(result.checkoutUrl);
1077
- else window.location.href = result.checkoutUrl;
1078
- return {
1079
- kind: "checkout-redirect",
1080
- checkoutUrl: result.checkoutUrl
1081
- };
1082
- } catch (cause) {
1083
- const message = cause instanceof Error ? cause.message : "Checkout failed";
1084
- setters.setErrorMessage(message);
1085
- setters.setStep("error");
1086
- return {
1087
- kind: "failed",
1088
- message
1089
- };
1090
- }
1091
- }
1092
- async function submitDetails(state, setters) {
1093
- const invalid = validateSubmission(state, setters);
1094
- if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1095
- if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
1096
- const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
1097
- const canUseMembership = requiresPayment && state.selectedRun.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
1098
- if (requiresPayment && canUseMembership) {
1099
- setters.setStep("select-payment");
1100
- return { kind: "state-updated" };
1101
- }
1102
- if (requiresPayment) return checkout(state, setters);
1103
- return enroll(state, setters, { method: "free" });
1104
- }
1105
- async function continuePayment(state, setters) {
1106
- const invalid = validateSubmission(state, setters);
1107
- if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1108
- if (!state.pricing?.selectedRequiresPayment) {
1109
- setters.setStep("enter-details");
1110
- return { kind: "state-updated" };
1111
- }
1112
- const selectedState = state;
1113
- if (state.paymentChoice === "membership") {
1114
- if (!state.selectedMembershipId) return blocked("Select a membership to sign up.", setters);
1115
- return enroll(selectedState, setters, {
1116
- method: "membership",
1117
- membershipId: state.selectedMembershipId
1118
- });
1119
- }
1120
- return checkout(selectedState, setters);
1121
- }
1122
- function useWholeSeriesRegistrationActions(state, setStep) {
1123
- const [errors, setErrors] = useState({});
1124
- const [enrollmentResult, setEnrollmentResult] = useState(null);
1125
- const [errorMessage, setErrorMessage] = useState("");
1126
- const reportError = useCallback((message) => {
1127
- setErrorMessage(message);
1128
- }, []);
1129
- const recordEnrollmentResult = useCallback((result) => {
1130
- setEnrollmentResult(result);
1131
- }, []);
1132
- const setters = {
1133
- setStep,
1134
- setErrors,
1135
- setEnrollmentResult,
1136
- setErrorMessage
1137
- };
1138
- return {
1139
- errors,
1140
- enrollmentResult,
1141
- errorMessage,
1142
- reportError,
1143
- recordEnrollmentResult,
1144
- handleSubmit: () => submitDetails(state, setters),
1145
- handlePaymentContinue: () => continuePayment(state, setters)
1146
- };
1147
- }
1148
- //#endregion
1149
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.ts
1150
- const EMPTY_FORM = {
1151
- name: "",
1152
- email: "",
1153
- phone: "",
1154
- notes: "",
1155
- consentAccepted: false
1156
- };
1157
- function useWholeSeriesRegistrationPortal(api) {
1158
- const [formData, setFormData] = useState(EMPTY_FORM);
1159
- const [portalAuthState, setPortalAuthState] = useState("checking");
1160
- const updateFormData = useCallback((updater) => {
1161
- setFormData(updater);
1162
- }, []);
1163
- useEffect(() => {
1164
- let cancelled = false;
1165
- if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
1166
- setPortalAuthState("unauthenticated");
1167
- return;
1168
- }
1169
- setPortalAuthState("checking");
1170
- api.getPortalProfile().then((result) => {
1171
- if (cancelled) return;
1172
- setPortalAuthState("authenticated");
1173
- setFormData((current) => ({
1174
- ...current,
1175
- email: result.profile.email,
1176
- name: current.name || result.profile.name,
1177
- phone: current.phone || result.profile.phone || ""
1178
- }));
1179
- }).catch(() => {
1180
- if (!cancelled) setPortalAuthState("unauthenticated");
1181
- });
1182
- return () => {
1183
- cancelled = true;
1184
- };
1185
- }, [api]);
1186
- return {
1187
- formData,
1188
- updateFormData,
1189
- portalAuthState
1190
- };
1191
- }
1192
- //#endregion
1193
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.ts
1194
- function useWholeSeriesWaitlistSelection(input) {
1195
- useEffect(() => {
1196
- const claim = input.waitlistClaim.claim;
1197
- if (!claim || claim.subject.kind !== "whole_series") return;
1198
- const eventSeriesId = claim.subject.eventSeriesId;
1199
- const run = input.scopedRuns.find((candidate) => candidate.eventSeriesId === eventSeriesId);
1200
- if (!run) {
1201
- input.reportError("This waitlist claim is for a different run.");
1202
- input.goToStep("error");
1203
- return;
1204
- }
1205
- input.chooseRun(run);
1206
- input.updateFormData((current) => ({
1207
- ...current,
1208
- email: claim.prefill.email,
1209
- name: claim.prefill.name,
1210
- phone: claim.prefill.phone ?? "",
1211
- notes: claim.prefill.notes ?? ""
1212
- }));
1213
- if (input.step === "select-run") input.goToStep("enter-details");
1214
- }, [
1215
- input.chooseRun,
1216
- input.goToStep,
1217
- input.reportError,
1218
- input.scopedRuns,
1219
- input.step,
1220
- input.updateFormData,
1221
- input.waitlistClaim.claim
1222
- ]);
1223
- useEffect(() => {
1224
- if (input.waitlistClaim.requiresPortalLogin || !input.waitlistClaim.error) return;
1225
- input.reportError(input.waitlistClaim.error);
1226
- input.goToStep("error");
1227
- }, [
1228
- input.goToStep,
1229
- input.reportError,
1230
- input.waitlistClaim.error,
1231
- input.waitlistClaim.requiresPortalLogin
1232
- ]);
1233
- }
1234
- //#endregion
1235
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.ts
1236
- function useWholeSeriesRegistrationWizard(props, options = {}) {
1237
- return useWholeSeriesRegistrationWizardWithDeps(wholeSeriesRegistrationWizardDeps, props, options);
1238
- }
1239
- const wholeSeriesRegistrationWizardDeps = { readLocation: () => ({
1240
- search: window.location.search,
1241
- hash: window.location.hash
1242
- }) };
1243
- function useWholeSeriesRegistrationWizardWithDeps(deps, props, options = {}) {
1244
- const api = useBlockApi();
1245
- const [location] = useState(deps.readLocation);
1246
- const selection = useWholeSeriesRegistrationSelection(props, location);
1247
- const portal = useWholeSeriesRegistrationPortal(api);
1248
- const waitlistClaim = useWaitlistClaimForToken(new URLSearchParams(location.search).get("waitlist_claim")?.trim() || null);
1249
- const [bookingMode, setBookingMode] = useState(null);
1250
- const [altchaSolution, setAltchaSolution] = useState(null);
1251
- const eligibility = useWholeSeriesEligibility({
1252
- api,
1253
- selectedRun: selection.selectedRun,
1254
- hasPaidSelection: selection.selectedRunPricing?.hasPaidSelection ?? false,
1255
- portalAuthState: portal.portalAuthState,
1256
- waitlistClaimToken: waitlistClaim.token
1257
- });
1258
- const discountUi = useDiscountCodeUi({
1259
- api,
1260
- discountContext: useMemo(() => selection.selectedRun && selection.selectedRunPricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
1261
- type: "whole_series",
1262
- eventSeriesId: selection.selectedRun.eventSeriesId
1263
- } : null, [
1264
- eligibility.paymentChoice,
1265
- selection.selectedRun,
1266
- selection.selectedRunPricing?.selectedRequiresPayment
1267
- ]),
1268
- subtotalCents: selection.selectedRunPricing?.selectedPriceAmount ?? void 0
1269
- });
1270
- const actions = useWholeSeriesRegistrationActions({
1271
- api,
1272
- selectedRun: selection.selectedRun,
1273
- pricing: selection.selectedRunPricing,
1274
- formData: portal.formData,
1275
- portalAuthState: portal.portalAuthState,
1276
- eligibility: eligibility.runEligibility,
1277
- eligibleMemberships: eligibility.eligibleMemberships,
1278
- paymentChoice: eligibility.paymentChoice,
1279
- selectedMembershipId: eligibility.selectedMembershipId,
1280
- claimToken: waitlistClaim.token,
1281
- hasClaim: waitlistClaim.claim !== null,
1282
- altchaSolution,
1283
- discountCode: discountUi.discountCode,
1284
- options
1285
- }, selection.goToStep);
1286
- useWholeSeriesRegistrationEffects({
1287
- api,
1288
- actions,
1289
- portal,
1290
- selection,
1291
- waitlistClaim,
1292
- anchorId: options.anchorId ?? "event-registration",
1293
- location
1294
- });
1295
- return buildWholeSeriesRegistrationWizardResult({
1296
- api,
1297
- selection,
1298
- portal,
1299
- eligibility,
1300
- actions,
1301
- discountUi,
1302
- waitlistClaim,
1303
- view: deriveWholeSeriesRegistrationViewState({
1304
- scopedRuns: selection.scopedRuns,
1305
- selectedRun: selection.selectedRun,
1306
- pricing: selection.selectedRunPricing,
1307
- portalAuthState: portal.portalAuthState,
1308
- eligibleMembershipCount: eligibility.eligibleMemberships.length,
1309
- bookingMode,
1310
- step: selection.step,
1311
- waitlistRequiresPortalLogin: waitlistClaim.requiresPortalLogin
1312
- }),
1313
- bookingMode,
1314
- setBookingMode,
1315
- altchaSolution,
1316
- setAltchaSolution,
1317
- anchorId: options.anchorId ?? "event-registration"
1318
- });
1319
- }
1320
- function useWholeSeriesRegistrationEffects(input) {
1321
- useWholeSeriesPaymentVerification(input.api, {
1322
- setStep: input.selection.goToStep,
1323
- setErrorMessage: input.actions.reportError,
1324
- setEnrollmentResult: input.actions.recordEnrollmentResult
1325
- }, input.anchorId, input.location);
1326
- useWholeSeriesWaitlistSelection({
1327
- waitlistClaim: input.waitlistClaim,
1328
- scopedRuns: input.selection.scopedRuns,
1329
- step: input.selection.step,
1330
- goToStep: input.selection.goToStep,
1331
- chooseRun: input.selection.chooseRun,
1332
- updateFormData: input.portal.updateFormData,
1333
- reportError: input.actions.reportError
1334
- });
1335
- }
1336
- function buildWholeSeriesRegistrationWizardResult(parts) {
1337
- const handleBookingModeChange = (mode) => {
1338
- parts.setBookingMode(mode);
1339
- parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
1340
- };
1341
- return {
1342
- api: parts.api,
1343
- ...parts.selection,
1344
- ...parts.portal,
1345
- ...parts.eligibility,
1346
- ...parts.actions,
1347
- waitlistClaim: parts.waitlistClaim,
1348
- bookingMode: parts.bookingMode,
1349
- altchaSolution: parts.altchaSolution,
1350
- setAltchaSolution: parts.setAltchaSolution,
1351
- showSpamProtection: isSpamProtectionEnabled(),
1352
- discountUiOpen: parts.discountUi.discountUiOpen,
1353
- setDiscountUiOpen: parts.discountUi.setDiscountUiOpen,
1354
- discountCode: parts.discountUi.discountCode,
1355
- setDiscountCode: parts.discountUi.setDiscountCode,
1356
- discountsAvailable: parts.discountUi.discountsAvailable,
1357
- manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
1358
- discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
1359
- ...parts.view,
1360
- handleRunSelect: (run) => {
1361
- parts.selection.chooseRun(run);
1362
- parts.selection.goToStep("enter-details");
1363
- },
1364
- handleRetry: () => {
1365
- parts.selection.goToStep(parts.selection.scopedRuns.length === 1 ? "enter-details" : "select-run");
1366
- parts.actions.reportError("");
1367
- },
1368
- handleBookingModeChange,
1369
- handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(parts.anchorId) : void 0,
1370
- selectedRunPricingPayload: buildWholeSeriesPricingOptionPayload(parts.selection.selectedRunPricing)
1371
- };
1372
- }
1373
- //#endregion
1374
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/MembershipHero.tsx
1375
- /**
1376
- * Membership Hero for run registration.
1377
- * Thin wrapper around the shared MembershipHero with the canonical Event class prefix.
1378
- */
1379
- function MembershipHero(props) {
1380
- return /* @__PURE__ */ jsx(MembershipHero$1, {
1381
- ...props,
1382
- classPrefix: "er-whole-series"
1383
- });
1384
- }
1385
- //#endregion
1386
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/BookingModeStep.tsx
1387
- function BookingModeStep({ bookingMode, onBookingModeChange, eligibleMemberships, selectedMembershipId, onMembershipSelect, priceCents, currency, showEnrollForOtherLink = false, onEnrollForOther }) {
1388
- const hasSingleMembership = eligibleMemberships.length === 1;
1389
- const hasMultipleMemberships = eligibleMemberships.length > 1;
1390
- const showMembershipHero = hasSingleMembership && bookingMode === "membership" && eligibleMemberships[0];
1391
- const singleMembership = eligibleMemberships[0];
1392
- return /* @__PURE__ */ jsxs("div", {
1393
- className: "er-whole-series-booking-mode",
1394
- children: [
1395
- /* @__PURE__ */ jsx("h2", {
1396
- className: "er-whole-series-booking-mode__title",
1397
- children: "How would you like to enroll?"
1398
- }),
1399
- /* @__PURE__ */ jsx("p", {
1400
- className: "er-whole-series-booking-mode__subtitle",
1401
- children: "Choose how you want to book"
1402
- }),
1403
- showMembershipHero && singleMembership && /* @__PURE__ */ jsx(MembershipHero, { membershipName: singleMembership.membershipName }),
1404
- /* @__PURE__ */ jsxs("div", {
1405
- className: "er-whole-series-payment-tiles",
1406
- children: [
1407
- hasSingleMembership && singleMembership && /* @__PURE__ */ jsx(MembershipOption, {
1408
- membership: singleMembership,
1409
- selected: bookingMode === "membership",
1410
- description: "Use your membership to book for free",
1411
- onSelect: () => {
1412
- onBookingModeChange("membership");
1413
- onMembershipSelect(singleMembership.customerMembershipId);
1414
- }
1415
- }),
1416
- hasMultipleMemberships && eligibleMemberships.map((membership) => /* @__PURE__ */ jsx(MembershipOption, {
1417
- membership,
1418
- selected: bookingMode === "membership" && selectedMembershipId === membership.customerMembershipId,
1419
- description: "Use this membership to book for free",
1420
- onSelect: () => {
1421
- onBookingModeChange("membership");
1422
- onMembershipSelect(membership.customerMembershipId);
1423
- }
1424
- }, membership.customerMembershipId)),
1425
- /* @__PURE__ */ jsx(BookingOption, {
1426
- selected: bookingMode === "card",
1427
- name: "Pay by Card",
1428
- price: priceCents === null ? null : formatPrice(priceCents, currency),
1429
- description: "Pay with credit or debit card",
1430
- onSelect: () => {
1431
- onBookingModeChange("card");
1432
- onMembershipSelect(null);
1433
- }
1434
- })
1435
- ]
1436
- }),
1437
- showEnrollForOtherLink && onEnrollForOther && /* @__PURE__ */ jsx("div", {
1438
- className: "er-whole-series-booking-mode__link",
1439
- children: /* @__PURE__ */ jsx("a", {
1440
- onClick: onEnrollForOther,
1441
- role: "button",
1442
- tabIndex: 0,
1443
- children: "Enrolling for someone else?"
1444
- })
1445
- })
1446
- ]
1447
- });
1448
- }
1449
- function MembershipOption({ membership, selected, description, onSelect }) {
1450
- return /* @__PURE__ */ jsx(BookingOption, {
1451
- selected,
1452
- name: membership.membershipName,
1453
- price: "Free",
1454
- description,
1455
- onSelect
1456
- });
1457
- }
1458
- function BookingOption({ selected, name, price, description, onSelect }) {
1459
- return /* @__PURE__ */ jsxs("button", {
1460
- type: "button",
1461
- className: `er-whole-series-payment-tile${selected ? " er-whole-series-payment-tile--selected" : ""}`,
1462
- onClick: onSelect,
1463
- "aria-pressed": selected,
1464
- children: [
1465
- /* @__PURE__ */ jsx("div", {
1466
- className: "er-whole-series-payment-tile__check",
1467
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1468
- }),
1469
- /* @__PURE__ */ jsxs("div", {
1470
- className: "er-whole-series-payment-tile__header",
1471
- children: [/* @__PURE__ */ jsx("h3", {
1472
- className: "er-whole-series-payment-tile__name",
1473
- children: name
1474
- }), price ? /* @__PURE__ */ jsx("span", {
1475
- className: "er-whole-series-payment-tile__price",
1476
- children: price
1477
- }) : null]
1478
- }),
1479
- /* @__PURE__ */ jsx("p", {
1480
- className: "er-whole-series-payment-tile__description",
1481
- children: description
1482
- })
1483
- ]
1484
- });
1485
- }
1486
- //#endregion
1487
- //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
1488
- /**
1489
- * Displays the logged-in user's email with an optional logout link.
1490
- *
1491
- * Used in registration forms when the email field is locked due to portal authentication.
1492
- * Shows: "Logged in as {email} — Not you? Log out"
1493
- */
1494
- function LoggedInAsUser({ email, onLogout, classPrefix }) {
1495
- return /* @__PURE__ */ jsxs("p", {
1496
- className: `${classPrefix}-logged-in-hint`,
1497
- children: [
1498
- "Logged in as ",
1499
- email,
1500
- onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [" — ", /* @__PURE__ */ jsx("button", {
1501
- type: "button",
1502
- className: `${classPrefix}-link`,
1503
- onClick: onLogout,
1504
- children: "Not you? Log out"
1505
- })] })
1506
- ]
1507
- });
1508
- }
1509
- //#endregion
1510
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/components.tsx
1511
- function TeamMemberInlineList({ teamMembers }) {
1512
- return /* @__PURE__ */ jsx(Fragment, { children: teamMembers.map((teamMember, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 ? ", " : "", teamMember.profilePath ? /* @__PURE__ */ jsx("a", {
1513
- href: teamMember.profilePath,
1514
- children: teamMember.name
1515
- }) : teamMember.name] }, teamMember.id)) });
1516
- }
1517
- function RunCard({ run, isSelected, onSelect, showSessions, showPrice, showCapacity, showVenue }) {
1518
- const pricing = resolveWholeSeriesPricingState(run);
1519
- const view = buildRunCardView(run, pricing);
1520
- return /* @__PURE__ */ jsxs("div", {
1521
- className: `er-whole-series-run-card ${isSelected ? "er-whole-series-run-card--selected" : ""}`,
1522
- onClick: onSelect,
1523
- role: "button",
1524
- tabIndex: 0,
1525
- "aria-pressed": isSelected,
1526
- onKeyDown: (e) => {
1527
- if (e.key === "Enter" || e.key === " ") {
1528
- e.preventDefault();
1529
- onSelect();
1530
- }
1531
- },
1532
- children: [
1533
- /* @__PURE__ */ jsx("h3", {
1534
- className: "er-whole-series-run-card__title",
1535
- children: run.title
1536
- }),
1537
- view.enrollmentClosed && /* @__PURE__ */ jsx("p", {
1538
- className: "er-whole-series-run-card__status",
1539
- children: "Registration closed"
1540
- }),
1541
- showSessions && run.sessionsCount > 0 && /* @__PURE__ */ jsxs("p", {
1542
- className: "er-whole-series-run-card__sessions",
1543
- children: [
1544
- run.sessionsCount,
1545
- " session",
1546
- run.sessionsCount !== 1 ? "s" : ""
1547
- ]
1548
- }),
1549
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsx("p", {
1550
- className: "er-whole-series-run-card__price",
1551
- children: view.priceLabel
1552
- }),
1553
- showCapacity && run.availableSpots !== null && /* @__PURE__ */ jsx("p", {
1554
- className: "er-whole-series-run-card__capacity",
1555
- children: view.capacityLabel
1556
- }),
1557
- showVenue && run.venue && /* @__PURE__ */ jsx("p", {
1558
- className: "er-whole-series-run-card__venue",
1559
- children: run.venue.name
1560
- }),
1561
- view.teamMemberNames.length > 0 && /* @__PURE__ */ jsxs("p", {
1562
- className: "er-whole-series-run-card__venue",
1563
- children: ["Team: ", view.teamMemberNames.join(", ")]
1564
- })
1565
- ]
1566
- });
1567
- }
1568
- function buildRunCardView(run, pricing) {
1569
- const availableSpots = run.availableSpots ?? 0;
1570
- return {
1571
- enrollmentClosed: run.enrollmentOpen === false,
1572
- priceLabel: formatWholeSeriesPriceDisplay(pricing.display),
1573
- capacityLabel: availableSpots > 0 ? `${availableSpots} spot${availableSpots === 1 ? "" : "s"} available` : "Waitlist only",
1574
- teamMemberNames: (run.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean)
1575
- };
1576
- }
1577
- function RunSummary({ run, pricing, showSessions, showVenue, showPrice, showMembershipNote }) {
1578
- const teamMembers = run.teamMembers ?? [];
1579
- const priceLabel = pricing.selectedOption ? `${pricing.selectedOption.name} - ${formatWholeSeriesPriceAmount(pricing.selectedOption.priceAmount, pricing.currency)}` : formatWholeSeriesPriceDisplay(pricing.display);
1580
- return /* @__PURE__ */ jsxs("div", {
1581
- className: "er-whole-series-summary",
1582
- children: [
1583
- /* @__PURE__ */ jsx("h3", {
1584
- className: "er-whole-series-summary__title",
1585
- children: run.title
1586
- }),
1587
- showSessions && run.sessions.length > 0 && /* @__PURE__ */ jsxs("div", {
1588
- className: "er-whole-series-summary__sessions",
1589
- children: [/* @__PURE__ */ jsx("h4", {
1590
- className: "er-whole-series-summary__sessions-title",
1591
- children: "Sessions"
1592
- }), /* @__PURE__ */ jsx("ul", {
1593
- className: "er-whole-series-summary__sessions-list",
1594
- children: run.sessions.map((session) => /* @__PURE__ */ jsxs("li", {
1595
- className: "er-whole-series-summary__session",
1596
- children: [
1597
- formatDate(session.startsAt, { timeZone: session.timeZone }),
1598
- " ",
1599
- "at",
1600
- " ",
1601
- formatTime(session.startsAt, { timeZone: session.timeZone })
1602
- ]
1603
- }, session.id))
1604
- })]
1605
- }),
1606
- showVenue && run.venue && /* @__PURE__ */ jsxs("p", {
1607
- className: "er-whole-series-summary__venue",
1608
- children: [
1609
- /* @__PURE__ */ jsx("strong", { children: "Venue:" }),
1610
- " ",
1611
- run.venue.name,
1612
- run.venue.address && ` - ${run.venue.address}`
1613
- ]
1614
- }),
1615
- teamMembers.length > 0 && /* @__PURE__ */ jsxs("div", {
1616
- className: "er-whole-series-summary__venue",
1617
- children: [
1618
- /* @__PURE__ */ jsx("strong", { children: "Team:" }),
1619
- " ",
1620
- /* @__PURE__ */ jsx(TeamMemberInlineList, { teamMembers })
1621
- ]
1622
- }),
1623
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsxs("p", {
1624
- className: "er-whole-series-summary__price",
1625
- children: [
1626
- /* @__PURE__ */ jsx("strong", { children: pricing.selectableOptions.length > 0 ? "Pricing:" : "Price:" }),
1627
- " ",
1628
- priceLabel
1629
- ]
1630
- }),
1631
- showMembershipNote && /* @__PURE__ */ jsx("p", {
1632
- className: "er-whole-series-summary__membership",
1633
- children: "✓ Your membership can be used to book for free"
1634
- })
1635
- ]
1636
- });
1637
- }
1638
- function WholeSeriesPricingSelector({ pricing, selectedPricingOptionId, onSelect }) {
1639
- if (pricing.selectableOptions.length <= 1) return null;
1640
- return /* @__PURE__ */ jsxs("fieldset", {
1641
- className: "er-whole-series-form__field",
1642
- children: [/* @__PURE__ */ jsx("legend", {
1643
- id: "er-whole-series-pricing-options-label",
1644
- className: "er-whole-series-form__label",
1645
- children: "Pricing option"
1646
- }), /* @__PURE__ */ jsx("div", {
1647
- className: "er-whole-series-payment-tiles",
1648
- role: "radiogroup",
1649
- "aria-labelledby": "er-whole-series-pricing-options-label",
1650
- children: pricing.selectableOptions.map((option) => {
1651
- const isSelected = selectedPricingOptionId === option.id;
1652
- const priceLabel = formatWholeSeriesPriceAmount(option.priceAmount, pricing.currency);
1653
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("button", {
1654
- type: "button",
1655
- role: "radio",
1656
- "aria-checked": isSelected,
1657
- className: `er-whole-series-payment-tile${isSelected ? " er-whole-series-payment-tile--selected" : ""}`,
1658
- onClick: () => onSelect(option.id),
1659
- children: [/* @__PURE__ */ jsxs("div", {
1660
- className: "er-whole-series-payment-tile__header",
1661
- children: [/* @__PURE__ */ jsx("h3", {
1662
- className: "er-whole-series-payment-tile__name",
1663
- children: option.name
1664
- }), /* @__PURE__ */ jsx("span", {
1665
- className: "er-whole-series-payment-tile__price",
1666
- children: priceLabel
1667
- })]
1668
- }), option.description ? /* @__PURE__ */ jsx("p", {
1669
- className: "er-whole-series-payment-tile__description",
1670
- children: option.description
1671
- }) : null]
1672
- }) }, option.id);
1673
- })
1674
- })]
1675
- });
1676
- }
1677
- function WholeSeriesSlidingScaleInput({ pricing, value, onChange }) {
1678
- const slidingScale = pricing.slidingScale;
1679
- if (!slidingScale) return null;
1680
- const minLabel = formatWholeSeriesPriceAmount(slidingScale.minAmount, pricing.currency);
1681
- const maxLabel = formatWholeSeriesPriceAmount(slidingScale.maxAmount, pricing.currency);
1682
- const suggestedLabel = slidingScale.suggestedAmount !== null ? formatWholeSeriesPriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
1683
- return /* @__PURE__ */ jsxs("div", {
1684
- className: "er-whole-series-form__field",
1685
- children: [
1686
- /* @__PURE__ */ jsx("label", {
1687
- htmlFor: "er-whole-series-sliding-amount",
1688
- className: "er-whole-series-form__label",
1689
- children: "Amount"
1690
- }),
1691
- /* @__PURE__ */ jsx("input", {
1692
- id: "er-whole-series-sliding-amount",
1693
- type: "number",
1694
- min: slidingScale.minAmount / 100,
1695
- max: slidingScale.maxAmount / 100,
1696
- step: "0.01",
1697
- inputMode: "decimal",
1698
- className: "er-whole-series-form__input",
1699
- value,
1700
- onChange: (event) => onChange(event.target.value)
1701
- }),
1702
- /* @__PURE__ */ jsxs("p", {
1703
- className: "er-whole-series-text er-whole-series-text--muted",
1704
- children: [
1705
- "Choose between ",
1706
- minLabel,
1707
- " and ",
1708
- maxLabel,
1709
- suggestedLabel ? `; suggested ${suggestedLabel}` : "",
1710
- "."
1711
- ]
1712
- })
1713
- ]
1714
- });
1715
- }
1716
- function WholeSeriesConsentField({ consent, error, formData, isLoading, onChange }) {
1717
- const errorId = "er-whole-series-consent-error";
1718
- return /* @__PURE__ */ jsxs("div", {
1719
- className: "er-whole-series-form__field",
1720
- children: [
1721
- /* @__PURE__ */ jsx(BookingConsentAgreement, {
1722
- agreement: consent.agreement,
1723
- title: consent.title,
1724
- titleId: "er-whole-series-consent-title"
1725
- }),
1726
- /* @__PURE__ */ jsxs("label", {
1727
- className: "er-whole-series-form__label rb-flex rb-items-start rb-gap-2 rb-cursor-pointer",
1728
- children: [
1729
- /* @__PURE__ */ jsx("input", {
1730
- type: "checkbox",
1731
- className: "form-checkbox rb-mt-0.5",
1732
- checked: formData.consentAccepted === true,
1733
- disabled: isLoading,
1734
- "aria-describedby": error ? errorId : void 0,
1735
- onChange: (event) => onChange({
1736
- ...formData,
1737
- consentAccepted: event.target.checked
1738
- })
1739
- }),
1740
- consent.checkboxLabel,
1741
- " *"
1742
- ]
1743
- }),
1744
- error ? /* @__PURE__ */ jsx(FieldValidationMessage, {
1745
- id: errorId,
1746
- className: "er-whole-series-form__error",
1747
- children: error
1748
- }) : null
1749
- ]
1750
- });
1751
- }
1752
- function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout, consent }) {
1753
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1754
- /* @__PURE__ */ jsx(EnrollmentIdentityFields, {
1755
- formData,
1756
- errors,
1757
- onChange,
1758
- isEmailLocked,
1759
- isLoading,
1760
- onLogout
1761
- }),
1762
- /* @__PURE__ */ jsx(EnrollmentOptionalFields, {
1763
- formData,
1764
- onChange,
1765
- isLoading
1766
- }),
1767
- consent ? /* @__PURE__ */ jsx(WholeSeriesConsentField, {
1768
- consent,
1769
- error: errors.consentAccepted,
1770
- formData,
1771
- isLoading,
1772
- onChange
1773
- }) : null
1774
- ] });
1775
- }
1776
- function EnrollmentIdentityFields({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
1777
- const nameErrorId = "er-whole-series-name-error";
1778
- const emailErrorId = "er-whole-series-email-error";
1779
- const nameValidationProps = getFieldValidationControlProps({
1780
- message: errors.name,
1781
- messageId: nameErrorId
1782
- });
1783
- const emailValidationProps = getFieldValidationControlProps({
1784
- message: errors.email,
1785
- messageId: emailErrorId
1786
- });
1787
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1788
- className: "er-whole-series-form__field",
1789
- children: [
1790
- /* @__PURE__ */ jsx("label", {
1791
- htmlFor: "er-whole-series-name",
1792
- className: "er-whole-series-form__label",
1793
- children: "Name *"
1794
- }),
1795
- /* @__PURE__ */ jsx("input", {
1796
- id: "er-whole-series-name",
1797
- type: "text",
1798
- className: `er-whole-series-form__input ${errors.name ? "er-whole-series-form__input--error" : ""}`,
1799
- value: formData.name,
1800
- onChange: (e) => onChange({
1801
- ...formData,
1802
- name: e.target.value
1803
- }),
1804
- disabled: isLoading,
1805
- ...nameValidationProps
1806
- }),
1807
- errors.name && /* @__PURE__ */ jsx(FieldValidationMessage, {
1808
- id: nameErrorId,
1809
- className: "er-whole-series-form__error",
1810
- children: errors.name
1811
- })
1812
- ]
1813
- }), /* @__PURE__ */ jsxs("div", {
1814
- className: "er-whole-series-form__field",
1815
- children: [
1816
- /* @__PURE__ */ jsx("label", {
1817
- htmlFor: "er-whole-series-email",
1818
- className: "er-whole-series-form__label",
1819
- children: "Email *"
1820
- }),
1821
- /* @__PURE__ */ jsx("input", {
1822
- id: "er-whole-series-email",
1823
- type: "email",
1824
- className: `er-whole-series-form__input ${errors.email ? "er-whole-series-form__input--error" : ""}`,
1825
- value: formData.email,
1826
- onChange: (e) => onChange({
1827
- ...formData,
1828
- email: e.target.value
1829
- }),
1830
- disabled: isEmailLocked || isLoading,
1831
- ...emailValidationProps
1832
- }),
1833
- errors.email && /* @__PURE__ */ jsx(FieldValidationMessage, {
1834
- id: emailErrorId,
1835
- className: "er-whole-series-form__error",
1836
- children: errors.email
1837
- }),
1838
- isEmailLocked && /* @__PURE__ */ jsx(LoggedInAsUser, {
1839
- email: formData.email,
1840
- onLogout,
1841
- classPrefix: "er-whole-series"
1842
- })
1843
- ]
1844
- })] });
1845
- }
1846
- function EnrollmentOptionalFields({ formData, onChange, isLoading }) {
1847
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1848
- className: "er-whole-series-form__field",
1849
- children: [/* @__PURE__ */ jsx("label", {
1850
- htmlFor: "er-whole-series-phone",
1851
- className: "er-whole-series-form__label",
1852
- children: "Phone"
1853
- }), /* @__PURE__ */ jsx("input", {
1854
- id: "er-whole-series-phone",
1855
- type: "tel",
1856
- className: "er-whole-series-form__input",
1857
- value: formData.phone,
1858
- onChange: (e) => onChange({
1859
- ...formData,
1860
- phone: e.target.value
1861
- }),
1862
- disabled: isLoading
1863
- })]
1864
- }), /* @__PURE__ */ jsxs("div", {
1865
- className: "er-whole-series-form__field",
1866
- children: [/* @__PURE__ */ jsx("label", {
1867
- htmlFor: "er-whole-series-notes",
1868
- className: "er-whole-series-form__label",
1869
- children: "Notes"
1870
- }), /* @__PURE__ */ jsx("textarea", {
1871
- id: "er-whole-series-notes",
1872
- className: "er-whole-series-form__textarea",
1873
- value: formData.notes,
1874
- onChange: (e) => onChange({
1875
- ...formData,
1876
- notes: e.target.value
1877
- }),
1878
- rows: 3,
1879
- disabled: isLoading
1880
- })]
1881
- })] });
1882
- }
1883
- //#endregion
1884
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.tsx
1885
- function WholeSeriesRegistrationActiveStep({ wizard, display }) {
1886
- switch (wizard.step) {
1887
- case "select-run": return /* @__PURE__ */ jsx(RunSelectionStep, {
1888
- wizard,
1889
- display
1890
- });
1891
- case "enter-details": return /* @__PURE__ */ jsx(RegistrationDetailsStep, {
1892
- wizard,
1893
- display
1894
- });
1895
- case "booking-mode": return /* @__PURE__ */ jsx(RegistrationBookingModeStep, {
1896
- wizard,
1897
- display
1898
- });
1899
- case "select-payment": return /* @__PURE__ */ jsx(RegistrationPaymentStep, {
1900
- wizard,
1901
- display
1902
- });
1903
- case "error":
1904
- case "payment-failed":
1905
- case "redirecting":
1906
- case "submitting":
1907
- case "success":
1908
- case "verifying-payment":
1909
- case "verifying-timeout":
1910
- case "waitlist": return null;
1911
- }
1912
- }
1913
- function RunSelectionStep({ wizard, display }) {
1914
- return /* @__PURE__ */ jsx("div", {
1915
- className: "er-whole-series-run-list",
1916
- children: wizard.scopedRuns.map((run) => /* @__PURE__ */ jsx(RunCard, {
1917
- run,
1918
- isSelected: wizard.selectedRun?.eventSeriesId === run.eventSeriesId,
1919
- onSelect: () => wizard.handleRunSelect(run),
1920
- showSessions: display.showSessions,
1921
- showPrice: display.showPrice,
1922
- showCapacity: display.showCapacity,
1923
- showVenue: display.showVenue
1924
- }, run.eventSeriesId))
1925
- });
1926
- }
1927
- function RegistrationDetailsStep({ wizard, display }) {
1928
- const selection = selectedRunWithPricing(wizard);
1929
- if (!selection) return null;
1930
- return /* @__PURE__ */ jsxs("div", {
1931
- className: "er-whole-series-details",
1932
- children: [/* @__PURE__ */ jsx(RunSummary, {
1933
- run: selection.run,
1934
- pricing: selection.pricing,
1935
- showSessions: display.showSessions,
1936
- showVenue: display.showVenue,
1937
- showPrice: display.showPrice,
1938
- showMembershipNote: selection.run.acceptsMemberships && wizard.portalAuthState === "authenticated"
1939
- }), selection.run.enrollmentOpen === false ? /* @__PURE__ */ jsx(ClosedRunNotice, { wizard }) : /* @__PURE__ */ jsx(RegistrationDetailsForm, {
1940
- wizard,
1941
- display
1942
- })]
1943
- });
1944
- }
1945
- function ClosedRunNotice({ wizard }) {
1946
- return /* @__PURE__ */ jsxs("div", {
1947
- className: "er-whole-series-form",
1948
- children: [/* @__PURE__ */ jsx(BackToRunsButton, { wizard }), /* @__PURE__ */ jsx("p", {
1949
- className: "er-whole-series-text er-whole-series-text--muted",
1950
- children: "Registration closed."
1951
- })]
1952
- });
1953
- }
1954
- function RegistrationDetailsForm({ wizard, display }) {
1955
- const blockers = deriveDetailsBlockers(wizard);
1956
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("form", {
1957
- className: "er-whole-series-form",
1958
- onSubmit: (event) => {
1959
- event.preventDefault();
1960
- wizard.handleSubmit();
1961
- },
1962
- children: [
1963
- /* @__PURE__ */ jsx(EnrollmentForm, {
1964
- formData: wizard.formData,
1965
- errors: wizard.errors,
1966
- onChange: wizard.updateFormData,
1967
- isEmailLocked: wizard.portalAuthState === "authenticated" || wizard.waitlistClaim.claim !== null,
1968
- isLoading: wizard.portalAuthState === "checking" || wizard.waitlistClaim.isLoading,
1969
- onLogout: wizard.handleLogout,
1970
- consent: wizard.selectedRun?.consent ?? null
1971
- }),
1972
- /* @__PURE__ */ jsx(PricingFields, { wizard }),
1973
- wizard.showSpamProtection ? /* @__PURE__ */ jsx("div", {
1974
- className: "er-whole-series-altcha",
1975
- children: /* @__PURE__ */ jsx(AltchaWidget, {
1976
- challengeUrl: getChallengeUrl(),
1977
- onSolutionChange: wizard.setAltchaSolution
1978
- })
1979
- }) : null,
1980
- /* @__PURE__ */ jsx(DiscountFields, { wizard }),
1981
- /* @__PURE__ */ jsxs("div", {
1982
- className: "er-whole-series-actions",
1983
- children: [/* @__PURE__ */ jsx(BackToRunsButton, {
1984
- wizard,
1985
- compact: true
1986
- }), /* @__PURE__ */ jsx("button", {
1987
- type: "submit",
1988
- className: buttonClass(display.buttonVariant),
1989
- disabled: blockers.disabled,
1990
- children: detailsSubmitLabel(wizard, display.buttonText, blockers.soldOut)
1991
- })]
1992
- })
1993
- ]
1994
- }), /* @__PURE__ */ jsx(DetailsBlockerMessages, {
1995
- wizard,
1996
- blockers
1997
- })] });
1998
- }
1999
- function PricingFields({ wizard }) {
2000
- if (!wizard.selectedRunPricing) return null;
2001
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(WholeSeriesPricingSelector, {
2002
- pricing: wizard.selectedRunPricing,
2003
- selectedPricingOptionId: wizard.selectedPricingOptionId,
2004
- onSelect: wizard.choosePricingOption
2005
- }), /* @__PURE__ */ jsx(WholeSeriesSlidingScaleInput, {
2006
- pricing: wizard.selectedRunPricing,
2007
- value: wizard.selectedSlidingAmountInput,
2008
- onChange: wizard.changeSlidingAmount
2009
- })] });
2010
- }
2011
- function RegistrationBookingModeStep({ wizard, display }) {
2012
- const selection = selectedRunWithPricing(wizard);
2013
- if (!selection) return null;
2014
- const membershipMissing = wizard.bookingMode === "membership" && !wizard.selectedMembershipId;
2015
- return /* @__PURE__ */ jsxs("div", {
2016
- className: "er-whole-series-details",
2017
- children: [
2018
- /* @__PURE__ */ jsx(RunSummary, {
2019
- run: selection.run,
2020
- pricing: selection.pricing,
2021
- showSessions: display.showSessions,
2022
- showVenue: display.showVenue,
2023
- showPrice: display.showPrice,
2024
- showMembershipNote: false
2025
- }),
2026
- /* @__PURE__ */ jsx(BookingModeStep, {
2027
- bookingMode: wizard.bookingMode,
2028
- onBookingModeChange: wizard.handleBookingModeChange,
2029
- eligibleMemberships: wizard.eligibleMemberships,
2030
- selectedMembershipId: wizard.selectedMembershipId,
2031
- onMembershipSelect: wizard.chooseMembership,
2032
- priceCents: wizard.selectedRunPricing?.selectedPriceAmount ?? null,
2033
- currency: selection.run.currency ?? "GBP"
2034
- }),
2035
- /* @__PURE__ */ jsxs("div", {
2036
- className: "er-whole-series-actions",
2037
- children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
2038
- type: "button",
2039
- className: buttonClass(display.buttonVariant),
2040
- onClick: wizard.handlePaymentContinue,
2041
- disabled: !wizard.bookingMode || membershipMissing,
2042
- children: wizard.bookingMode === "membership" ? "Book run" : "Continue to payment"
2043
- })]
2044
- })
2045
- ]
2046
- });
2047
- }
2048
- function RegistrationPaymentStep({ wizard, display }) {
2049
- const selection = selectedRunWithPricing(wizard);
2050
- if (!selection) return null;
2051
- return /* @__PURE__ */ jsxs("div", {
2052
- className: "er-whole-series-details",
2053
- children: [/* @__PURE__ */ jsx(RunSummary, {
2054
- run: selection.run,
2055
- pricing: selection.pricing,
2056
- showSessions: display.showSessions,
2057
- showVenue: display.showVenue,
2058
- showPrice: display.showPrice,
2059
- showMembershipNote: false
2060
- }), /* @__PURE__ */ jsxs("div", {
2061
- className: "er-whole-series-form",
2062
- children: [
2063
- /* @__PURE__ */ jsx(PaymentChoices, { wizard }),
2064
- /* @__PURE__ */ jsx(DiscountFields, { wizard }),
2065
- /* @__PURE__ */ jsxs("div", {
2066
- className: "er-whole-series-actions",
2067
- children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
2068
- type: "button",
2069
- className: buttonClass(display.buttonVariant),
2070
- onClick: wizard.handlePaymentContinue,
2071
- children: "Continue"
2072
- })]
2073
- })
2074
- ]
2075
- })]
2076
- });
2077
- }
2078
- function PaymentChoices({ wizard }) {
2079
- return /* @__PURE__ */ jsxs("fieldset", {
2080
- className: "er-whole-series-form__field",
2081
- children: [/* @__PURE__ */ jsx("legend", {
2082
- className: "er-whole-series-form__label",
2083
- children: "Choose how to book"
2084
- }), /* @__PURE__ */ jsxs("div", {
2085
- className: "er-whole-series-payment__options",
2086
- children: [
2087
- /* @__PURE__ */ jsx(PaymentChoice, {
2088
- checked: wizard.paymentChoice === "membership",
2089
- label: "Use a membership (free)",
2090
- onChange: () => wizard.choosePaymentChoice("membership")
2091
- }),
2092
- wizard.paymentChoice === "membership" && wizard.eligibleMemberships.length > 1 ? /* @__PURE__ */ jsx(MembershipSelect, { wizard }) : null,
2093
- /* @__PURE__ */ jsx(PaymentChoice, {
2094
- checked: wizard.paymentChoice === "checkout",
2095
- label: "Pay by card",
2096
- onChange: () => wizard.choosePaymentChoice("checkout")
2097
- })
2098
- ]
2099
- })]
2100
- });
2101
- }
2102
- function PaymentChoice({ checked, label, onChange }) {
2103
- return /* @__PURE__ */ jsxs("label", {
2104
- className: "er-whole-series-payment__option",
2105
- children: [/* @__PURE__ */ jsx("input", {
2106
- type: "radio",
2107
- name: "paymentChoice",
2108
- checked,
2109
- onChange
2110
- }), /* @__PURE__ */ jsx("span", { children: label })]
2111
- });
2112
- }
2113
- function MembershipSelect({ wizard }) {
2114
- return /* @__PURE__ */ jsxs("div", {
2115
- className: "er-whole-series-form__field",
2116
- children: [/* @__PURE__ */ jsx("label", {
2117
- htmlFor: "er-whole-series-membership",
2118
- className: "er-whole-series-form__label",
2119
- children: "Membership"
2120
- }), /* @__PURE__ */ jsxs("select", {
2121
- id: "er-whole-series-membership",
2122
- className: "er-whole-series-form__input",
2123
- value: wizard.selectedMembershipId ?? "",
2124
- onChange: (event) => wizard.chooseMembership(event.target.value || null),
2125
- children: [/* @__PURE__ */ jsx("option", {
2126
- value: "",
2127
- disabled: true,
2128
- children: "Select a membership…"
2129
- }), wizard.eligibleMemberships.map((membership) => /* @__PURE__ */ jsx("option", {
2130
- value: membership.customerMembershipId,
2131
- children: membership.membershipName
2132
- }, membership.customerMembershipId))]
2133
- })]
2134
- });
2135
- }
2136
- function DiscountFields({ wizard }) {
2137
- if (!canShowDiscount(wizard)) return null;
2138
- return /* @__PURE__ */ jsx(DiscountCodeDisclosure, {
2139
- surface: "whole-series-registration",
2140
- isOpen: wizard.discountUiOpen,
2141
- code: wizard.discountCode,
2142
- onOpen: () => wizard.setDiscountUiOpen(true),
2143
- onChange: wizard.setDiscountCode,
2144
- onRemove: () => {
2145
- wizard.setDiscountCode("");
2146
- wizard.setDiscountUiOpen(false);
2147
- },
2148
- id: "er-whole-series-discount-code"
2149
- });
2150
- }
2151
- function deriveDetailsBlockers(wizard) {
2152
- const soldOut = wizard.waitlistClaim.claim === null && wizard.runEligibility?.isFull === true && wizard.runEligibility.canJoinWaitlist !== true;
2153
- const missingPricing = wizard.selectedRunPricing?.requiresSelection === true && !wizard.selectedRunPricing.selectedOption && !wizard.selectedRunPricing.slidingScale;
2154
- const slidingScaleMessage = slidingScaleBlocker(wizard.selectedRunPricing);
2155
- const pricingUnavailable = wizard.selectedRunPricing?.display.kind === "unavailable";
2156
- return {
2157
- disabled: soldOut || wizard.eligibilityLoading || missingPricing || slidingScaleMessage !== null || pricingUnavailable,
2158
- soldOut,
2159
- missingPricing,
2160
- slidingScaleMessage,
2161
- pricingUnavailable
2162
- };
2163
- }
2164
- function DetailsBlockerMessages({ wizard, blockers }) {
2165
- return /* @__PURE__ */ jsxs(Fragment, { children: [[
2166
- blockers.soldOut ? "This run is fully booked and there is no waitlist available right now." : null,
2167
- blockers.missingPricing ? "Choose a pricing option to continue." : null,
2168
- blockers.slidingScaleMessage,
2169
- blockers.pricingUnavailable ? "Pricing is not available for this run right now." : null
2170
- ].filter((message) => message !== null).map((message) => /* @__PURE__ */ jsx("p", {
2171
- className: "er-whole-series-text er-whole-series-text--muted",
2172
- children: message
2173
- }, message)), wizard.eligibilityError ? /* @__PURE__ */ jsx("p", {
2174
- className: "er-whole-series-text er-whole-series-text--error",
2175
- children: wizard.eligibilityError
2176
- }) : null] });
2177
- }
2178
- function BackToRunsButton({ wizard, compact = false }) {
2179
- if (wizard.scopedRuns.length <= 1) return null;
2180
- const button = /* @__PURE__ */ jsx("button", {
2181
- type: "button",
2182
- onClick: () => wizard.goToStep("select-run"),
2183
- className: "er-whole-series-back-btn",
2184
- children: "← Back"
2185
- });
2186
- return compact ? button : /* @__PURE__ */ jsx("div", {
2187
- className: "er-whole-series-actions",
2188
- children: button
2189
- });
2190
- }
2191
- function BackToDetailsButton({ wizard }) {
2192
- return /* @__PURE__ */ jsx("button", {
2193
- type: "button",
2194
- onClick: () => wizard.goToStep("enter-details"),
2195
- className: "er-whole-series-back-btn",
2196
- children: "← Back"
2197
- });
2198
- }
2199
- function selectedRunWithPricing(wizard) {
2200
- return wizard.selectedRun && wizard.selectedRunPricing ? {
2201
- run: wizard.selectedRun,
2202
- pricing: wizard.selectedRunPricing
2203
- } : null;
2204
- }
2205
- function canShowDiscount(wizard) {
2206
- return !wizard.discountsAvailableLoading && wizard.paymentChoice === "checkout" && wizard.discountsAvailable && wizard.manualCodeEntryAllowed;
2207
- }
2208
- function slidingScaleBlocker(pricing) {
2209
- if (!pricing?.slidingScale) return null;
2210
- if (pricing.selectedSlidingAmount === null) return "Choose an amount to continue.";
2211
- return pricing.selectedSlidingAmount < pricing.slidingScale.minAmount || pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount ? "Choose an amount within the sliding scale." : null;
2212
- }
2213
- function detailsSubmitLabel(wizard, buttonText, soldOut) {
2214
- if (wizard.eligibilityLoading) return "Checking availability…";
2215
- if (soldOut) return "Sold out";
2216
- return wizard.runEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
2217
- }
2218
- function buttonClass(variant) {
2219
- return themeButtonClassName({
2220
- variant: variant ?? "primary",
2221
- size: "md"
2222
- });
2223
- }
2224
- //#endregion
2225
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/ErrorStep.tsx
2226
- /**
2227
- * Error terminal state component.
2228
- * Shows error message with retry option.
2229
- */
2230
- function ErrorStep({ message, buttonText = "Try Again", buttonVariant = "primary", onRetry }) {
2231
- const buttonClass = themeButtonClassName({
2232
- variant: buttonVariant,
2233
- size: "md"
2234
- });
2235
- return /* @__PURE__ */ jsx(TerminalPanel, {
2236
- tone: "error",
2237
- className: "er-whole-series-error",
2238
- titleClassName: "er-whole-series-error__title",
2239
- icon: /* @__PURE__ */ jsx(StateIcon, {
2240
- variant: "error",
2241
- children: /* @__PURE__ */ jsx(CrossIcon, {})
2242
- }),
2243
- title: "Enrollment Failed",
2244
- body: /* @__PURE__ */ jsx("p", {
2245
- className: "er-whole-series-error__message",
2246
- children: message
2247
- }),
2248
- actionsClassName: "er-whole-series-error__retry",
2249
- actions: /* @__PURE__ */ jsx("button", {
2250
- type: "button",
2251
- onClick: onRetry,
2252
- className: buttonClass,
2253
- children: buttonText
2254
- })
2255
- });
2256
- }
2257
- //#endregion
2258
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/PaymentFailedStep.tsx
2259
- /**
2260
- * Payment failed terminal state component.
2261
- * Shows when payment could not be processed.
2262
- */
2263
- function PaymentFailedStep({ message = "Your payment could not be processed.", buttonText = "Try Again", buttonVariant = "primary", onRetry }) {
2264
- const buttonClass = themeButtonClassName({
2265
- variant: buttonVariant,
2266
- size: "md"
2267
- });
2268
- return /* @__PURE__ */ jsx(TerminalPanel, {
2269
- tone: "error",
2270
- className: "er-whole-series-payment-failed",
2271
- titleClassName: "er-whole-series-payment-failed__title",
2272
- icon: /* @__PURE__ */ jsx(StateIcon, {
2273
- variant: "error",
2274
- children: /* @__PURE__ */ jsx(CrossIcon, {})
2275
- }),
2276
- title: "Payment Failed",
2277
- body: /* @__PURE__ */ jsx("p", {
2278
- className: "er-whole-series-payment-failed__message",
2279
- children: message
2280
- }),
2281
- actionsClassName: "er-whole-series-payment-failed__retry",
2282
- actions: /* @__PURE__ */ jsx("button", {
2283
- type: "button",
2284
- onClick: onRetry,
2285
- className: buttonClass,
2286
- children: buttonText
2287
- })
2288
- });
2289
- }
2290
- //#endregion
2291
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/SuccessStep.tsx
2292
- /**
2293
- * Success terminal state component.
2294
- * Shows confirmation after successful enrollment.
2295
- */
2296
- function SuccessStep({ usedMembership, successMessage, membershipMessage }) {
2297
- return /* @__PURE__ */ jsx(TerminalPanel, {
2298
- tone: "success",
2299
- className: "er-whole-series-success",
2300
- titleClassName: "er-whole-series-success__title",
2301
- icon: /* @__PURE__ */ jsx(StateIcon, {
2302
- variant: "success",
2303
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 2 })
2304
- }),
2305
- title: "Enrollment Complete!",
2306
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2307
- className: "er-whole-series-success__message",
2308
- children: usedMembership ? membershipMessage : successMessage
2309
- }), usedMembership && /* @__PURE__ */ jsx("p", {
2310
- className: "er-whole-series-success__membership",
2311
- children: "Enrolled using your membership"
2312
- })] })
2313
- });
2314
- }
2315
- //#endregion
2316
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/VerifyingTimeoutStep.tsx
2317
- /**
2318
- * Verifying timeout terminal state component.
2319
- * Shows when payment verification takes too long.
2320
- */
2321
- function VerifyingTimeoutStep({ buttonText = "Check Again", buttonVariant = "primary", onCheckAgain, supportEmail }) {
2322
- const buttonClass = themeButtonClassName({
2323
- variant: buttonVariant,
2324
- size: "md"
2325
- });
2326
- return /* @__PURE__ */ jsx(TerminalPanel, {
2327
- tone: "warning",
2328
- className: "er-whole-series-error",
2329
- titleClassName: "er-whole-series-error__title",
2330
- icon: /* @__PURE__ */ jsx(StateIcon, {
2331
- variant: "warning",
2332
- children: /* @__PURE__ */ jsx(ClockIcon, {})
2333
- }),
2334
- title: "Payment Verification Taking Longer",
2335
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2336
- className: "er-whole-series-error__message",
2337
- children: "Your payment may still be processing. Please check your email for confirmation."
2338
- }), supportEmail && /* @__PURE__ */ jsxs("p", {
2339
- className: "er-whole-series-error__message",
2340
- children: [
2341
- "If you need help, contact us at",
2342
- " ",
2343
- /* @__PURE__ */ jsx("a", {
2344
- href: `mailto:${supportEmail}`,
2345
- children: supportEmail
2346
- })
2347
- ]
2348
- })] }),
2349
- actionsClassName: "er-whole-series-error__retry",
2350
- actions: /* @__PURE__ */ jsx("button", {
2351
- type: "button",
2352
- onClick: onCheckAgain,
2353
- className: buttonClass,
2354
- children: buttonText
2355
- })
2356
- });
2357
- }
2358
- //#endregion
2359
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WaitlistStep.tsx
2360
- /**
2361
- * Waitlist terminal state component.
2362
- * Shows confirmation when user is added to waitlist.
2363
- */
2364
- function WaitlistStep({ message, position }) {
2365
- return /* @__PURE__ */ jsx(TerminalPanel, {
2366
- tone: "info",
2367
- className: "er-whole-series-waitlist",
2368
- titleClassName: "er-whole-series-waitlist__title",
2369
- icon: /* @__PURE__ */ jsx(StateIcon, {
2370
- variant: "waitlist",
2371
- children: /* @__PURE__ */ jsx(ClockIcon, {})
2372
- }),
2373
- title: "Added to Waitlist",
2374
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2375
- className: "er-whole-series-waitlist__message",
2376
- children: message
2377
- }), typeof position === "number" && /* @__PURE__ */ jsxs("p", {
2378
- className: "er-whole-series-waitlist__position",
2379
- children: ["Your position: #", position]
2380
- })] })
2381
- });
2382
- }
2383
- //#endregion
2384
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.tsx
2385
- function WholeSeriesRegistrationTerminalContent({ wizard, copy }) {
2386
- switch (wizard.step) {
2387
- case "submitting": return /* @__PURE__ */ jsx(PendingState, {
2388
- label: "Booking run...",
2389
- spinnerLabel: "Processing"
2390
- });
2391
- case "redirecting": return /* @__PURE__ */ jsx(PendingState, {
2392
- label: "Redirecting to payment...",
2393
- spinnerLabel: "Redirecting"
2394
- });
2395
- case "verifying-payment": return /* @__PURE__ */ jsx(PendingState, {
2396
- label: "Verifying payment...",
2397
- spinnerLabel: "Verifying payment"
2398
- });
2399
- case "verifying-timeout": return /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
2400
- buttonVariant: copy.buttonVariant,
2401
- onCheckAgain: wizard.handleRetry
2402
- });
2403
- case "payment-failed": return /* @__PURE__ */ jsx(PaymentFailedStep, {
2404
- message: wizard.errorMessage,
2405
- buttonVariant: copy.buttonVariant,
2406
- onRetry: wizard.handleRetry
2407
- });
2408
- case "success": return /* @__PURE__ */ jsx(SuccessStep, {
2409
- usedMembership: wizard.enrollmentResult?.usedMembership,
2410
- successMessage: copy.successMessage,
2411
- membershipMessage: copy.membershipMessage
2412
- });
2413
- case "waitlist": return /* @__PURE__ */ jsx(WaitlistStep, {
2414
- message: copy.waitlistMessage,
2415
- position: wizard.enrollmentResult?.waitlistPosition
2416
- });
2417
- case "error": return /* @__PURE__ */ jsx(ErrorStep, {
2418
- message: wizard.errorMessage,
2419
- buttonVariant: copy.buttonVariant,
2420
- onRetry: wizard.handleRetry
2421
- });
2422
- case "booking-mode":
2423
- case "enter-details":
2424
- case "select-payment":
2425
- case "select-run": return null;
2426
- }
2427
- }
2428
- function PendingState({ label, spinnerLabel }) {
2429
- return /* @__PURE__ */ jsxs("div", {
2430
- className: "er-whole-series-center",
2431
- children: [/* @__PURE__ */ jsx(SpinnerNode, {
2432
- size: "md",
2433
- srLabel: spinnerLabel
2434
- }), /* @__PURE__ */ jsx("p", {
2435
- className: "er-whole-series-text--muted",
2436
- children: label
2437
- })]
2438
- });
2439
- }
2440
- //#endregion
2441
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.tsx
2442
- const DEFAULT_COPY = {
2443
- successMessage: "You're booked in! Check your email for confirmation and session details.",
2444
- waitlistMessage: "You've been added to the waitlist. We'll email you a claim link if a spot opens up.",
2445
- membershipMessage: "Booked using your membership! Check your email for session details.",
2446
- buttonText: "Sign up"
2447
- };
2448
- function WholeSeriesRegistrationWizard(props) {
2449
- const presentation = resolveWholeSeriesRegistrationPresentation(props.presentationKind ?? "event");
2450
- const wizard = useWholeSeriesRegistrationWizard(props, { anchorId: presentation.anchorId });
2451
- const className = `${presentation.rootClass} ${props.className ?? ""}`;
2452
- const emptyMessage = resolveEmptyMessage(props, wizard);
2453
- if (emptyMessage) return /* @__PURE__ */ jsx(RegistrationRoot, {
2454
- className,
2455
- presentation,
2456
- children: /* @__PURE__ */ jsx("div", {
2457
- className: "er-whole-series-empty",
2458
- children: /* @__PURE__ */ jsx("p", {
2459
- className: "er-whole-series-empty__text",
2460
- children: emptyMessage
2461
- })
2462
- })
2463
- });
2464
- return /* @__PURE__ */ jsx(RegistrationWorkspace, {
2465
- wizard,
2466
- props,
2467
- className,
2468
- presentation
2469
- });
2470
- }
2471
- function RegistrationWorkspace({ wizard, props, className, presentation }) {
2472
- const display = resolveDisplayProps(props);
2473
- const copy = resolveTerminalCopy(props);
2474
- const showSidebar = wizard.showPortalAuthSidebar;
2475
- return /* @__PURE__ */ jsx(RegistrationRoot, {
2476
- className,
2477
- presentation,
2478
- children: /* @__PURE__ */ jsx("div", {
2479
- className: "rb-reg-surface er-whole-series-container",
2480
- children: /* @__PURE__ */ jsxs("div", {
2481
- className: `er-whole-series-layout${showSidebar ? " er-whole-series-layout--with-sidebar" : ""}`,
2482
- children: [/* @__PURE__ */ jsxs("div", {
2483
- className: "er-whole-series-layout__main",
2484
- children: [
2485
- WIZARD_STEPS.includes(wizard.step) && wizard.totalSteps > 1 ? /* @__PURE__ */ jsx(StepIndicator, {
2486
- currentStep: wizard.currentStepNumber,
2487
- totalSteps: wizard.totalSteps,
2488
- stepLabels: wizard.stepLabels
2489
- }) : null,
2490
- /* @__PURE__ */ jsx(WholeSeriesRegistrationActiveStep, {
2491
- wizard,
2492
- display
2493
- }),
2494
- /* @__PURE__ */ jsx(WholeSeriesRegistrationTerminalContent, {
2495
- wizard,
2496
- copy
2497
- })
2498
- ]
2499
- }), showSidebar ? /* @__PURE__ */ jsx(RegistrationSidebar, { wizard }) : null]
2500
- })
2501
- })
2502
- });
2503
- }
2504
- function resolveDisplayProps(props) {
2505
- return {
2506
- showSessions: props.showSessions ?? true,
2507
- showPrice: props.showPrice ?? true,
2508
- showCapacity: props.showCapacity ?? true,
2509
- showVenue: props.showVenue ?? true,
2510
- buttonText: props.buttonText ?? DEFAULT_COPY.buttonText,
2511
- buttonVariant: props.buttonVariant
2512
- };
2513
- }
2514
- function resolveTerminalCopy(props) {
2515
- return {
2516
- successMessage: props.successMessage ?? DEFAULT_COPY.successMessage,
2517
- waitlistMessage: props.waitlistMessage ?? DEFAULT_COPY.waitlistMessage,
2518
- membershipMessage: props.membershipMessage ?? DEFAULT_COPY.membershipMessage,
2519
- buttonVariant: props.buttonVariant
2520
- };
2521
- }
2522
- function RegistrationRoot({ children, className, presentation }) {
2523
- return /* @__PURE__ */ jsx("div", {
2524
- id: presentation.anchorId,
2525
- className,
2526
- "data-block": presentation.dataBlock,
2527
- children
2528
- });
2529
- }
2530
- function RegistrationSidebar({ wizard }) {
2531
- return /* @__PURE__ */ jsx("div", {
2532
- className: "er-whole-series-layout__sidebar",
2533
- children: /* @__PURE__ */ jsx(PortalAuthSidebar, {
2534
- autoOpen: wizard.waitlistClaim.requiresPortalLogin,
2535
- loginMessage: wizard.waitlistClaim.loginMessage,
2536
- variant: wizard.waitlistClaim.requiresPortalLogin ? "waitlist-claim" : "membership"
2537
- })
2538
- });
2539
- }
2540
- function resolveEmptyMessage(props, wizard) {
2541
- if (wizard.scopedRuns.length === 0) return props.subject?.kind === "eventOffering" && props.subject.availableEventSeriesIds.length === 0 ? "New dates are coming soon. Booking will open when the next run is ready." : "No runs available to book.";
2542
- const allowedStatuses = wizard.api.config.isPreview ? ["active", "draft"] : ["active"];
2543
- return wizard.scopedRuns.some((run) => !run.status || allowedStatuses.includes(run.status)) ? null : "Booking is not currently available for this run.";
2544
- }
2545
- //#endregion
2546
- export { MagicLinkForm as a, useWaitlistClaim as i, LoggedInAsUser as n, WholeSeriesRegistrationErrorBoundary as o, logoutPortal as r, ClockIcon as s, WholeSeriesRegistrationWizard as t };