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