@riverbankcms/sdk 0.132.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 (328) hide show
  1. package/CHANGELOG.md +14 -3
  2. package/README.md +1 -1
  3. package/dist/{PreviewEditorSidebar-DKQ5eFK9.mjs → PreviewEditorSidebar-roNY0GVy.mjs} +4 -4
  4. package/dist/{PreviewEditorUI-CNTcOjCC.mjs → PreviewEditorUI-KboDbEh_.mjs} +3 -3
  5. package/dist/{PreviewQueryProvider-D51gQaG3.mjs → PreviewQueryProvider-DcgaESkm.mjs} +1 -1
  6. package/dist/{SdkPreviewModeRuntime-DJu3qu33.mjs → SdkPreviewModeRuntime-DBrF7Caa.mjs} +48 -17
  7. package/dist/{SiteChromeCustomizeContext-2TzT3vbj.mjs → SiteChromeCustomizeContext-DrIEpJKn.mjs} +4351 -7964
  8. package/dist/_dts/ai/src/contracts/proposals.d.ts +549 -549
  9. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +234 -234
  10. package/dist/_dts/api/src/accountApi.d.ts +5 -5
  11. package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +1 -1
  12. package/dist/_dts/api/src/bookingConfig.d.ts +1 -1
  13. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +25 -60
  14. package/dist/_dts/api/src/bookingOperations.d.ts +111 -173
  15. package/dist/_dts/api/src/bookingPaymentTermSchemas.d.ts +123 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +13 -13
  17. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +4 -4
  18. package/dist/_dts/api/src/bookingSessionSummaryTypes.d.ts +34 -0
  19. package/dist/_dts/api/src/bookings.d.ts +7 -11
  20. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -7
  21. package/dist/_dts/api/src/communications.d.ts +1 -1
  22. package/dist/_dts/api/src/contentRuntime.d.ts +1 -1
  23. package/dist/_dts/api/src/endpoints.d.ts +30 -110
  24. package/dist/_dts/api/src/eventManagementContracts.d.ts +1 -1
  25. package/dist/_dts/api/src/eventSeriesRegistrationEndpointDefinitions.d.ts +43 -0
  26. package/dist/_dts/api/src/index.d.ts +3 -4
  27. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  28. package/dist/_dts/api/src/navigation/contracts.d.ts +9 -6
  29. package/dist/_dts/api/src/navigation/linkResolver.d.ts +6 -2
  30. package/dist/_dts/api/src/navigation/types.d.ts +23 -6
  31. package/dist/_dts/api/src/navigation.d.ts +1 -1
  32. package/dist/_dts/api/src/participantMessaging.d.ts +2 -2
  33. package/dist/_dts/api/src/publicBookingService.d.ts +15 -0
  34. package/dist/_dts/api/src/publicEventEndpointDefinitions.d.ts +8 -0
  35. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +32 -28
  36. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +88 -6
  37. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +1 -1
  38. package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +9 -98
  39. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +7 -6
  40. package/dist/_dts/api/src/publicWholeSeriesEndpointDefinitions.d.ts +0 -32
  41. package/dist/_dts/api/src/sdk-event-payment-terms.d.ts +1 -1
  42. package/dist/_dts/api/src/sdk-event-upsert.d.ts +2 -2
  43. package/dist/_dts/api/src/sdkThemeWire.d.ts +50 -50
  44. package/dist/_dts/api/src/siteBanner.d.ts +4 -2
  45. package/dist/_dts/api/src/siteOperations.d.ts +2 -2
  46. package/dist/_dts/api/src/types.d.ts +2 -2
  47. package/dist/_dts/api/src/webhooks.d.ts +12 -12
  48. package/dist/_dts/api/src/{courses.d.ts → wholeSeriesOfferings.d.ts} +43 -95
  49. package/dist/_dts/blocks/src/client.d.ts +1 -6
  50. package/dist/_dts/blocks/src/contracts/index.d.ts +1 -1
  51. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +33 -166
  52. package/dist/_dts/blocks/src/index.d.ts +3 -2
  53. package/dist/_dts/blocks/src/portal/dateFormatting.d.ts +3 -0
  54. package/dist/_dts/blocks/src/portal/types.d.ts +17 -20
  55. package/dist/_dts/blocks/src/primitives/content/components/RichText.d.ts +2 -2
  56. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +1 -0
  57. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +147 -42
  58. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +46 -24
  59. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +3 -0
  60. package/dist/_dts/blocks/src/system/blocks/events/whole-series/schemas.d.ts +3 -3
  61. package/dist/_dts/blocks/src/system/blocks/events/whole-series/types.d.ts +6 -0
  62. package/dist/_dts/blocks/src/system/blocks/index.d.ts +0 -2
  63. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +4 -4
  64. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +148 -148
  65. package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +5 -4
  66. package/dist/_dts/blocks/src/system/blocks/offerings-preview/scheduleSummary.d.ts +3 -3
  67. package/dist/_dts/blocks/src/system/blocks/shared/bookingConsent.d.ts +36 -0
  68. package/dist/_dts/blocks/src/system/constants/blockKinds.d.ts +1 -1
  69. package/dist/_dts/blocks/src/system/manifest/hydrateLinks.d.ts +9 -2
  70. package/dist/_dts/blocks/src/system/manifest/resolveBlockData.d.ts +8 -0
  71. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +79 -79
  72. package/dist/_dts/blocks/src/system/node/builder.d.ts +0 -1
  73. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +9 -12
  74. package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +2 -44
  75. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  76. package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +2 -11
  77. package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +1 -1
  78. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +100 -59
  79. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  80. package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +19 -16
  81. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -0
  82. package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +1 -1
  83. package/dist/_dts/blocks/src/system/runtime/components/multi-step/DynamicFormFields.d.ts +3 -19
  84. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -247
  85. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +13 -126
  86. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +0 -1
  87. package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -3
  88. package/dist/_dts/blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.d.ts +2 -0
  89. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.consent.d.ts +10 -0
  90. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.field-values.d.ts +4 -0
  91. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.fields.d.ts +21 -0
  92. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +2 -1
  93. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +38 -144
  94. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +5 -19
  95. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +3 -2
  96. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/WholeSeriesPricingDisplay.d.ts +8 -0
  97. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/AttendeeDetailsStep.d.ts +2 -0
  98. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationBookingLayer.d.ts +17 -0
  99. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +24 -0
  100. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentBlockingPanel.d.ts +18 -0
  101. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +5 -0
  102. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/constants.d.ts +1 -0
  103. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +1 -3
  104. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +7 -4
  105. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +0 -1
  106. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +7 -8
  107. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/index.d.ts +1 -1
  108. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationDerivations.d.ts +4 -4
  109. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationEventAdapter.d.ts +3 -0
  110. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationStateMachine.d.ts +5 -0
  111. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +18 -1
  112. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationWizardContext.d.ts +28 -0
  113. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +12 -11
  114. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +53 -45
  115. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +10 -6
  116. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +9 -1
  117. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +24 -9
  118. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useWaitlistClaimRestoration.d.ts +20 -0
  119. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +5 -56
  120. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/validation.d.ts +2 -1
  121. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/waitlistClaimRestoration.d.ts +20 -0
  122. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +6 -22
  123. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/DateTimeTile.d.ts +1 -1
  124. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +40 -18
  125. package/dist/_dts/blocks/src/system/runtime/nodes/offerings-preview.d.ts +2 -2
  126. package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptions.d.ts +6 -1
  127. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingConsentAgreement.d.ts +7 -0
  128. package/dist/_dts/blocks/src/system/runtime/shared/components/DiscountCodeDisclosure.d.ts +1 -13
  129. package/dist/_dts/blocks/src/system/runtime/shared/components/LoggedInAsUser.d.ts +1 -1
  130. package/dist/_dts/blocks/src/system/runtime/shared/components/MembershipHero.d.ts +1 -1
  131. package/dist/_dts/blocks/src/system/runtime/shared/components/StateIcon.d.ts +1 -1
  132. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +1 -1
  133. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +2 -1
  134. package/dist/_dts/blocks/src/system/runtime/shared/utils/checkoutUrls.d.ts +2 -2
  135. package/dist/_dts/blocks/src/system/types/link.d.ts +7 -1
  136. package/dist/_dts/commerce/src/index.d.ts +16 -0
  137. package/dist/_dts/commerce/src/money.d.ts +122 -0
  138. package/dist/_dts/commerce/src/moneyContracts.d.ts +178 -0
  139. package/dist/_dts/commerce/src/moneyDateUtils.d.ts +22 -0
  140. package/dist/_dts/commerce/src/moneyPayments.d.ts +59 -0
  141. package/dist/_dts/commerce/src/moneyPlanningTime.d.ts +4 -0
  142. package/dist/_dts/commerce/src/moneyReceiptReadModel.d.ts +68 -0
  143. package/dist/_dts/commerce/src/moneyReport.d.ts +105 -0
  144. package/dist/_dts/commerce/src/moneyReportBreakdowns.d.ts +3 -0
  145. package/dist/_dts/commerce/src/moneyReportKindFilter.d.ts +4 -0
  146. package/dist/_dts/commerce/src/moneyReportPage.d.ts +132 -0
  147. package/dist/_dts/commerce/src/purchase/checkoutCollectionPlan.d.ts +1 -1
  148. package/dist/_dts/commerce/src/purchase/confirmationEmailPayment.d.ts +1 -1
  149. package/dist/_dts/commerce/src/purchase/orderCompletionEmailPlan.d.ts +3 -3
  150. package/dist/_dts/commerce/src/purchase/orderFulfillmentPlan.d.ts +6 -25
  151. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +4 -4
  152. package/dist/_dts/commerce/src/purchase/orderPlanningTypes.d.ts +11 -11
  153. package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +1 -1
  154. package/dist/_dts/commerce/src/purchase/persistedCheckoutLines.d.ts +1 -1
  155. package/dist/_dts/commerce/src/purchase/types.d.ts +12 -8
  156. package/dist/_dts/commerce/src/shop/digitalFulfillment.d.ts +111 -0
  157. package/dist/_dts/commerce/src/shop/fulfillmentStatus.d.ts +10 -0
  158. package/dist/_dts/commerce/src/shop/inventoryRestore.d.ts +13 -0
  159. package/dist/_dts/commerce/src/shop/shippingAddress.d.ts +18 -0
  160. package/dist/_dts/commerce/src/types/json.d.ts +3 -0
  161. package/dist/_dts/commerce/src/utils/isPlainRecord.d.ts +1 -0
  162. package/dist/_dts/commerce/src/waitlists.d.ts +172 -0
  163. package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +0 -30
  164. package/dist/_dts/content-model/src/content-types/builtins.d.ts +2 -39
  165. package/dist/_dts/content-model/src/content-types/schema.d.ts +4 -4
  166. package/dist/_dts/content-model/src/metadataConfig.d.ts +0 -1
  167. package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -68
  168. package/dist/_dts/core/src/booking-consent.d.ts +8 -0
  169. package/dist/_dts/core/src/branded.d.ts +3 -3
  170. package/dist/_dts/core/src/event-pricing.d.ts +6 -6
  171. package/dist/_dts/core/src/index.d.ts +1 -0
  172. package/dist/_dts/core/src/participants.d.ts +17 -17
  173. package/dist/_dts/core/src/rectification.d.ts +1 -1
  174. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +899 -2157
  175. package/dist/_dts/db/src/schemas/forms.d.ts +21 -21
  176. package/dist/_dts/db/src/types/jsonb.d.ts +1 -1
  177. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +2 -1
  178. package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +2 -1
  179. package/dist/_dts/editor/src/primitives/rich-text/toolbar/linkPopoverUtils.d.ts +3 -2
  180. package/dist/_dts/editor/src/primitives/rich-text/useRichTextEditor.d.ts +3 -4
  181. package/dist/_dts/media-core/src/usageScanner.d.ts +1 -1
  182. package/dist/_dts/sdk/src/bookings/index.d.ts +4 -5
  183. package/dist/_dts/sdk/src/bookings/types.d.ts +8 -60
  184. package/dist/_dts/sdk/src/config/validation.d.ts +30 -30
  185. package/dist/_dts/sdk/src/contracts/content.d.ts +10 -36
  186. package/dist/_dts/sdk/src/contracts/rendering.d.ts +1 -1
  187. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +9 -9
  188. package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -19
  189. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +4 -6
  190. package/dist/_dts/sdk/src/version.d.ts +1 -1
  191. package/dist/_dts/theme-core/src/accordions/types.d.ts +2 -2
  192. package/dist/_dts/theme-core/src/blocks/vars/index.d.ts +0 -2
  193. package/dist/_dts/theme-core/src/buttons/types.d.ts +12 -12
  194. package/dist/_dts/theme-core/src/cards/types.d.ts +5 -5
  195. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  196. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +72 -72
  197. package/dist/_dts/theme-core/src/navigation/types.d.ts +4 -4
  198. package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
  199. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +2 -2
  200. package/dist/_dts/theme-core/src/schema.d.ts +82 -82
  201. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +1 -1
  202. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +1 -1
  203. package/dist/_dts/theme-core/src/site-styles/cardRoleVocabulary.d.ts +1 -1
  204. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  205. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -4
  206. package/dist/_dts/theme-core/src/site-styles/logoBranding.d.ts +4 -4
  207. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +1 -1
  208. package/dist/_dts/ui/src/badge.d.ts +1 -1
  209. package/dist/_dts/ui/src/button.d.ts +1 -1
  210. package/dist/_dts/ui/src/callout.d.ts +1 -1
  211. package/dist/_dts/ui/src/card.d.ts +1 -1
  212. package/dist/client/{usePolling-M5jG675x.mjs → BookingConsentAgreement-BQqwi8Oa.mjs} +180 -4
  213. package/dist/client/{DiscountCodeDisclosure-DO7llLxm.mjs → DiscountCodeDisclosure-B97aMo0V.mjs} +13 -27
  214. package/dist/client/{EventCombined.client-xID7zN__.mjs → EventCombined.client-Bs2Iw9Q6.mjs} +3 -3
  215. package/dist/client/{EventListing.client-CriBslp0.mjs → EventListing.client-C4QUQdmg.mjs} +2 -2
  216. package/dist/client/{LeafletStaticMap-DYmHnM8g.mjs → LeafletStaticMap-CwWRk69M.mjs} +1 -1
  217. package/dist/client/{accordion-CgFbnnnQ.mjs → accordion-BA0j8Mpw.mjs} +1 -1
  218. package/dist/client/{bookingForm-dUyGpbxc.mjs → bookingForm-Br2e41H0.mjs} +72 -47
  219. package/dist/client/bookings.mjs +1987 -2132
  220. package/dist/client/{carousel-BvBwkUzx.mjs → carousel-B4dmwnpD.mjs} +1 -1
  221. package/dist/client/{cart-DiZENT2E.mjs → cart-B_ckGW4b.mjs} +3 -3
  222. package/dist/client/{checkout-Dq13KIgR.mjs → checkout-DAyspHdf.mjs} +3 -3
  223. package/dist/client/checkoutUrls-BuseL0dw.mjs +189 -0
  224. package/dist/client/client.mjs +5627 -9543
  225. package/dist/client/{context-B83PiNzm.mjs → context-DljQn8L5.mjs} +15 -82
  226. package/dist/client/{eventCalendar-BF0Jatfw.mjs → eventCalendar-pJu3FUod.mjs} +5 -5
  227. package/dist/client/{eventCombined-BuoCF8je.mjs → eventCombined-B6Kacm9F.mjs} +3 -3
  228. package/dist/client/{eventDetails-CKwh0S9s.mjs → eventDetails-CaX9z1pv.mjs} +8 -8
  229. package/dist/client/{eventListing-eUxaWFaB.mjs → eventListing-B9aXPO-I.mjs} +3 -3
  230. package/dist/client/{eventRegistration-CfkNOkPb.mjs → eventRegistration-CBSovBkg.mjs} +4550 -3671
  231. package/dist/client/{form-C17H1c_H.mjs → form-Cm0tu_7o.mjs} +2 -2
  232. package/dist/client/{headerSection-DEwUmrtt.mjs → headerSection-OgRtHeKS.mjs} +2 -2
  233. package/dist/client/hooks.mjs +535 -694
  234. package/dist/client/{locationMap-Pf2QwuvW.mjs → locationMap-DmjcYqNM.mjs} +2 -2
  235. package/dist/client/{newsletterForm-BWQAH5Sv.mjs → newsletterForm-D08OZQAC.mjs} +2 -2
  236. package/dist/client/{productDetail-BZi1Fa_G.mjs → productDetail-BqZeu2P4.mjs} +3 -3
  237. package/dist/client/{productList-qq-55DNk.mjs → productList-mNyIF9FG.mjs} +3 -3
  238. package/dist/client/{propsDecoder-BxmqPKdP.mjs → propsDecoder-DwHXRm9X.mjs} +4850 -4502
  239. package/dist/client/rendering/client.mjs +59921 -62298
  240. package/dist/client/rendering/islands.mjs +17 -19
  241. package/dist/client/rendering.mjs +6226 -10236
  242. package/dist/client/{scrollToBlock-B3CcKdtG.mjs → scrollToBlock-DtmdM3v-.mjs} +2 -2
  243. package/dist/client/{shop-DNWJPut5.mjs → shop-CNjZK16F.mjs} +6 -6
  244. package/dist/client/{shop-commerce-BhvQCosS.mjs → shop-commerce-DkNNao1J.mjs} +7 -164
  245. package/dist/client/{shop-commerce-store-B04sCNnW.mjs → shop-commerce-store-9WA--zuW.mjs} +1 -1
  246. package/dist/client/{shopShared-DNNgZlmW.mjs → shopShared-CHCVfccY.mjs} +3 -3
  247. package/dist/client/{useEventFilters-CUmhE24_.mjs → useEventFilters-DvuaB4ZN.mjs} +3 -3
  248. package/dist/preview-next/before-render.mjs +40 -161
  249. package/dist/preview-next/client/runtime.mjs +4 -4
  250. package/dist/preview-next/keepAlive.mjs +40 -161
  251. package/dist/preview-next/middleware.mjs +40 -161
  252. package/dist/{previewAuthStore-BFKd4LrN.mjs → previewAuthStore-C7ksxt5b.mjs} +40 -161
  253. package/dist/{sdk-runtime-BEXb1wqo.mjs → sdk-runtime-3GhW4knb.mjs} +2 -2
  254. package/dist/{separator-DGMuip1D.mjs → separator-D3bCWYYb.mjs} +1 -1
  255. package/dist/server/components.mjs +634 -2969
  256. package/dist/server/config-validation.mjs +535 -694
  257. package/dist/server/config.mjs +535 -694
  258. package/dist/server/data.mjs +535 -694
  259. package/dist/server/index.mjs +41 -162
  260. package/dist/server/next.mjs +644 -2979
  261. package/dist/server/page-converter.mjs +435 -561
  262. package/dist/server/prebuild.mjs +1 -1
  263. package/dist/server/rendering/server.mjs +635 -2874
  264. package/dist/server/rendering.mjs +634 -2969
  265. package/dist/server/routing.mjs +706 -1138
  266. package/dist/server/server.mjs +549 -708
  267. package/dist/server/theme-bridge.mjs +152 -1635
  268. package/dist/styles/index.css +41 -1348
  269. package/package.json +2 -2
  270. package/dist/_dts/api/src/courseEndpointDefinitions.d.ts +0 -99
  271. package/dist/_dts/blocks/src/client/course-registration.d.ts +0 -5
  272. package/dist/_dts/blocks/src/system/blocks/course-details.d.ts +0 -134
  273. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +0 -130
  274. package/dist/_dts/blocks/src/system/blocks/courses/shared/index.d.ts +0 -3
  275. package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +0 -2
  276. package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +0 -1
  277. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +0 -1
  278. package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +0 -133
  279. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +0 -28
  280. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/logic.d.ts +0 -11
  281. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/runs.d.ts +0 -10
  282. package/dist/_dts/blocks/src/system/runtime/nodes/course-details/view.d.ts +0 -15
  283. package/dist/_dts/blocks/src/system/runtime/nodes/course-details.server.d.ts +0 -20
  284. package/dist/_dts/blocks/src/system/runtime/nodes/course-page-surface-scope.d.ts +0 -14
  285. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.client.d.ts +0 -10
  286. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +0 -181
  287. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.server.d.ts +0 -12
  288. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/CoursePricingDisplay.d.ts +0 -8
  289. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/BookingModeStep.d.ts +0 -32
  290. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/CheckIcon.d.ts +0 -4
  291. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/ErrorStep.d.ts +0 -17
  292. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/MembershipHero.d.ts +0 -12
  293. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/PaymentFailedStep.d.ts +0 -17
  294. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/PortalAuthSidebar.d.ts +0 -9
  295. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/StepIndicator.d.ts +0 -6
  296. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/SuccessStep.d.ts +0 -14
  297. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/VerifyingTimeoutStep.d.ts +0 -17
  298. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WaitlistStep.d.ts +0 -12
  299. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.d.ts +0 -9
  300. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationErrorBoundary.d.ts +0 -25
  301. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.d.ts +0 -8
  302. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.d.ts +0 -8
  303. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/components.d.ts +0 -45
  304. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/index.d.ts +0 -18
  305. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/presentation.d.ts +0 -7
  306. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/pricing.d.ts +0 -14
  307. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/types.d.ts +0 -105
  308. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesEligibility.d.ts +0 -24
  309. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesPaymentVerification.d.ts +0 -10
  310. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationActions.d.ts +0 -35
  311. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.d.ts +0 -7
  312. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationSelection.d.ts +0 -35
  313. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.d.ts +0 -185
  314. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.d.ts +0 -14
  315. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/utils.d.ts +0 -43
  316. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.contract.d.ts +0 -323
  317. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/whole-series-registration.headless.planning.d.ts +0 -27
  318. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesPageSurfaceScope.d.ts +0 -17
  319. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wholeSeriesRegistrationViewState.d.ts +0 -21
  320. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/whole-series/wizardSteps.d.ts +0 -30
  321. package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +0 -3
  322. package/dist/_dts/theme-core/src/blocks/vars/course-details.d.ts +0 -16
  323. package/dist/_dts/theme-core/src/blocks/vars/course-registration.d.ts +0 -21
  324. package/dist/client/StepIndicator-CGixP_LW.mjs +0 -138
  325. package/dist/client/WholeSeriesRegistrationWizard-BEjzSiOA.mjs +0 -2496
  326. package/dist/client/checkoutUrls-Ct8Mxna3.mjs +0 -26
  327. package/dist/client/courseRegistration-CKC5NmyH.mjs +0 -52
  328. package/dist/client/pricing-CVdvbopJ.mjs +0 -195
@@ -1,2496 +0,0 @@
1
- "use client";
2
- import { At as formatBookingDate, Bt as parseEventPageSurfaceSubject, Jt as assertNever$1, Nt as formatBookingTime, Rt as toBookingTimeZone, St as assertNever, et as themeButtonClassName, zt as toScheduledBookingDateTime } from "./propsDecoder-BxmqPKdP.mjs";
3
- import { n as formatWholeSeriesPriceDisplay, r as resolveWholeSeriesPricingState, t as formatWholeSeriesPriceAmount } from "./pricing-CVdvbopJ.mjs";
4
- import { n as useBlockApi } from "./context-B83PiNzm.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-B3CcKdtG.mjs";
7
- import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-DO7llLxm.mjs";
8
- import { n as SpinnerNode, r as formatPrice, t as StepIndicator$1 } from "./StepIndicator-CGixP_LW.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-Ct8Mxna3.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
- setters.setErrors(errors);
1007
- if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
1008
- const pricingMessage = getMissingWholeSeriesPricingSelectionMessage(state.pricing);
1009
- if (pricingMessage) return blocked(pricingMessage, setters);
1010
- if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This run is fully booked.", setters);
1011
- if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
1012
- return null;
1013
- }
1014
- function enrollmentPayload(state, payment) {
1015
- return {
1016
- ...registrantPayload(state),
1017
- paymentMethod: payment.method,
1018
- ...payment.method === "membership" ? { customerMembershipId: payment.membershipId } : {}
1019
- };
1020
- }
1021
- function registrantPayload(state) {
1022
- return {
1023
- eventSeriesId: state.selectedRun.eventSeriesId,
1024
- ...buildWholeSeriesPricingOptionPayload(state.pricing),
1025
- email: state.formData.email.trim().toLowerCase(),
1026
- name: state.formData.name.trim(),
1027
- phone: state.formData.phone.trim() || void 0,
1028
- formData: { notes: state.formData.notes.trim() || void 0 },
1029
- altchaSolution: state.altchaSolution,
1030
- claimToken: state.claimToken ?? void 0
1031
- };
1032
- }
1033
- async function enroll(state, setters, payment) {
1034
- setters.setStep("submitting");
1035
- try {
1036
- const result = await state.api.registerForWholeSeries(enrollmentPayload(state, payment));
1037
- setters.setEnrollmentResult({
1038
- status: result.status,
1039
- waitlistPosition: result.waitlistPosition ?? void 0,
1040
- usedMembership: payment.method === "membership"
1041
- });
1042
- setters.setStep(result.status === "waitlist" ? "waitlist" : "success");
1043
- return { kind: "state-updated" };
1044
- } catch (cause) {
1045
- const message = cause instanceof Error ? cause.message : "Booking failed";
1046
- setters.setErrorMessage(message);
1047
- setters.setStep("error");
1048
- return {
1049
- kind: "failed",
1050
- message
1051
- };
1052
- }
1053
- }
1054
- async function checkout(state, setters) {
1055
- setters.setStep("submitting");
1056
- try {
1057
- const urls = buildCheckoutReturnUrls("enrollment", state.options.anchorId ?? "event-registration");
1058
- const result = await state.api.createWholeSeriesCheckout({
1059
- ...registrantPayload(state),
1060
- discountCode: state.discountCode.trim() || void 0,
1061
- successUrl: urls.successUrl,
1062
- cancelUrl: urls.cancelUrl
1063
- });
1064
- if (result.bypassed) {
1065
- setters.setEnrollmentResult({
1066
- status: "enrolled",
1067
- usedMembership: false
1068
- });
1069
- setters.setStep("success");
1070
- return { kind: "state-updated" };
1071
- }
1072
- if (!result.checkoutUrl) throw new Error("Checkout URL missing");
1073
- setters.setStep("redirecting");
1074
- if (state.options.onCheckoutRedirect) state.options.onCheckoutRedirect(result.checkoutUrl);
1075
- else window.location.href = result.checkoutUrl;
1076
- return {
1077
- kind: "checkout-redirect",
1078
- checkoutUrl: result.checkoutUrl
1079
- };
1080
- } catch (cause) {
1081
- const message = cause instanceof Error ? cause.message : "Checkout failed";
1082
- setters.setErrorMessage(message);
1083
- setters.setStep("error");
1084
- return {
1085
- kind: "failed",
1086
- message
1087
- };
1088
- }
1089
- }
1090
- async function submitDetails(state, setters) {
1091
- const invalid = validateSubmission(state, setters);
1092
- if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1093
- if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
1094
- const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
1095
- const canUseMembership = requiresPayment && state.selectedRun.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
1096
- if (requiresPayment && canUseMembership) {
1097
- setters.setStep("select-payment");
1098
- return { kind: "state-updated" };
1099
- }
1100
- if (requiresPayment) return checkout(state, setters);
1101
- return enroll(state, setters, { method: "free" });
1102
- }
1103
- async function continuePayment(state, setters) {
1104
- const invalid = validateSubmission(state, setters);
1105
- if (invalid || !state.selectedRun) return invalid ?? { kind: "validation-failed" };
1106
- if (!state.pricing?.selectedRequiresPayment) {
1107
- setters.setStep("enter-details");
1108
- return { kind: "state-updated" };
1109
- }
1110
- const selectedState = state;
1111
- if (state.paymentChoice === "membership") {
1112
- if (!state.selectedMembershipId) return blocked("Select a membership to sign up.", setters);
1113
- return enroll(selectedState, setters, {
1114
- method: "membership",
1115
- membershipId: state.selectedMembershipId
1116
- });
1117
- }
1118
- return checkout(selectedState, setters);
1119
- }
1120
- function useWholeSeriesRegistrationActions(state, setStep) {
1121
- const [errors, setErrors] = useState({});
1122
- const [enrollmentResult, setEnrollmentResult] = useState(null);
1123
- const [errorMessage, setErrorMessage] = useState("");
1124
- const reportError = useCallback((message) => {
1125
- setErrorMessage(message);
1126
- }, []);
1127
- const recordEnrollmentResult = useCallback((result) => {
1128
- setEnrollmentResult(result);
1129
- }, []);
1130
- const setters = {
1131
- setStep,
1132
- setErrors,
1133
- setEnrollmentResult,
1134
- setErrorMessage
1135
- };
1136
- return {
1137
- errors,
1138
- enrollmentResult,
1139
- errorMessage,
1140
- reportError,
1141
- recordEnrollmentResult,
1142
- handleSubmit: () => submitDetails(state, setters),
1143
- handlePaymentContinue: () => continuePayment(state, setters)
1144
- };
1145
- }
1146
- //#endregion
1147
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationPortal.ts
1148
- const EMPTY_FORM = {
1149
- name: "",
1150
- email: "",
1151
- phone: "",
1152
- notes: ""
1153
- };
1154
- function useWholeSeriesRegistrationPortal(api) {
1155
- const [formData, setFormData] = useState(EMPTY_FORM);
1156
- const [portalAuthState, setPortalAuthState] = useState("checking");
1157
- const updateFormData = useCallback((updater) => {
1158
- setFormData(updater);
1159
- }, []);
1160
- useEffect(() => {
1161
- let cancelled = false;
1162
- if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
1163
- setPortalAuthState("unauthenticated");
1164
- return;
1165
- }
1166
- setPortalAuthState("checking");
1167
- api.getPortalProfile().then((result) => {
1168
- if (cancelled) return;
1169
- setPortalAuthState("authenticated");
1170
- setFormData((current) => ({
1171
- ...current,
1172
- email: result.profile.email,
1173
- name: current.name || result.profile.name,
1174
- phone: current.phone || result.profile.phone || ""
1175
- }));
1176
- }).catch(() => {
1177
- if (!cancelled) setPortalAuthState("unauthenticated");
1178
- });
1179
- return () => {
1180
- cancelled = true;
1181
- };
1182
- }, [api]);
1183
- return {
1184
- formData,
1185
- updateFormData,
1186
- portalAuthState
1187
- };
1188
- }
1189
- //#endregion
1190
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesWaitlistSelection.ts
1191
- function useWholeSeriesWaitlistSelection(input) {
1192
- useEffect(() => {
1193
- const claim = input.waitlistClaim.claim;
1194
- if (!claim || claim.subject.kind !== "whole_series") return;
1195
- const eventSeriesId = claim.subject.eventSeriesId;
1196
- const run = input.scopedRuns.find((candidate) => candidate.eventSeriesId === eventSeriesId);
1197
- if (!run) {
1198
- input.reportError("This waitlist claim is for a different run.");
1199
- input.goToStep("error");
1200
- return;
1201
- }
1202
- input.chooseRun(run);
1203
- input.updateFormData((current) => ({
1204
- ...current,
1205
- email: claim.prefill.email,
1206
- name: claim.prefill.name,
1207
- phone: claim.prefill.phone ?? "",
1208
- notes: claim.prefill.notes ?? ""
1209
- }));
1210
- if (input.step === "select-run") input.goToStep("enter-details");
1211
- }, [
1212
- input.chooseRun,
1213
- input.goToStep,
1214
- input.reportError,
1215
- input.scopedRuns,
1216
- input.step,
1217
- input.updateFormData,
1218
- input.waitlistClaim.claim
1219
- ]);
1220
- useEffect(() => {
1221
- if (input.waitlistClaim.requiresPortalLogin || !input.waitlistClaim.error) return;
1222
- input.reportError(input.waitlistClaim.error);
1223
- input.goToStep("error");
1224
- }, [
1225
- input.goToStep,
1226
- input.reportError,
1227
- input.waitlistClaim.error,
1228
- input.waitlistClaim.requiresPortalLogin
1229
- ]);
1230
- }
1231
- //#endregion
1232
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/useWholeSeriesRegistrationWizard.ts
1233
- function useWholeSeriesRegistrationWizard(props, options = {}) {
1234
- return useWholeSeriesRegistrationWizardWithDeps(wholeSeriesRegistrationWizardDeps, props, options);
1235
- }
1236
- const wholeSeriesRegistrationWizardDeps = { readLocation: () => ({
1237
- search: window.location.search,
1238
- hash: window.location.hash
1239
- }) };
1240
- function useWholeSeriesRegistrationWizardWithDeps(deps, props, options = {}) {
1241
- const api = useBlockApi();
1242
- const [location] = useState(deps.readLocation);
1243
- const selection = useWholeSeriesRegistrationSelection(props, location);
1244
- const portal = useWholeSeriesRegistrationPortal(api);
1245
- const waitlistClaim = useWaitlistClaimForToken(new URLSearchParams(location.search).get("waitlist_claim")?.trim() || null);
1246
- const [bookingMode, setBookingMode] = useState(null);
1247
- const [altchaSolution, setAltchaSolution] = useState(null);
1248
- const eligibility = useWholeSeriesEligibility({
1249
- api,
1250
- selectedRun: selection.selectedRun,
1251
- hasPaidSelection: selection.selectedRunPricing?.hasPaidSelection ?? false,
1252
- portalAuthState: portal.portalAuthState,
1253
- waitlistClaimToken: waitlistClaim.token
1254
- });
1255
- const discountUi = useDiscountCodeUi({
1256
- api,
1257
- discountContext: useMemo(() => selection.selectedRun && selection.selectedRunPricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
1258
- type: "whole_series",
1259
- eventSeriesId: selection.selectedRun.eventSeriesId
1260
- } : null, [
1261
- eligibility.paymentChoice,
1262
- selection.selectedRun,
1263
- selection.selectedRunPricing?.selectedRequiresPayment
1264
- ]),
1265
- subtotalCents: selection.selectedRunPricing?.selectedPriceAmount ?? void 0
1266
- });
1267
- const actions = useWholeSeriesRegistrationActions({
1268
- api,
1269
- selectedRun: selection.selectedRun,
1270
- pricing: selection.selectedRunPricing,
1271
- formData: portal.formData,
1272
- portalAuthState: portal.portalAuthState,
1273
- eligibility: eligibility.runEligibility,
1274
- eligibleMemberships: eligibility.eligibleMemberships,
1275
- paymentChoice: eligibility.paymentChoice,
1276
- selectedMembershipId: eligibility.selectedMembershipId,
1277
- claimToken: waitlistClaim.token,
1278
- hasClaim: waitlistClaim.claim !== null,
1279
- altchaSolution,
1280
- discountCode: discountUi.discountCode,
1281
- options
1282
- }, selection.goToStep);
1283
- useWholeSeriesRegistrationEffects({
1284
- api,
1285
- actions,
1286
- portal,
1287
- selection,
1288
- waitlistClaim,
1289
- anchorId: options.anchorId ?? "event-registration",
1290
- location
1291
- });
1292
- return buildWholeSeriesRegistrationWizardResult({
1293
- api,
1294
- selection,
1295
- portal,
1296
- eligibility,
1297
- actions,
1298
- discountUi,
1299
- waitlistClaim,
1300
- view: deriveWholeSeriesRegistrationViewState({
1301
- scopedRuns: selection.scopedRuns,
1302
- selectedRun: selection.selectedRun,
1303
- pricing: selection.selectedRunPricing,
1304
- portalAuthState: portal.portalAuthState,
1305
- eligibleMembershipCount: eligibility.eligibleMemberships.length,
1306
- bookingMode,
1307
- step: selection.step,
1308
- waitlistRequiresPortalLogin: waitlistClaim.requiresPortalLogin
1309
- }),
1310
- bookingMode,
1311
- setBookingMode,
1312
- altchaSolution,
1313
- setAltchaSolution,
1314
- anchorId: options.anchorId ?? "event-registration"
1315
- });
1316
- }
1317
- function useWholeSeriesRegistrationEffects(input) {
1318
- useWholeSeriesPaymentVerification(input.api, {
1319
- setStep: input.selection.goToStep,
1320
- setErrorMessage: input.actions.reportError,
1321
- setEnrollmentResult: input.actions.recordEnrollmentResult
1322
- }, input.anchorId, input.location);
1323
- useWholeSeriesWaitlistSelection({
1324
- waitlistClaim: input.waitlistClaim,
1325
- scopedRuns: input.selection.scopedRuns,
1326
- step: input.selection.step,
1327
- goToStep: input.selection.goToStep,
1328
- chooseRun: input.selection.chooseRun,
1329
- updateFormData: input.portal.updateFormData,
1330
- reportError: input.actions.reportError
1331
- });
1332
- }
1333
- function buildWholeSeriesRegistrationWizardResult(parts) {
1334
- const handleBookingModeChange = (mode) => {
1335
- parts.setBookingMode(mode);
1336
- parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
1337
- };
1338
- return {
1339
- api: parts.api,
1340
- ...parts.selection,
1341
- ...parts.portal,
1342
- ...parts.eligibility,
1343
- ...parts.actions,
1344
- waitlistClaim: parts.waitlistClaim,
1345
- bookingMode: parts.bookingMode,
1346
- altchaSolution: parts.altchaSolution,
1347
- setAltchaSolution: parts.setAltchaSolution,
1348
- showSpamProtection: isSpamProtectionEnabled(),
1349
- discountUiOpen: parts.discountUi.discountUiOpen,
1350
- setDiscountUiOpen: parts.discountUi.setDiscountUiOpen,
1351
- discountCode: parts.discountUi.discountCode,
1352
- setDiscountCode: parts.discountUi.setDiscountCode,
1353
- discountsAvailable: parts.discountUi.discountsAvailable,
1354
- manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
1355
- discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
1356
- ...parts.view,
1357
- handleRunSelect: (run) => {
1358
- parts.selection.chooseRun(run);
1359
- parts.selection.goToStep("enter-details");
1360
- },
1361
- handleRetry: () => {
1362
- parts.selection.goToStep(parts.selection.scopedRuns.length === 1 ? "enter-details" : "select-run");
1363
- parts.actions.reportError("");
1364
- },
1365
- handleBookingModeChange,
1366
- handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(parts.anchorId) : void 0,
1367
- selectedRunPricingPayload: buildWholeSeriesPricingOptionPayload(parts.selection.selectedRunPricing)
1368
- };
1369
- }
1370
- //#endregion
1371
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/MembershipHero.tsx
1372
- /**
1373
- * Membership Hero for run registration.
1374
- * Thin wrapper around the shared MembershipHero with the canonical Event class prefix.
1375
- */
1376
- function MembershipHero(props) {
1377
- return /* @__PURE__ */ jsx(MembershipHero$1, {
1378
- ...props,
1379
- classPrefix: "er-whole-series"
1380
- });
1381
- }
1382
- //#endregion
1383
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/BookingModeStep.tsx
1384
- function BookingModeStep({ bookingMode, onBookingModeChange, eligibleMemberships, selectedMembershipId, onMembershipSelect, priceCents, currency, showEnrollForOtherLink = false, onEnrollForOther }) {
1385
- const hasSingleMembership = eligibleMemberships.length === 1;
1386
- const hasMultipleMemberships = eligibleMemberships.length > 1;
1387
- const showMembershipHero = hasSingleMembership && bookingMode === "membership" && eligibleMemberships[0];
1388
- const singleMembership = eligibleMemberships[0];
1389
- return /* @__PURE__ */ jsxs("div", {
1390
- className: "er-whole-series-booking-mode",
1391
- children: [
1392
- /* @__PURE__ */ jsx("h2", {
1393
- className: "er-whole-series-booking-mode__title",
1394
- children: "How would you like to enroll?"
1395
- }),
1396
- /* @__PURE__ */ jsx("p", {
1397
- className: "er-whole-series-booking-mode__subtitle",
1398
- children: "Choose how you want to book"
1399
- }),
1400
- showMembershipHero && singleMembership && /* @__PURE__ */ jsx(MembershipHero, { membershipName: singleMembership.membershipName }),
1401
- /* @__PURE__ */ jsxs("div", {
1402
- className: "er-whole-series-payment-tiles",
1403
- children: [
1404
- hasSingleMembership && singleMembership && /* @__PURE__ */ jsx(MembershipOption, {
1405
- membership: singleMembership,
1406
- selected: bookingMode === "membership",
1407
- description: "Use your membership to book for free",
1408
- onSelect: () => {
1409
- onBookingModeChange("membership");
1410
- onMembershipSelect(singleMembership.customerMembershipId);
1411
- }
1412
- }),
1413
- hasMultipleMemberships && eligibleMemberships.map((membership) => /* @__PURE__ */ jsx(MembershipOption, {
1414
- membership,
1415
- selected: bookingMode === "membership" && selectedMembershipId === membership.customerMembershipId,
1416
- description: "Use this membership to book for free",
1417
- onSelect: () => {
1418
- onBookingModeChange("membership");
1419
- onMembershipSelect(membership.customerMembershipId);
1420
- }
1421
- }, membership.customerMembershipId)),
1422
- /* @__PURE__ */ jsx(BookingOption, {
1423
- selected: bookingMode === "card",
1424
- name: "Pay by Card",
1425
- price: priceCents === null ? null : formatPrice(priceCents, currency),
1426
- description: "Pay with credit or debit card",
1427
- onSelect: () => {
1428
- onBookingModeChange("card");
1429
- onMembershipSelect(null);
1430
- }
1431
- })
1432
- ]
1433
- }),
1434
- showEnrollForOtherLink && onEnrollForOther && /* @__PURE__ */ jsx("div", {
1435
- className: "er-whole-series-booking-mode__link",
1436
- children: /* @__PURE__ */ jsx("a", {
1437
- onClick: onEnrollForOther,
1438
- role: "button",
1439
- tabIndex: 0,
1440
- children: "Enrolling for someone else?"
1441
- })
1442
- })
1443
- ]
1444
- });
1445
- }
1446
- function MembershipOption({ membership, selected, description, onSelect }) {
1447
- return /* @__PURE__ */ jsx(BookingOption, {
1448
- selected,
1449
- name: membership.membershipName,
1450
- price: "Free",
1451
- description,
1452
- onSelect
1453
- });
1454
- }
1455
- function BookingOption({ selected, name, price, description, onSelect }) {
1456
- return /* @__PURE__ */ jsxs("button", {
1457
- type: "button",
1458
- className: `er-whole-series-payment-tile${selected ? " er-whole-series-payment-tile--selected" : ""}`,
1459
- onClick: onSelect,
1460
- "aria-pressed": selected,
1461
- children: [
1462
- /* @__PURE__ */ jsx("div", {
1463
- className: "er-whole-series-payment-tile__check",
1464
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
1465
- }),
1466
- /* @__PURE__ */ jsxs("div", {
1467
- className: "er-whole-series-payment-tile__header",
1468
- children: [/* @__PURE__ */ jsx("h3", {
1469
- className: "er-whole-series-payment-tile__name",
1470
- children: name
1471
- }), price ? /* @__PURE__ */ jsx("span", {
1472
- className: "er-whole-series-payment-tile__price",
1473
- children: price
1474
- }) : null]
1475
- }),
1476
- /* @__PURE__ */ jsx("p", {
1477
- className: "er-whole-series-payment-tile__description",
1478
- children: description
1479
- })
1480
- ]
1481
- });
1482
- }
1483
- //#endregion
1484
- //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
1485
- /**
1486
- * Displays the logged-in user's email with an optional logout link.
1487
- *
1488
- * Used in registration forms when the email field is locked due to portal authentication.
1489
- * Shows: "Logged in as {email} — Not you? Log out"
1490
- */
1491
- function LoggedInAsUser({ email, onLogout, classPrefix }) {
1492
- return /* @__PURE__ */ jsxs("p", {
1493
- className: `${classPrefix}-logged-in-hint`,
1494
- children: [
1495
- "Logged in as ",
1496
- email,
1497
- onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [" — ", /* @__PURE__ */ jsx("button", {
1498
- type: "button",
1499
- className: `${classPrefix}-link`,
1500
- onClick: onLogout,
1501
- children: "Not you? Log out"
1502
- })] })
1503
- ]
1504
- });
1505
- }
1506
- //#endregion
1507
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/components.tsx
1508
- function TeamMemberInlineList({ teamMembers }) {
1509
- return /* @__PURE__ */ jsx(Fragment, { children: teamMembers.map((teamMember, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 ? ", " : "", teamMember.profilePath ? /* @__PURE__ */ jsx("a", {
1510
- href: teamMember.profilePath,
1511
- children: teamMember.name
1512
- }) : teamMember.name] }, teamMember.id)) });
1513
- }
1514
- function RunCard({ run, isSelected, onSelect, showSessions, showPrice, showCapacity, showVenue }) {
1515
- const pricing = resolveWholeSeriesPricingState(run);
1516
- const view = buildRunCardView(run, pricing);
1517
- return /* @__PURE__ */ jsxs("div", {
1518
- className: `er-whole-series-run-card ${isSelected ? "er-whole-series-run-card--selected" : ""}`,
1519
- onClick: onSelect,
1520
- role: "button",
1521
- tabIndex: 0,
1522
- "aria-pressed": isSelected,
1523
- onKeyDown: (e) => {
1524
- if (e.key === "Enter" || e.key === " ") {
1525
- e.preventDefault();
1526
- onSelect();
1527
- }
1528
- },
1529
- children: [
1530
- /* @__PURE__ */ jsx("h3", {
1531
- className: "er-whole-series-run-card__title",
1532
- children: run.title
1533
- }),
1534
- view.enrollmentClosed && /* @__PURE__ */ jsx("p", {
1535
- className: "er-whole-series-run-card__status",
1536
- children: "Registration closed"
1537
- }),
1538
- showSessions && run.sessionsCount > 0 && /* @__PURE__ */ jsxs("p", {
1539
- className: "er-whole-series-run-card__sessions",
1540
- children: [
1541
- run.sessionsCount,
1542
- " session",
1543
- run.sessionsCount !== 1 ? "s" : ""
1544
- ]
1545
- }),
1546
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsx("p", {
1547
- className: "er-whole-series-run-card__price",
1548
- children: view.priceLabel
1549
- }),
1550
- showCapacity && run.availableSpots !== null && /* @__PURE__ */ jsx("p", {
1551
- className: "er-whole-series-run-card__capacity",
1552
- children: view.capacityLabel
1553
- }),
1554
- showVenue && run.venue && /* @__PURE__ */ jsx("p", {
1555
- className: "er-whole-series-run-card__venue",
1556
- children: run.venue.name
1557
- }),
1558
- view.teamMemberNames.length > 0 && /* @__PURE__ */ jsxs("p", {
1559
- className: "er-whole-series-run-card__venue",
1560
- children: ["Team: ", view.teamMemberNames.join(", ")]
1561
- })
1562
- ]
1563
- });
1564
- }
1565
- function buildRunCardView(run, pricing) {
1566
- const availableSpots = run.availableSpots ?? 0;
1567
- return {
1568
- enrollmentClosed: run.enrollmentOpen === false,
1569
- priceLabel: formatWholeSeriesPriceDisplay(pricing.display),
1570
- capacityLabel: availableSpots > 0 ? `${availableSpots} spot${availableSpots === 1 ? "" : "s"} available` : "Waitlist only",
1571
- teamMemberNames: (run.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean)
1572
- };
1573
- }
1574
- function RunSummary({ run, pricing, showSessions, showVenue, showPrice, showMembershipNote }) {
1575
- const teamMembers = run.teamMembers ?? [];
1576
- const priceLabel = pricing.selectedOption ? `${pricing.selectedOption.name} - ${formatWholeSeriesPriceAmount(pricing.selectedOption.priceAmount, pricing.currency)}` : formatWholeSeriesPriceDisplay(pricing.display);
1577
- return /* @__PURE__ */ jsxs("div", {
1578
- className: "er-whole-series-summary",
1579
- children: [
1580
- /* @__PURE__ */ jsx("h3", {
1581
- className: "er-whole-series-summary__title",
1582
- children: run.title
1583
- }),
1584
- showSessions && run.sessions.length > 0 && /* @__PURE__ */ jsxs("div", {
1585
- className: "er-whole-series-summary__sessions",
1586
- children: [/* @__PURE__ */ jsx("h4", {
1587
- className: "er-whole-series-summary__sessions-title",
1588
- children: "Sessions"
1589
- }), /* @__PURE__ */ jsx("ul", {
1590
- className: "er-whole-series-summary__sessions-list",
1591
- children: run.sessions.map((session) => /* @__PURE__ */ jsxs("li", {
1592
- className: "er-whole-series-summary__session",
1593
- children: [
1594
- formatDate(session.startsAt, { timeZone: session.timeZone }),
1595
- " ",
1596
- "at",
1597
- " ",
1598
- formatTime(session.startsAt, { timeZone: session.timeZone })
1599
- ]
1600
- }, session.id))
1601
- })]
1602
- }),
1603
- showVenue && run.venue && /* @__PURE__ */ jsxs("p", {
1604
- className: "er-whole-series-summary__venue",
1605
- children: [
1606
- /* @__PURE__ */ jsx("strong", { children: "Venue:" }),
1607
- " ",
1608
- run.venue.name,
1609
- run.venue.address && ` - ${run.venue.address}`
1610
- ]
1611
- }),
1612
- teamMembers.length > 0 && /* @__PURE__ */ jsxs("div", {
1613
- className: "er-whole-series-summary__venue",
1614
- children: [
1615
- /* @__PURE__ */ jsx("strong", { children: "Team:" }),
1616
- " ",
1617
- /* @__PURE__ */ jsx(TeamMemberInlineList, { teamMembers })
1618
- ]
1619
- }),
1620
- showPrice && pricing.display.kind !== "unavailable" && /* @__PURE__ */ jsxs("p", {
1621
- className: "er-whole-series-summary__price",
1622
- children: [
1623
- /* @__PURE__ */ jsx("strong", { children: pricing.selectableOptions.length > 0 ? "Pricing:" : "Price:" }),
1624
- " ",
1625
- priceLabel
1626
- ]
1627
- }),
1628
- showMembershipNote && /* @__PURE__ */ jsx("p", {
1629
- className: "er-whole-series-summary__membership",
1630
- children: "✓ Your membership can be used to book for free"
1631
- })
1632
- ]
1633
- });
1634
- }
1635
- function WholeSeriesPricingSelector({ pricing, selectedPricingOptionId, onSelect }) {
1636
- if (pricing.selectableOptions.length <= 1) return null;
1637
- return /* @__PURE__ */ jsxs("fieldset", {
1638
- className: "er-whole-series-form__field",
1639
- children: [/* @__PURE__ */ jsx("legend", {
1640
- id: "er-whole-series-pricing-options-label",
1641
- className: "er-whole-series-form__label",
1642
- children: "Pricing option"
1643
- }), /* @__PURE__ */ jsx("div", {
1644
- className: "er-whole-series-payment-tiles",
1645
- role: "radiogroup",
1646
- "aria-labelledby": "er-whole-series-pricing-options-label",
1647
- children: pricing.selectableOptions.map((option) => {
1648
- const isSelected = selectedPricingOptionId === option.id;
1649
- const priceLabel = formatWholeSeriesPriceAmount(option.priceAmount, pricing.currency);
1650
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("button", {
1651
- type: "button",
1652
- role: "radio",
1653
- "aria-checked": isSelected,
1654
- className: `er-whole-series-payment-tile${isSelected ? " er-whole-series-payment-tile--selected" : ""}`,
1655
- onClick: () => onSelect(option.id),
1656
- children: [/* @__PURE__ */ jsxs("div", {
1657
- className: "er-whole-series-payment-tile__header",
1658
- children: [/* @__PURE__ */ jsx("h3", {
1659
- className: "er-whole-series-payment-tile__name",
1660
- children: option.name
1661
- }), /* @__PURE__ */ jsx("span", {
1662
- className: "er-whole-series-payment-tile__price",
1663
- children: priceLabel
1664
- })]
1665
- }), option.description ? /* @__PURE__ */ jsx("p", {
1666
- className: "er-whole-series-payment-tile__description",
1667
- children: option.description
1668
- }) : null]
1669
- }) }, option.id);
1670
- })
1671
- })]
1672
- });
1673
- }
1674
- function WholeSeriesSlidingScaleInput({ pricing, value, onChange }) {
1675
- const slidingScale = pricing.slidingScale;
1676
- if (!slidingScale) return null;
1677
- const minLabel = formatWholeSeriesPriceAmount(slidingScale.minAmount, pricing.currency);
1678
- const maxLabel = formatWholeSeriesPriceAmount(slidingScale.maxAmount, pricing.currency);
1679
- const suggestedLabel = slidingScale.suggestedAmount !== null ? formatWholeSeriesPriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
1680
- return /* @__PURE__ */ jsxs("div", {
1681
- className: "er-whole-series-form__field",
1682
- children: [
1683
- /* @__PURE__ */ jsx("label", {
1684
- htmlFor: "er-whole-series-sliding-amount",
1685
- className: "er-whole-series-form__label",
1686
- children: "Amount"
1687
- }),
1688
- /* @__PURE__ */ jsx("input", {
1689
- id: "er-whole-series-sliding-amount",
1690
- type: "number",
1691
- min: slidingScale.minAmount / 100,
1692
- max: slidingScale.maxAmount / 100,
1693
- step: "0.01",
1694
- inputMode: "decimal",
1695
- className: "er-whole-series-form__input",
1696
- value,
1697
- onChange: (event) => onChange(event.target.value)
1698
- }),
1699
- /* @__PURE__ */ jsxs("p", {
1700
- className: "er-whole-series-text er-whole-series-text--muted",
1701
- children: [
1702
- "Choose between ",
1703
- minLabel,
1704
- " and ",
1705
- maxLabel,
1706
- suggestedLabel ? `; suggested ${suggestedLabel}` : "",
1707
- "."
1708
- ]
1709
- })
1710
- ]
1711
- });
1712
- }
1713
- function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
1714
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EnrollmentIdentityFields, {
1715
- formData,
1716
- errors,
1717
- onChange,
1718
- isEmailLocked,
1719
- isLoading,
1720
- onLogout
1721
- }), /* @__PURE__ */ jsx(EnrollmentOptionalFields, {
1722
- formData,
1723
- onChange,
1724
- isLoading
1725
- })] });
1726
- }
1727
- function EnrollmentIdentityFields({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
1728
- const nameErrorId = "er-whole-series-name-error";
1729
- const emailErrorId = "er-whole-series-email-error";
1730
- const nameValidationProps = getFieldValidationControlProps({
1731
- message: errors.name,
1732
- messageId: nameErrorId
1733
- });
1734
- const emailValidationProps = getFieldValidationControlProps({
1735
- message: errors.email,
1736
- messageId: emailErrorId
1737
- });
1738
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1739
- className: "er-whole-series-form__field",
1740
- children: [
1741
- /* @__PURE__ */ jsx("label", {
1742
- htmlFor: "er-whole-series-name",
1743
- className: "er-whole-series-form__label",
1744
- children: "Name *"
1745
- }),
1746
- /* @__PURE__ */ jsx("input", {
1747
- id: "er-whole-series-name",
1748
- type: "text",
1749
- className: `er-whole-series-form__input ${errors.name ? "er-whole-series-form__input--error" : ""}`,
1750
- value: formData.name,
1751
- onChange: (e) => onChange({
1752
- ...formData,
1753
- name: e.target.value
1754
- }),
1755
- disabled: isLoading,
1756
- ...nameValidationProps
1757
- }),
1758
- errors.name && /* @__PURE__ */ jsx(FieldValidationMessage, {
1759
- id: nameErrorId,
1760
- className: "er-whole-series-form__error",
1761
- children: errors.name
1762
- })
1763
- ]
1764
- }), /* @__PURE__ */ jsxs("div", {
1765
- className: "er-whole-series-form__field",
1766
- children: [
1767
- /* @__PURE__ */ jsx("label", {
1768
- htmlFor: "er-whole-series-email",
1769
- className: "er-whole-series-form__label",
1770
- children: "Email *"
1771
- }),
1772
- /* @__PURE__ */ jsx("input", {
1773
- id: "er-whole-series-email",
1774
- type: "email",
1775
- className: `er-whole-series-form__input ${errors.email ? "er-whole-series-form__input--error" : ""}`,
1776
- value: formData.email,
1777
- onChange: (e) => onChange({
1778
- ...formData,
1779
- email: e.target.value
1780
- }),
1781
- disabled: isEmailLocked || isLoading,
1782
- ...emailValidationProps
1783
- }),
1784
- errors.email && /* @__PURE__ */ jsx(FieldValidationMessage, {
1785
- id: emailErrorId,
1786
- className: "er-whole-series-form__error",
1787
- children: errors.email
1788
- }),
1789
- isEmailLocked && /* @__PURE__ */ jsx(LoggedInAsUser, {
1790
- email: formData.email,
1791
- onLogout,
1792
- classPrefix: "er-whole-series"
1793
- })
1794
- ]
1795
- })] });
1796
- }
1797
- function EnrollmentOptionalFields({ formData, onChange, isLoading }) {
1798
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
1799
- className: "er-whole-series-form__field",
1800
- children: [/* @__PURE__ */ jsx("label", {
1801
- htmlFor: "er-whole-series-phone",
1802
- className: "er-whole-series-form__label",
1803
- children: "Phone"
1804
- }), /* @__PURE__ */ jsx("input", {
1805
- id: "er-whole-series-phone",
1806
- type: "tel",
1807
- className: "er-whole-series-form__input",
1808
- value: formData.phone,
1809
- onChange: (e) => onChange({
1810
- ...formData,
1811
- phone: e.target.value
1812
- }),
1813
- disabled: isLoading
1814
- })]
1815
- }), /* @__PURE__ */ jsxs("div", {
1816
- className: "er-whole-series-form__field",
1817
- children: [/* @__PURE__ */ jsx("label", {
1818
- htmlFor: "er-whole-series-notes",
1819
- className: "er-whole-series-form__label",
1820
- children: "Notes"
1821
- }), /* @__PURE__ */ jsx("textarea", {
1822
- id: "er-whole-series-notes",
1823
- className: "er-whole-series-form__textarea",
1824
- value: formData.notes,
1825
- onChange: (e) => onChange({
1826
- ...formData,
1827
- notes: e.target.value
1828
- }),
1829
- rows: 3,
1830
- disabled: isLoading
1831
- })]
1832
- })] });
1833
- }
1834
- //#endregion
1835
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationActiveSteps.tsx
1836
- function WholeSeriesRegistrationActiveStep({ wizard, display }) {
1837
- switch (wizard.step) {
1838
- case "select-run": return /* @__PURE__ */ jsx(RunSelectionStep, {
1839
- wizard,
1840
- display
1841
- });
1842
- case "enter-details": return /* @__PURE__ */ jsx(RegistrationDetailsStep, {
1843
- wizard,
1844
- display
1845
- });
1846
- case "booking-mode": return /* @__PURE__ */ jsx(RegistrationBookingModeStep, {
1847
- wizard,
1848
- display
1849
- });
1850
- case "select-payment": return /* @__PURE__ */ jsx(RegistrationPaymentStep, {
1851
- wizard,
1852
- display
1853
- });
1854
- case "error":
1855
- case "payment-failed":
1856
- case "redirecting":
1857
- case "submitting":
1858
- case "success":
1859
- case "verifying-payment":
1860
- case "verifying-timeout":
1861
- case "waitlist": return null;
1862
- }
1863
- }
1864
- function RunSelectionStep({ wizard, display }) {
1865
- return /* @__PURE__ */ jsx("div", {
1866
- className: "er-whole-series-run-list",
1867
- children: wizard.scopedRuns.map((run) => /* @__PURE__ */ jsx(RunCard, {
1868
- run,
1869
- isSelected: wizard.selectedRun?.eventSeriesId === run.eventSeriesId,
1870
- onSelect: () => wizard.handleRunSelect(run),
1871
- showSessions: display.showSessions,
1872
- showPrice: display.showPrice,
1873
- showCapacity: display.showCapacity,
1874
- showVenue: display.showVenue
1875
- }, run.eventSeriesId))
1876
- });
1877
- }
1878
- function RegistrationDetailsStep({ wizard, display }) {
1879
- const selection = selectedRunWithPricing(wizard);
1880
- if (!selection) return null;
1881
- return /* @__PURE__ */ jsxs("div", {
1882
- className: "er-whole-series-details",
1883
- children: [/* @__PURE__ */ jsx(RunSummary, {
1884
- run: selection.run,
1885
- pricing: selection.pricing,
1886
- showSessions: display.showSessions,
1887
- showVenue: display.showVenue,
1888
- showPrice: display.showPrice,
1889
- showMembershipNote: selection.run.acceptsMemberships && wizard.portalAuthState === "authenticated"
1890
- }), selection.run.enrollmentOpen === false ? /* @__PURE__ */ jsx(ClosedRunNotice, { wizard }) : /* @__PURE__ */ jsx(RegistrationDetailsForm, {
1891
- wizard,
1892
- display
1893
- })]
1894
- });
1895
- }
1896
- function ClosedRunNotice({ wizard }) {
1897
- return /* @__PURE__ */ jsxs("div", {
1898
- className: "er-whole-series-form",
1899
- children: [/* @__PURE__ */ jsx(BackToRunsButton, { wizard }), /* @__PURE__ */ jsx("p", {
1900
- className: "er-whole-series-text er-whole-series-text--muted",
1901
- children: "Registration closed."
1902
- })]
1903
- });
1904
- }
1905
- function RegistrationDetailsForm({ wizard, display }) {
1906
- const blockers = deriveDetailsBlockers(wizard);
1907
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("form", {
1908
- className: "er-whole-series-form",
1909
- onSubmit: (event) => {
1910
- event.preventDefault();
1911
- wizard.handleSubmit();
1912
- },
1913
- children: [
1914
- /* @__PURE__ */ jsx(EnrollmentForm, {
1915
- formData: wizard.formData,
1916
- errors: wizard.errors,
1917
- onChange: wizard.updateFormData,
1918
- isEmailLocked: wizard.portalAuthState === "authenticated" || wizard.waitlistClaim.claim !== null,
1919
- isLoading: wizard.portalAuthState === "checking" || wizard.waitlistClaim.isLoading,
1920
- onLogout: wizard.handleLogout
1921
- }),
1922
- /* @__PURE__ */ jsx(PricingFields, { wizard }),
1923
- wizard.showSpamProtection ? /* @__PURE__ */ jsx("div", {
1924
- className: "er-whole-series-altcha",
1925
- children: /* @__PURE__ */ jsx(AltchaWidget, {
1926
- challengeUrl: getChallengeUrl(),
1927
- onSolutionChange: wizard.setAltchaSolution
1928
- })
1929
- }) : null,
1930
- /* @__PURE__ */ jsx(DiscountFields, { wizard }),
1931
- /* @__PURE__ */ jsxs("div", {
1932
- className: "er-whole-series-actions",
1933
- children: [/* @__PURE__ */ jsx(BackToRunsButton, {
1934
- wizard,
1935
- compact: true
1936
- }), /* @__PURE__ */ jsx("button", {
1937
- type: "submit",
1938
- className: buttonClass(display.buttonVariant),
1939
- disabled: blockers.disabled,
1940
- children: detailsSubmitLabel(wizard, display.buttonText, blockers.soldOut)
1941
- })]
1942
- })
1943
- ]
1944
- }), /* @__PURE__ */ jsx(DetailsBlockerMessages, {
1945
- wizard,
1946
- blockers
1947
- })] });
1948
- }
1949
- function PricingFields({ wizard }) {
1950
- if (!wizard.selectedRunPricing) return null;
1951
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(WholeSeriesPricingSelector, {
1952
- pricing: wizard.selectedRunPricing,
1953
- selectedPricingOptionId: wizard.selectedPricingOptionId,
1954
- onSelect: wizard.choosePricingOption
1955
- }), /* @__PURE__ */ jsx(WholeSeriesSlidingScaleInput, {
1956
- pricing: wizard.selectedRunPricing,
1957
- value: wizard.selectedSlidingAmountInput,
1958
- onChange: wizard.changeSlidingAmount
1959
- })] });
1960
- }
1961
- function RegistrationBookingModeStep({ wizard, display }) {
1962
- const selection = selectedRunWithPricing(wizard);
1963
- if (!selection) return null;
1964
- const membershipMissing = wizard.bookingMode === "membership" && !wizard.selectedMembershipId;
1965
- return /* @__PURE__ */ jsxs("div", {
1966
- className: "er-whole-series-details",
1967
- children: [
1968
- /* @__PURE__ */ jsx(RunSummary, {
1969
- run: selection.run,
1970
- pricing: selection.pricing,
1971
- showSessions: display.showSessions,
1972
- showVenue: display.showVenue,
1973
- showPrice: display.showPrice,
1974
- showMembershipNote: false
1975
- }),
1976
- /* @__PURE__ */ jsx(BookingModeStep, {
1977
- bookingMode: wizard.bookingMode,
1978
- onBookingModeChange: wizard.handleBookingModeChange,
1979
- eligibleMemberships: wizard.eligibleMemberships,
1980
- selectedMembershipId: wizard.selectedMembershipId,
1981
- onMembershipSelect: wizard.chooseMembership,
1982
- priceCents: wizard.selectedRunPricing?.selectedPriceAmount ?? null,
1983
- currency: selection.run.currency ?? "GBP"
1984
- }),
1985
- /* @__PURE__ */ jsxs("div", {
1986
- className: "er-whole-series-actions",
1987
- children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
1988
- type: "button",
1989
- className: buttonClass(display.buttonVariant),
1990
- onClick: wizard.handlePaymentContinue,
1991
- disabled: !wizard.bookingMode || membershipMissing,
1992
- children: wizard.bookingMode === "membership" ? "Book run" : "Continue to payment"
1993
- })]
1994
- })
1995
- ]
1996
- });
1997
- }
1998
- function RegistrationPaymentStep({ wizard, display }) {
1999
- const selection = selectedRunWithPricing(wizard);
2000
- if (!selection) return null;
2001
- return /* @__PURE__ */ jsxs("div", {
2002
- className: "er-whole-series-details",
2003
- children: [/* @__PURE__ */ jsx(RunSummary, {
2004
- run: selection.run,
2005
- pricing: selection.pricing,
2006
- showSessions: display.showSessions,
2007
- showVenue: display.showVenue,
2008
- showPrice: display.showPrice,
2009
- showMembershipNote: false
2010
- }), /* @__PURE__ */ jsxs("div", {
2011
- className: "er-whole-series-form",
2012
- children: [
2013
- /* @__PURE__ */ jsx(PaymentChoices, { wizard }),
2014
- /* @__PURE__ */ jsx(DiscountFields, { wizard }),
2015
- /* @__PURE__ */ jsxs("div", {
2016
- className: "er-whole-series-actions",
2017
- children: [/* @__PURE__ */ jsx(BackToDetailsButton, { wizard }), /* @__PURE__ */ jsx("button", {
2018
- type: "button",
2019
- className: buttonClass(display.buttonVariant),
2020
- onClick: wizard.handlePaymentContinue,
2021
- children: "Continue"
2022
- })]
2023
- })
2024
- ]
2025
- })]
2026
- });
2027
- }
2028
- function PaymentChoices({ wizard }) {
2029
- return /* @__PURE__ */ jsxs("fieldset", {
2030
- className: "er-whole-series-form__field",
2031
- children: [/* @__PURE__ */ jsx("legend", {
2032
- className: "er-whole-series-form__label",
2033
- children: "Choose how to book"
2034
- }), /* @__PURE__ */ jsxs("div", {
2035
- className: "er-whole-series-payment__options",
2036
- children: [
2037
- /* @__PURE__ */ jsx(PaymentChoice, {
2038
- checked: wizard.paymentChoice === "membership",
2039
- label: "Use a membership (free)",
2040
- onChange: () => wizard.choosePaymentChoice("membership")
2041
- }),
2042
- wizard.paymentChoice === "membership" && wizard.eligibleMemberships.length > 1 ? /* @__PURE__ */ jsx(MembershipSelect, { wizard }) : null,
2043
- /* @__PURE__ */ jsx(PaymentChoice, {
2044
- checked: wizard.paymentChoice === "checkout",
2045
- label: "Pay by card",
2046
- onChange: () => wizard.choosePaymentChoice("checkout")
2047
- })
2048
- ]
2049
- })]
2050
- });
2051
- }
2052
- function PaymentChoice({ checked, label, onChange }) {
2053
- return /* @__PURE__ */ jsxs("label", {
2054
- className: "er-whole-series-payment__option",
2055
- children: [/* @__PURE__ */ jsx("input", {
2056
- type: "radio",
2057
- name: "paymentChoice",
2058
- checked,
2059
- onChange
2060
- }), /* @__PURE__ */ jsx("span", { children: label })]
2061
- });
2062
- }
2063
- function MembershipSelect({ wizard }) {
2064
- return /* @__PURE__ */ jsxs("div", {
2065
- className: "er-whole-series-form__field",
2066
- children: [/* @__PURE__ */ jsx("label", {
2067
- htmlFor: "er-whole-series-membership",
2068
- className: "er-whole-series-form__label",
2069
- children: "Membership"
2070
- }), /* @__PURE__ */ jsxs("select", {
2071
- id: "er-whole-series-membership",
2072
- className: "er-whole-series-form__input",
2073
- value: wizard.selectedMembershipId ?? "",
2074
- onChange: (event) => wizard.chooseMembership(event.target.value || null),
2075
- children: [/* @__PURE__ */ jsx("option", {
2076
- value: "",
2077
- disabled: true,
2078
- children: "Select a membership…"
2079
- }), wizard.eligibleMemberships.map((membership) => /* @__PURE__ */ jsx("option", {
2080
- value: membership.customerMembershipId,
2081
- children: membership.membershipName
2082
- }, membership.customerMembershipId))]
2083
- })]
2084
- });
2085
- }
2086
- function DiscountFields({ wizard }) {
2087
- if (!canShowDiscount(wizard)) return null;
2088
- return /* @__PURE__ */ jsx(DiscountCodeDisclosure, {
2089
- surface: "whole-series-registration",
2090
- isOpen: wizard.discountUiOpen,
2091
- code: wizard.discountCode,
2092
- onOpen: () => wizard.setDiscountUiOpen(true),
2093
- onChange: wizard.setDiscountCode,
2094
- onRemove: () => {
2095
- wizard.setDiscountCode("");
2096
- wizard.setDiscountUiOpen(false);
2097
- },
2098
- id: "er-whole-series-discount-code"
2099
- });
2100
- }
2101
- function deriveDetailsBlockers(wizard) {
2102
- const soldOut = wizard.waitlistClaim.claim === null && wizard.runEligibility?.isFull === true && wizard.runEligibility.canJoinWaitlist !== true;
2103
- const missingPricing = wizard.selectedRunPricing?.requiresSelection === true && !wizard.selectedRunPricing.selectedOption && !wizard.selectedRunPricing.slidingScale;
2104
- const slidingScaleMessage = slidingScaleBlocker(wizard.selectedRunPricing);
2105
- const pricingUnavailable = wizard.selectedRunPricing?.display.kind === "unavailable";
2106
- return {
2107
- disabled: soldOut || wizard.eligibilityLoading || missingPricing || slidingScaleMessage !== null || pricingUnavailable,
2108
- soldOut,
2109
- missingPricing,
2110
- slidingScaleMessage,
2111
- pricingUnavailable
2112
- };
2113
- }
2114
- function DetailsBlockerMessages({ wizard, blockers }) {
2115
- return /* @__PURE__ */ jsxs(Fragment, { children: [[
2116
- blockers.soldOut ? "This run is fully booked and there is no waitlist available right now." : null,
2117
- blockers.missingPricing ? "Choose a pricing option to continue." : null,
2118
- blockers.slidingScaleMessage,
2119
- blockers.pricingUnavailable ? "Pricing is not available for this run right now." : null
2120
- ].filter((message) => message !== null).map((message) => /* @__PURE__ */ jsx("p", {
2121
- className: "er-whole-series-text er-whole-series-text--muted",
2122
- children: message
2123
- }, message)), wizard.eligibilityError ? /* @__PURE__ */ jsx("p", {
2124
- className: "er-whole-series-text er-whole-series-text--error",
2125
- children: wizard.eligibilityError
2126
- }) : null] });
2127
- }
2128
- function BackToRunsButton({ wizard, compact = false }) {
2129
- if (wizard.scopedRuns.length <= 1) return null;
2130
- const button = /* @__PURE__ */ jsx("button", {
2131
- type: "button",
2132
- onClick: () => wizard.goToStep("select-run"),
2133
- className: "er-whole-series-back-btn",
2134
- children: "← Back"
2135
- });
2136
- return compact ? button : /* @__PURE__ */ jsx("div", {
2137
- className: "er-whole-series-actions",
2138
- children: button
2139
- });
2140
- }
2141
- function BackToDetailsButton({ wizard }) {
2142
- return /* @__PURE__ */ jsx("button", {
2143
- type: "button",
2144
- onClick: () => wizard.goToStep("enter-details"),
2145
- className: "er-whole-series-back-btn",
2146
- children: "← Back"
2147
- });
2148
- }
2149
- function selectedRunWithPricing(wizard) {
2150
- return wizard.selectedRun && wizard.selectedRunPricing ? {
2151
- run: wizard.selectedRun,
2152
- pricing: wizard.selectedRunPricing
2153
- } : null;
2154
- }
2155
- function canShowDiscount(wizard) {
2156
- return !wizard.discountsAvailableLoading && wizard.paymentChoice === "checkout" && wizard.discountsAvailable && wizard.manualCodeEntryAllowed;
2157
- }
2158
- function slidingScaleBlocker(pricing) {
2159
- if (!pricing?.slidingScale) return null;
2160
- if (pricing.selectedSlidingAmount === null) return "Choose an amount to continue.";
2161
- return pricing.selectedSlidingAmount < pricing.slidingScale.minAmount || pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount ? "Choose an amount within the sliding scale." : null;
2162
- }
2163
- function detailsSubmitLabel(wizard, buttonText, soldOut) {
2164
- if (wizard.eligibilityLoading) return "Checking availability…";
2165
- if (soldOut) return "Sold out";
2166
- return wizard.runEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
2167
- }
2168
- function buttonClass(variant) {
2169
- return themeButtonClassName({
2170
- variant: variant ?? "primary",
2171
- size: "md"
2172
- });
2173
- }
2174
- //#endregion
2175
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/ErrorStep.tsx
2176
- /**
2177
- * Error terminal state component.
2178
- * Shows error message with retry option.
2179
- */
2180
- function ErrorStep({ message, buttonText = "Try Again", buttonVariant = "primary", onRetry }) {
2181
- const buttonClass = themeButtonClassName({
2182
- variant: buttonVariant,
2183
- size: "md"
2184
- });
2185
- return /* @__PURE__ */ jsx(TerminalPanel, {
2186
- tone: "error",
2187
- className: "er-whole-series-error",
2188
- titleClassName: "er-whole-series-error__title",
2189
- icon: /* @__PURE__ */ jsx(StateIcon, {
2190
- variant: "error",
2191
- children: /* @__PURE__ */ jsx(CrossIcon, {})
2192
- }),
2193
- title: "Enrollment Failed",
2194
- body: /* @__PURE__ */ jsx("p", {
2195
- className: "er-whole-series-error__message",
2196
- children: message
2197
- }),
2198
- actionsClassName: "er-whole-series-error__retry",
2199
- actions: /* @__PURE__ */ jsx("button", {
2200
- type: "button",
2201
- onClick: onRetry,
2202
- className: buttonClass,
2203
- children: buttonText
2204
- })
2205
- });
2206
- }
2207
- //#endregion
2208
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/PaymentFailedStep.tsx
2209
- /**
2210
- * Payment failed terminal state component.
2211
- * Shows when payment could not be processed.
2212
- */
2213
- function PaymentFailedStep({ message = "Your payment could not be processed.", buttonText = "Try Again", buttonVariant = "primary", onRetry }) {
2214
- const buttonClass = themeButtonClassName({
2215
- variant: buttonVariant,
2216
- size: "md"
2217
- });
2218
- return /* @__PURE__ */ jsx(TerminalPanel, {
2219
- tone: "error",
2220
- className: "er-whole-series-payment-failed",
2221
- titleClassName: "er-whole-series-payment-failed__title",
2222
- icon: /* @__PURE__ */ jsx(StateIcon, {
2223
- variant: "error",
2224
- children: /* @__PURE__ */ jsx(CrossIcon, {})
2225
- }),
2226
- title: "Payment Failed",
2227
- body: /* @__PURE__ */ jsx("p", {
2228
- className: "er-whole-series-payment-failed__message",
2229
- children: message
2230
- }),
2231
- actionsClassName: "er-whole-series-payment-failed__retry",
2232
- actions: /* @__PURE__ */ jsx("button", {
2233
- type: "button",
2234
- onClick: onRetry,
2235
- className: buttonClass,
2236
- children: buttonText
2237
- })
2238
- });
2239
- }
2240
- //#endregion
2241
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/SuccessStep.tsx
2242
- /**
2243
- * Success terminal state component.
2244
- * Shows confirmation after successful enrollment.
2245
- */
2246
- function SuccessStep({ usedMembership, successMessage, membershipMessage }) {
2247
- return /* @__PURE__ */ jsx(TerminalPanel, {
2248
- tone: "success",
2249
- className: "er-whole-series-success",
2250
- titleClassName: "er-whole-series-success__title",
2251
- icon: /* @__PURE__ */ jsx(StateIcon, {
2252
- variant: "success",
2253
- children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 2 })
2254
- }),
2255
- title: "Enrollment Complete!",
2256
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2257
- className: "er-whole-series-success__message",
2258
- children: usedMembership ? membershipMessage : successMessage
2259
- }), usedMembership && /* @__PURE__ */ jsx("p", {
2260
- className: "er-whole-series-success__membership",
2261
- children: "Enrolled using your membership"
2262
- })] })
2263
- });
2264
- }
2265
- //#endregion
2266
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/VerifyingTimeoutStep.tsx
2267
- /**
2268
- * Verifying timeout terminal state component.
2269
- * Shows when payment verification takes too long.
2270
- */
2271
- function VerifyingTimeoutStep({ buttonText = "Check Again", buttonVariant = "primary", onCheckAgain, supportEmail }) {
2272
- const buttonClass = themeButtonClassName({
2273
- variant: buttonVariant,
2274
- size: "md"
2275
- });
2276
- return /* @__PURE__ */ jsx(TerminalPanel, {
2277
- tone: "warning",
2278
- className: "er-whole-series-error",
2279
- titleClassName: "er-whole-series-error__title",
2280
- icon: /* @__PURE__ */ jsx(StateIcon, {
2281
- variant: "warning",
2282
- children: /* @__PURE__ */ jsx(ClockIcon, {})
2283
- }),
2284
- title: "Payment Verification Taking Longer",
2285
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2286
- className: "er-whole-series-error__message",
2287
- children: "Your payment may still be processing. Please check your email for confirmation."
2288
- }), supportEmail && /* @__PURE__ */ jsxs("p", {
2289
- className: "er-whole-series-error__message",
2290
- children: [
2291
- "If you need help, contact us at",
2292
- " ",
2293
- /* @__PURE__ */ jsx("a", {
2294
- href: `mailto:${supportEmail}`,
2295
- children: supportEmail
2296
- })
2297
- ]
2298
- })] }),
2299
- actionsClassName: "er-whole-series-error__retry",
2300
- actions: /* @__PURE__ */ jsx("button", {
2301
- type: "button",
2302
- onClick: onCheckAgain,
2303
- className: buttonClass,
2304
- children: buttonText
2305
- })
2306
- });
2307
- }
2308
- //#endregion
2309
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WaitlistStep.tsx
2310
- /**
2311
- * Waitlist terminal state component.
2312
- * Shows confirmation when user is added to waitlist.
2313
- */
2314
- function WaitlistStep({ message, position }) {
2315
- return /* @__PURE__ */ jsx(TerminalPanel, {
2316
- tone: "info",
2317
- className: "er-whole-series-waitlist",
2318
- titleClassName: "er-whole-series-waitlist__title",
2319
- icon: /* @__PURE__ */ jsx(StateIcon, {
2320
- variant: "waitlist",
2321
- children: /* @__PURE__ */ jsx(ClockIcon, {})
2322
- }),
2323
- title: "Added to Waitlist",
2324
- body: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
2325
- className: "er-whole-series-waitlist__message",
2326
- children: message
2327
- }), typeof position === "number" && /* @__PURE__ */ jsxs("p", {
2328
- className: "er-whole-series-waitlist__position",
2329
- children: ["Your position: #", position]
2330
- })] })
2331
- });
2332
- }
2333
- //#endregion
2334
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationTerminalContent.tsx
2335
- function WholeSeriesRegistrationTerminalContent({ wizard, copy }) {
2336
- switch (wizard.step) {
2337
- case "submitting": return /* @__PURE__ */ jsx(PendingState, {
2338
- label: "Booking run...",
2339
- spinnerLabel: "Processing"
2340
- });
2341
- case "redirecting": return /* @__PURE__ */ jsx(PendingState, {
2342
- label: "Redirecting to payment...",
2343
- spinnerLabel: "Redirecting"
2344
- });
2345
- case "verifying-payment": return /* @__PURE__ */ jsx(PendingState, {
2346
- label: "Verifying payment...",
2347
- spinnerLabel: "Verifying payment"
2348
- });
2349
- case "verifying-timeout": return /* @__PURE__ */ jsx(VerifyingTimeoutStep, {
2350
- buttonVariant: copy.buttonVariant,
2351
- onCheckAgain: wizard.handleRetry
2352
- });
2353
- case "payment-failed": return /* @__PURE__ */ jsx(PaymentFailedStep, {
2354
- message: wizard.errorMessage,
2355
- buttonVariant: copy.buttonVariant,
2356
- onRetry: wizard.handleRetry
2357
- });
2358
- case "success": return /* @__PURE__ */ jsx(SuccessStep, {
2359
- usedMembership: wizard.enrollmentResult?.usedMembership,
2360
- successMessage: copy.successMessage,
2361
- membershipMessage: copy.membershipMessage
2362
- });
2363
- case "waitlist": return /* @__PURE__ */ jsx(WaitlistStep, {
2364
- message: copy.waitlistMessage,
2365
- position: wizard.enrollmentResult?.waitlistPosition
2366
- });
2367
- case "error": return /* @__PURE__ */ jsx(ErrorStep, {
2368
- message: wizard.errorMessage,
2369
- buttonVariant: copy.buttonVariant,
2370
- onRetry: wizard.handleRetry
2371
- });
2372
- case "booking-mode":
2373
- case "enter-details":
2374
- case "select-payment":
2375
- case "select-run": return null;
2376
- }
2377
- }
2378
- function PendingState({ label, spinnerLabel }) {
2379
- return /* @__PURE__ */ jsxs("div", {
2380
- className: "er-whole-series-center",
2381
- children: [/* @__PURE__ */ jsx(SpinnerNode, {
2382
- size: "md",
2383
- srLabel: spinnerLabel
2384
- }), /* @__PURE__ */ jsx("p", {
2385
- className: "er-whole-series-text--muted",
2386
- children: label
2387
- })]
2388
- });
2389
- }
2390
- //#endregion
2391
- //#region ../blocks/src/system/runtime/nodes/event-registration/whole-series/WholeSeriesRegistrationWizard.tsx
2392
- const DEFAULT_COPY = {
2393
- successMessage: "You're booked in! Check your email for confirmation and session details.",
2394
- waitlistMessage: "You've been added to the waitlist. We'll email you a claim link if a spot opens up.",
2395
- membershipMessage: "Booked using your membership! Check your email for session details.",
2396
- buttonText: "Sign up"
2397
- };
2398
- function WholeSeriesRegistrationWizard(props) {
2399
- const presentation = resolveWholeSeriesRegistrationPresentation(props.presentationKind ?? "event");
2400
- const wizard = useWholeSeriesRegistrationWizard(props, { anchorId: presentation.anchorId });
2401
- const className = `${presentation.rootClass} ${props.className ?? ""}`;
2402
- const emptyMessage = resolveEmptyMessage(props, wizard);
2403
- if (emptyMessage) return /* @__PURE__ */ jsx(RegistrationRoot, {
2404
- className,
2405
- presentation,
2406
- children: /* @__PURE__ */ jsx("div", {
2407
- className: "er-whole-series-empty",
2408
- children: /* @__PURE__ */ jsx("p", {
2409
- className: "er-whole-series-empty__text",
2410
- children: emptyMessage
2411
- })
2412
- })
2413
- });
2414
- return /* @__PURE__ */ jsx(RegistrationWorkspace, {
2415
- wizard,
2416
- props,
2417
- className,
2418
- presentation
2419
- });
2420
- }
2421
- function RegistrationWorkspace({ wizard, props, className, presentation }) {
2422
- const display = resolveDisplayProps(props);
2423
- const copy = resolveTerminalCopy(props);
2424
- const showSidebar = wizard.showPortalAuthSidebar;
2425
- return /* @__PURE__ */ jsx(RegistrationRoot, {
2426
- className,
2427
- presentation,
2428
- children: /* @__PURE__ */ jsx("div", {
2429
- className: "rb-reg-surface er-whole-series-container",
2430
- children: /* @__PURE__ */ jsxs("div", {
2431
- className: `er-whole-series-layout${showSidebar ? " er-whole-series-layout--with-sidebar" : ""}`,
2432
- children: [/* @__PURE__ */ jsxs("div", {
2433
- className: "er-whole-series-layout__main",
2434
- children: [
2435
- WIZARD_STEPS.includes(wizard.step) && wizard.totalSteps > 1 ? /* @__PURE__ */ jsx(StepIndicator, {
2436
- currentStep: wizard.currentStepNumber,
2437
- totalSteps: wizard.totalSteps,
2438
- stepLabels: wizard.stepLabels
2439
- }) : null,
2440
- /* @__PURE__ */ jsx(WholeSeriesRegistrationActiveStep, {
2441
- wizard,
2442
- display
2443
- }),
2444
- /* @__PURE__ */ jsx(WholeSeriesRegistrationTerminalContent, {
2445
- wizard,
2446
- copy
2447
- })
2448
- ]
2449
- }), showSidebar ? /* @__PURE__ */ jsx(RegistrationSidebar, { wizard }) : null]
2450
- })
2451
- })
2452
- });
2453
- }
2454
- function resolveDisplayProps(props) {
2455
- return {
2456
- showSessions: props.showSessions ?? true,
2457
- showPrice: props.showPrice ?? true,
2458
- showCapacity: props.showCapacity ?? true,
2459
- showVenue: props.showVenue ?? true,
2460
- buttonText: props.buttonText ?? DEFAULT_COPY.buttonText,
2461
- buttonVariant: props.buttonVariant
2462
- };
2463
- }
2464
- function resolveTerminalCopy(props) {
2465
- return {
2466
- successMessage: props.successMessage ?? DEFAULT_COPY.successMessage,
2467
- waitlistMessage: props.waitlistMessage ?? DEFAULT_COPY.waitlistMessage,
2468
- membershipMessage: props.membershipMessage ?? DEFAULT_COPY.membershipMessage,
2469
- buttonVariant: props.buttonVariant
2470
- };
2471
- }
2472
- function RegistrationRoot({ children, className, presentation }) {
2473
- return /* @__PURE__ */ jsx("div", {
2474
- id: presentation.anchorId,
2475
- className,
2476
- "data-block": presentation.dataBlock,
2477
- children
2478
- });
2479
- }
2480
- function RegistrationSidebar({ wizard }) {
2481
- return /* @__PURE__ */ jsx("div", {
2482
- className: "er-whole-series-layout__sidebar",
2483
- children: /* @__PURE__ */ jsx(PortalAuthSidebar, {
2484
- autoOpen: wizard.waitlistClaim.requiresPortalLogin,
2485
- loginMessage: wizard.waitlistClaim.loginMessage,
2486
- variant: wizard.waitlistClaim.requiresPortalLogin ? "waitlist-claim" : "membership"
2487
- })
2488
- });
2489
- }
2490
- function resolveEmptyMessage(props, wizard) {
2491
- 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.";
2492
- const allowedStatuses = wizard.api.config.isPreview ? ["active", "draft"] : ["active"];
2493
- return wizard.scopedRuns.some((run) => !run.status || allowedStatuses.includes(run.status)) ? null : "Booking is not currently available for this run.";
2494
- }
2495
- //#endregion
2496
- export { MagicLinkForm as a, useWaitlistClaim as i, LoggedInAsUser as n, WholeSeriesRegistrationErrorBoundary as o, logoutPortal as r, ClockIcon as s, WholeSeriesRegistrationWizard as t };