@riverbankcms/sdk 0.123.0 → 0.124.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -9
- package/dist/{PreviewEditorSidebar-DvJFmC29.mjs → PreviewEditorSidebar-DBmAJJkQ.mjs} +22 -39
- package/dist/{PreviewEditorUI-DVHP4bCo.mjs → PreviewEditorUI-CfGaz9cY.mjs} +3 -3
- package/dist/{PreviewQueryProvider-07EE4uWL.mjs → PreviewQueryProvider-BH-3-jSj.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-BE5eFayo.mjs → SdkPreviewModeRuntime-BW9Z8j8T.mjs} +1020 -1234
- package/dist/{SiteChromeCustomizeContext-4hn4A0HX.mjs → SiteChromeCustomizeContext-2z8moxYf.mjs} +1900 -1959
- package/dist/_dts/ai/src/contracts/proposals.d.ts +1236 -4152
- package/dist/_dts/api/src/appointmentEndpointDefinitions.d.ts +435 -0
- package/dist/_dts/api/src/bookingClosures.d.ts +3 -3
- package/dist/_dts/api/src/bookingConfig.d.ts +72 -73
- package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +26 -35
- package/dist/_dts/api/src/bookingRecords.d.ts +4 -15
- package/dist/_dts/api/src/bookingVerticalCatalog.d.ts +746 -0
- package/dist/_dts/api/src/bookingVerticalPreset.d.ts +38 -0
- package/dist/_dts/api/src/bookingVerticals.d.ts +11 -652
- package/dist/_dts/api/src/bookings.d.ts +11 -9
- package/dist/_dts/api/src/cache-tags.d.ts +2 -2
- package/dist/_dts/api/src/commercePortalEndpoints.d.ts +10 -10
- package/dist/_dts/api/src/common/envelope.d.ts +2 -0
- package/dist/_dts/api/src/contentRuntime.d.ts +0 -17
- package/dist/_dts/api/src/courseEndpointDefinitions.d.ts +99 -0
- package/dist/_dts/api/src/courses.d.ts +22 -33
- package/dist/_dts/api/src/defineEndpointDefinitions.d.ts +14 -0
- package/dist/_dts/api/src/demoMutationPolicies.d.ts +4 -0
- package/dist/_dts/api/src/endpoints.d.ts +3740 -3733
- package/dist/_dts/api/src/event-destination-policy.d.ts +1 -1
- package/dist/_dts/api/src/event-presentation.d.ts +4 -9
- package/dist/_dts/api/src/index.d.ts +9 -11
- package/dist/_dts/api/src/newsletterEndpointDefinitions.d.ts +376 -0
- package/dist/_dts/api/src/participantMessaging.d.ts +2 -2
- package/dist/_dts/api/src/public/endpoints.d.ts +1 -1
- package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +272 -0
- package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +274 -0
- package/dist/_dts/api/src/publicExperience/newsletterEndpoints.d.ts +31 -0
- package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +152 -0
- package/dist/_dts/api/src/publicExperience/siteEndpoints.d.ts +95 -0
- package/dist/_dts/api/src/publicExperience/wholeSeriesEndpoints.d.ts +154 -0
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +10 -962
- package/dist/_dts/api/src/publicWholeSeriesEndpointDefinitions.d.ts +52 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +0 -51
- package/dist/_dts/api/src/sdkEntryReadEndpoints.d.ts +23 -0
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +1 -38
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -4
- package/dist/_dts/blocks/src/PageRenderer.d.ts +4 -15
- package/dist/_dts/blocks/src/contracts/index.d.ts +1 -1
- package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +0 -16
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +6 -222
- package/dist/_dts/blocks/src/portal/types.d.ts +3 -3
- package/dist/_dts/blocks/src/subroutes/fold.d.ts +1 -14
- package/dist/_dts/blocks/src/subroutes/index.d.ts +1 -1
- package/dist/_dts/blocks/src/subroutes/kinds.d.ts +3 -3
- package/dist/_dts/blocks/src/system/blocks/course-details.d.ts +0 -11
- package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +3 -4
- package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +1 -1
- package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +401 -12
- package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +9 -10
- package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +14 -13
- package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +1 -2
- package/dist/_dts/blocks/src/system/blocks/events/shared/filtering.d.ts +1 -4
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +19 -18
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +9 -11
- package/dist/_dts/blocks/src/system/blocks/offerings-preview/model.d.ts +2 -2
- package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +10 -10
- package/dist/_dts/blocks/src/system/runtime/api/endpoints.d.ts +10 -10
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/types/appointments.d.ts +162 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +59 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/courses.d.ts +134 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/discounts.d.ts +85 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +241 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/forms.d.ts +53 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/newsletter.d.ts +32 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +220 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +176 -0
- package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +12 -1121
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +19 -583
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +9 -276
- package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +1 -12
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessEventRegistrationFlow.d.ts +0 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +0 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +2 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details/logic.d.ts +1 -18
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details/runs.d.ts +0 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/course-details.server.d.ts +1 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/courseRegistrationViewState.d.ts +21 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/pricing.d.ts +14 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/types.d.ts +0 -25
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseEligibility.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.d.ts +9 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.d.ts +35 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationPortal.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.d.ts +31 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +80 -55
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseWaitlistSelection.d.ts +14 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.contract.d.ts +4 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +0 -38
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.client.d.ts +1 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.server.d.ts +0 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizardActions.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +0 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventScope.d.ts +0 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +0 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +0 -11
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/utils.d.ts +13 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +0 -21
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +24 -433
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +1 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +52 -266
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +5 -15
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventFilters.d.ts +0 -8
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +1573 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +1 -3
- package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +2 -3
- package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +2 -2
- package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +0 -5
- package/dist/_dts/content-model/src/content-types/builtins.d.ts +0 -5
- package/dist/_dts/content-model/src/templates/defaults.d.ts +6 -3
- package/dist/_dts/core/src/editor-state.d.ts +1 -13
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +1580 -120
- package/dist/_dts/preview-next/src/client/preview/siteChromeBrandPreferences.d.ts +6 -6
- package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +6 -1
- package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +27 -4
- package/dist/_dts/sdk/src/cli/commands/audit.d.ts +1 -2
- package/dist/_dts/sdk/src/cli/commands/pull-dated-offering-scope.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/commands/pull-dry-run.d.ts +4 -6
- package/dist/_dts/sdk/src/cli/commands/push/consts.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/commands/push/options.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/commands/push/pushAllExtras.d.ts +0 -1
- package/dist/_dts/sdk/src/cli/commands/push/verification.d.ts +1 -1
- package/dist/_dts/sdk/src/cli/content/collectionWriters.d.ts +23 -0
- package/dist/_dts/sdk/src/cli/content/metadataAfterPush.d.ts +25 -0
- package/dist/_dts/sdk/src/cli/content/reader.d.ts +0 -52
- package/dist/_dts/sdk/src/cli/content/writer.d.ts +3 -81
- package/dist/_dts/sdk/src/cli/site-commands/datedOfferingCommands.d.ts +6 -9
- package/dist/_dts/sdk/src/client/contentReadOperations.d.ts +40 -0
- package/dist/_dts/sdk/src/client/management/index.d.ts +1 -3
- package/dist/_dts/sdk/src/client/management/types.d.ts +3 -91
- package/dist/_dts/sdk/src/client/runtimeCacheKeys.d.ts +72 -0
- package/dist/_dts/sdk/src/client/runtimeCachePolicy.d.ts +10 -75
- package/dist/_dts/sdk/src/client/types.d.ts +7 -33
- package/dist/_dts/sdk/src/components.d.ts +1 -1
- package/dist/_dts/sdk/src/config/types.d.ts +1 -1
- package/dist/_dts/sdk/src/config/validation.d.ts +3 -6
- package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
- package/dist/_dts/sdk/src/contracts/page.d.ts +0 -8
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +1 -34
- package/dist/_dts/sdk/src/data/prefetchBlockData.d.ts +4 -3
- package/dist/_dts/sdk/src/next/catch-all-utils.d.ts +0 -11
- package/dist/_dts/sdk/src/next/catch-all.d.ts +1 -76
- package/dist/_dts/sdk/src/next/types.d.ts +0 -19
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +7 -207
- package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -1
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -2
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +0 -7
- package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +81 -0
- package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/islands/types.d.ts +1 -51
- package/dist/_dts/sdk/src/rendering/overrides.d.ts +2 -1
- package/dist/_dts/sdk/src/routing/entrySubroutes.d.ts +6 -6
- package/dist/_dts/sdk/src/routing/index.d.ts +0 -2
- package/dist/_dts/sdk/src/routing/resolveOccurrence.d.ts +3 -3
- package/dist/_dts/sdk/src/routing/resolvePageContent.d.ts +10 -39
- package/dist/_dts/sdk/src/types/block-kinds.d.ts +1 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/site-commands/src/adapter.d.ts +1 -1
- package/dist/_dts/site-commands/src/appointmentCommandSchemas.d.ts +100 -0
- package/dist/_dts/site-commands/src/capabilityGaps.d.ts +2 -2
- package/dist/_dts/site-commands/src/commandContract.d.ts +1242 -0
- package/dist/_dts/site-commands/src/commandDomain.d.ts +20 -0
- package/dist/_dts/site-commands/src/commandIdentifiers.d.ts +7 -0
- package/dist/_dts/site-commands/src/commandValidation.d.ts +10 -0
- package/dist/_dts/site-commands/src/commands.d.ts +729 -2659
- package/dist/_dts/site-commands/src/domain.d.ts +1 -1
- package/dist/_dts/site-commands/src/eventCommandContent.d.ts +11 -0
- package/dist/_dts/site-commands/src/exposure.d.ts +1 -1
- package/dist/_dts/site-commands/src/index.d.ts +6 -0
- package/dist/_dts/site-commands/src/metadata.d.ts +1 -27
- package/dist/_dts/site-commands/src/planner.d.ts +1 -1
- package/dist/_dts/site-commands/src/refContributions.d.ts +1 -1
- package/dist/_dts/site-commands/src/refs.d.ts +1 -4
- package/dist/_dts/site-commands/src/siteStyleCommandSchema.d.ts +378 -0
- package/dist/_dts/site-commands/src/siteStyleSelectionSchemaBuilder.d.ts +46 -0
- package/dist/_dts/site-commands/src/staticExecutionGaps.d.ts +2 -2
- package/dist/_dts/site-commands/src/venueCommandMapping.d.ts +21 -0
- package/dist/_dts/theme-core/src/site-styles/compilationPlan.d.ts +58 -0
- package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +1 -0
- package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
- package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +47 -24
- package/dist/cli/index.mjs +7250 -8478
- package/dist/cli/init-docs/content/cli-reference.md +5 -21
- package/dist/cli/init-docs/content/content-management.md +4 -5
- package/dist/client/{DiscountCodeDisclosure-DIWj-P9v.mjs → DiscountCodeDisclosure-DxvjKvck.mjs} +2 -2
- package/dist/client/{EventCombined.client-De8YWBSr.mjs → EventCombined.client-BydMGc4c.mjs} +5 -16
- package/dist/client/{EventListing.client-seHTjimY.mjs → EventListing.client-vpzhhysN.mjs} +3 -10
- package/dist/client/{LeafletStaticMap-BmQxFcJW.mjs → LeafletStaticMap-CB07rpf8.mjs} +1 -1
- package/dist/client/{MagicLinkForm-OoJAIUIj.mjs → MagicLinkForm-BzyRJ8VF.mjs} +2 -2
- package/dist/client/{StepIndicator-CiZ8kdPk.mjs → StepIndicator-CTcGf8Be.mjs} +2 -2
- package/dist/client/{accordion-6lnN__XJ.mjs → accordion-B-DUDLRD.mjs} +1 -1
- package/dist/client/{bookingForm-5uyqhONU.mjs → bookingForm-DSbClLcZ.mjs} +6 -6
- package/dist/client/bookings.mjs +753 -818
- package/dist/client/{carousel-Dtnifil_.mjs → carousel-B6Ccdx8M.mjs} +1 -1
- package/dist/client/{cart-5Tc5S7NV.mjs → cart-BZh8G8wM.mjs} +3 -3
- package/dist/client/{checkout-CYKKN5Hr.mjs → checkout-o6zaC-kM.mjs} +3 -3
- package/dist/client/client.mjs +6859 -7149
- package/dist/client/{context-BGZNlGXB.mjs → context-CJz1Vlsz.mjs} +40 -43
- package/dist/client/{courseRegistration-CxCBybB4.mjs → courseRegistration-Cf11pNDs.mjs} +606 -621
- package/dist/client/{eventCalendar-Xj2jZS9X.mjs → eventCalendar-BeXrdsSE.mjs} +5 -13
- package/dist/client/{eventCombined-CgcMoOgM.mjs → eventCombined-DA76PZgG.mjs} +3 -3
- package/dist/client/{eventDetails-CEAH8Edc.mjs → eventDetails-BLxg0rok.mjs} +140 -116
- package/dist/client/{eventListing-qyPVQ0wP.mjs → eventListing-tO9LheBX.mjs} +3 -3
- package/dist/client/{eventRegistration-DDu79CtL.mjs → eventRegistration-Cnene9D9.mjs} +165 -68
- package/dist/client/{form-Bc7JKI7I.mjs → form-DZf72CHB.mjs} +2 -2
- package/dist/client/{headerSection-vTku_LEl.mjs → headerSection-Hioja5Cr.mjs} +2 -2
- package/dist/client/hooks.mjs +3452 -2365
- package/dist/client/{locationMap-Bg7X4Jna.mjs → locationMap-DwhUXEix.mjs} +2 -2
- package/dist/client/{newsletterForm-lpylVdp5.mjs → newsletterForm-C350bEQf.mjs} +2 -2
- package/dist/client/{pricing-DE8fjJiT.mjs → pricing-BYWN_ATa.mjs} +3 -19
- package/dist/client/{productDetail-D7Bo2RMH.mjs → productDetail-CCqCyXgU.mjs} +3 -3
- package/dist/client/{productList-VjnZqiqN.mjs → productList-BAiNJrOU.mjs} +3 -3
- package/dist/client/{propsDecoder-DreFXjNP.mjs → propsDecoder-DeunRj6m.mjs} +210 -378
- package/dist/client/rendering/client.mjs +2541 -2813
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +5622 -4734
- package/dist/client/{shop-IRsHHbf7.mjs → shop-DUmCdBtw.mjs} +6 -6
- package/dist/client/{shop-commerce-gnI8PieZ.mjs → shop-commerce-CY27mEUr.mjs} +5 -5
- package/dist/client/{shop-commerce-store-BTbrhObn.mjs → shop-commerce-store-ChXPbWfa.mjs} +1 -1
- package/dist/client/{shopShared-D6KS2_qk.mjs → shopShared-q0kin1cv.mjs} +3 -3
- package/dist/client/{useDiscountCodeUi-DCccGCxV.mjs → useDiscountCodeUi-I-92-x2V.mjs} +2 -2
- package/dist/client/{useEventFilters-eGs3rPZQ.mjs → useEventFilters-DlcVluZh.mjs} +59 -124
- package/dist/client/{usePolling-CvSU2sur.mjs → usePolling-Bz7GFV_a.mjs} +2 -2
- package/dist/preview-next/before-render.mjs +1115 -1044
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/middleware.mjs +1118 -1047
- package/dist/{previewAuthStore-ShY26RNz.mjs → previewAuthStore-CJX21dGi.mjs} +1121 -1047
- package/dist/{sdk-runtime-CJxkFq2B.mjs → sdk-runtime-OnPM8Z69.mjs} +2 -2
- package/dist/{separator-CoFmo8uA.mjs → separator-CPtfzHqA.mjs} +1 -1
- package/dist/server/components.mjs +4560 -3672
- package/dist/server/config-validation.mjs +3454 -2356
- package/dist/server/config.mjs +3454 -2356
- package/dist/server/data.mjs +3452 -2367
- package/dist/server/index.mjs +1501 -1491
- package/dist/server/next.mjs +7524 -8067
- package/dist/server/page-converter.mjs +1898 -2040
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +4258 -3373
- package/dist/server/rendering.mjs +6228 -5393
- package/dist/server/routing.mjs +3614 -2509
- package/dist/server/server.mjs +3298 -3479
- package/package.json +1 -1
- package/dist/_dts/api/src/previewContentContract.d.ts +0 -4
- package/dist/_dts/sdk/src/cli/commands/course.d.ts +0 -6
- package/dist/_dts/sdk/src/cli/commands/push/scopes/courses.d.ts +0 -4
- package/dist/_dts/sdk/src/client/management/courses.d.ts +0 -10
- package/dist/_dts/sdk/src/routing/resolveEntrySubroute.d.ts +0 -36
package/dist/client/bookings.mjs
CHANGED
|
@@ -2583,23 +2583,23 @@ const EVENTS = {
|
|
|
2583
2583
|
method: "GET"
|
|
2584
2584
|
}
|
|
2585
2585
|
};
|
|
2586
|
-
const
|
|
2586
|
+
const WHOLE_SERIES = {
|
|
2587
2587
|
list: {
|
|
2588
|
-
path: "/public/sites/{siteId}/
|
|
2588
|
+
path: "/public/sites/{siteId}/dated-offerings/whole-series",
|
|
2589
2589
|
method: "GET"
|
|
2590
2590
|
},
|
|
2591
2591
|
enroll: {
|
|
2592
|
-
path: "/public/sites/{siteId}/
|
|
2592
|
+
path: "/public/sites/{siteId}/dated-offerings/whole-series/enroll",
|
|
2593
2593
|
method: "POST",
|
|
2594
2594
|
authScope: "portal"
|
|
2595
2595
|
},
|
|
2596
2596
|
checkout: {
|
|
2597
|
-
path: "/public/sites/{siteId}/
|
|
2597
|
+
path: "/public/sites/{siteId}/dated-offerings/whole-series/checkout",
|
|
2598
2598
|
method: "POST",
|
|
2599
2599
|
authScope: "portal"
|
|
2600
2600
|
},
|
|
2601
2601
|
checkEligibility: {
|
|
2602
|
-
path: "/public/sites/{siteId}/
|
|
2602
|
+
path: "/public/sites/{siteId}/dated-offerings/whole-series/check-eligibility",
|
|
2603
2603
|
method: "POST",
|
|
2604
2604
|
authScope: "portal"
|
|
2605
2605
|
},
|
|
@@ -2609,7 +2609,7 @@ const COURSES = {
|
|
|
2609
2609
|
authScope: "portal"
|
|
2610
2610
|
},
|
|
2611
2611
|
registrationStatus: {
|
|
2612
|
-
path: "/public/sites/{siteId}/
|
|
2612
|
+
path: "/public/sites/{siteId}/dated-offerings/whole-series/registration-status",
|
|
2613
2613
|
method: "GET",
|
|
2614
2614
|
authScope: "portal"
|
|
2615
2615
|
}
|
|
@@ -2765,26 +2765,26 @@ const PORTAL = {
|
|
|
2765
2765
|
authScope: "portal",
|
|
2766
2766
|
skipPreviewStage: true
|
|
2767
2767
|
},
|
|
2768
|
-
|
|
2769
|
-
path: "/portal/
|
|
2768
|
+
getWholeSeriesRegistrations: {
|
|
2769
|
+
path: "/portal/dated-offerings/whole-series",
|
|
2770
2770
|
method: "GET",
|
|
2771
2771
|
authScope: "portal",
|
|
2772
2772
|
skipPreviewStage: true
|
|
2773
2773
|
},
|
|
2774
|
-
|
|
2775
|
-
path: "/portal/
|
|
2774
|
+
getWholeSeriesBookingQuestions: {
|
|
2775
|
+
path: "/portal/dated-offerings/whole-series/{enrollmentId}/booking-questions",
|
|
2776
2776
|
method: "GET",
|
|
2777
2777
|
authScope: "portal",
|
|
2778
2778
|
skipPreviewStage: true
|
|
2779
2779
|
},
|
|
2780
|
-
|
|
2781
|
-
path: "/portal/
|
|
2780
|
+
updateWholeSeriesBookingQuestions: {
|
|
2781
|
+
path: "/portal/dated-offerings/whole-series/{enrollmentId}/booking-questions",
|
|
2782
2782
|
method: "PUT",
|
|
2783
2783
|
authScope: "portal",
|
|
2784
2784
|
skipPreviewStage: true
|
|
2785
2785
|
},
|
|
2786
|
-
|
|
2787
|
-
path: "/portal/
|
|
2786
|
+
cancelWholeSeriesRegistration: {
|
|
2787
|
+
path: "/portal/dated-offerings/whole-series/{enrollmentId}/cancel",
|
|
2788
2788
|
method: "POST",
|
|
2789
2789
|
authScope: "portal",
|
|
2790
2790
|
skipPreviewStage: true
|
|
@@ -3137,14 +3137,12 @@ function createBlockApi(config) {
|
|
|
3137
3137
|
afterId: params?.afterId,
|
|
3138
3138
|
limit: params?.limit,
|
|
3139
3139
|
stage: params?.stage,
|
|
3140
|
-
kind: params?.kind,
|
|
3141
3140
|
eventSurface: params?.eventSurface,
|
|
3142
3141
|
eventPresets: params?.eventPresets,
|
|
3143
3142
|
scheduleScope: params?.scheduleScope,
|
|
3144
3143
|
categoryIds: params?.categoryIds,
|
|
3145
3144
|
venueId: params?.venueId,
|
|
3146
3145
|
staffMemberId: params?.staffMemberId,
|
|
3147
|
-
entryId: params?.entryId,
|
|
3148
3146
|
seriesId: params?.seriesId,
|
|
3149
3147
|
includeOccurrenceId: params?.includeOccurrenceId,
|
|
3150
3148
|
detailLevel: params?.detailLevel
|
|
@@ -3160,7 +3158,6 @@ function createBlockApi(config) {
|
|
|
3160
3158
|
categoryIds: params?.categoryIds,
|
|
3161
3159
|
venueId: params?.venueId,
|
|
3162
3160
|
staffMemberId: params?.staffMemberId,
|
|
3163
|
-
kind: params?.kind,
|
|
3164
3161
|
eventSurface: params?.eventSurface,
|
|
3165
3162
|
eventPresets: params?.eventPresets,
|
|
3166
3163
|
scheduleScope: params?.scheduleScope
|
|
@@ -3200,37 +3197,37 @@ function createBlockApi(config) {
|
|
|
3200
3197
|
skipDedup: true
|
|
3201
3198
|
});
|
|
3202
3199
|
},
|
|
3203
|
-
async
|
|
3200
|
+
async registerForWholeSeries(data) {
|
|
3204
3201
|
const sid = requireSiteId();
|
|
3205
|
-
const path = buildPath(
|
|
3206
|
-
return request(
|
|
3202
|
+
const path = buildPath(WHOLE_SERIES.enroll.path, { siteId: sid });
|
|
3203
|
+
return request(WHOLE_SERIES.enroll, {
|
|
3207
3204
|
path,
|
|
3208
3205
|
body: withRequestOverrides(data, shouldUsePreviewStageForNonPortalRequests ? { stage: "preview" } : {})
|
|
3209
3206
|
});
|
|
3210
3207
|
},
|
|
3211
|
-
async
|
|
3208
|
+
async checkWholeSeriesEligibility(data) {
|
|
3212
3209
|
const sid = requireSiteId();
|
|
3213
|
-
const path = buildPath(
|
|
3214
|
-
return request(
|
|
3210
|
+
const path = buildPath(WHOLE_SERIES.checkEligibility.path, { siteId: sid });
|
|
3211
|
+
return request(WHOLE_SERIES.checkEligibility, {
|
|
3215
3212
|
path,
|
|
3216
3213
|
body: data
|
|
3217
3214
|
});
|
|
3218
3215
|
},
|
|
3219
3216
|
async resolveWaitlistClaim(data) {
|
|
3220
3217
|
const sid = requireSiteId();
|
|
3221
|
-
const path = buildPath(
|
|
3222
|
-
return request(
|
|
3218
|
+
const path = buildPath(WHOLE_SERIES.waitlistClaimResolve.path, { siteId: sid });
|
|
3219
|
+
return request(WHOLE_SERIES.waitlistClaimResolve, {
|
|
3223
3220
|
path,
|
|
3224
3221
|
body: { claimToken: data.claimToken }
|
|
3225
3222
|
});
|
|
3226
3223
|
},
|
|
3227
|
-
async
|
|
3224
|
+
async createWholeSeriesCheckout(data) {
|
|
3228
3225
|
const sid = requireSiteId();
|
|
3229
|
-
const path = buildPath(
|
|
3230
|
-
return request(
|
|
3226
|
+
const path = buildPath(WHOLE_SERIES.checkout.path, { siteId: sid });
|
|
3227
|
+
return request(WHOLE_SERIES.checkout, {
|
|
3231
3228
|
path,
|
|
3232
3229
|
body: {
|
|
3233
|
-
|
|
3230
|
+
eventSeriesId: data.eventSeriesId,
|
|
3234
3231
|
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
3235
3232
|
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
3236
3233
|
email: data.email,
|
|
@@ -3245,10 +3242,10 @@ function createBlockApi(config) {
|
|
|
3245
3242
|
}
|
|
3246
3243
|
});
|
|
3247
3244
|
},
|
|
3248
|
-
async
|
|
3245
|
+
async getWholeSeriesRegistrationStatus(params) {
|
|
3249
3246
|
const sid = requireSiteId();
|
|
3250
|
-
const path = buildPath(
|
|
3251
|
-
return request(
|
|
3247
|
+
const path = buildPath(WHOLE_SERIES.registrationStatus.path, { siteId: sid });
|
|
3248
|
+
return request(WHOLE_SERIES.registrationStatus, {
|
|
3252
3249
|
path,
|
|
3253
3250
|
query: { sessionId: params.sessionId },
|
|
3254
3251
|
skipDedup: true
|
|
@@ -3421,23 +3418,23 @@ function createBlockApi(config) {
|
|
|
3421
3418
|
body: data
|
|
3422
3419
|
})).task;
|
|
3423
3420
|
},
|
|
3424
|
-
async
|
|
3425
|
-
return (await request(PORTAL.
|
|
3421
|
+
async getPortalWholeSeriesRegistrations() {
|
|
3422
|
+
return (await request(PORTAL.getWholeSeriesRegistrations)).enrollments;
|
|
3426
3423
|
},
|
|
3427
|
-
async
|
|
3428
|
-
const path = buildPath(PORTAL.
|
|
3429
|
-
return (await request(PORTAL.
|
|
3424
|
+
async getPortalWholeSeriesBookingQuestions(enrollmentId) {
|
|
3425
|
+
const path = buildPath(PORTAL.getWholeSeriesBookingQuestions.path, { enrollmentId });
|
|
3426
|
+
return (await request(PORTAL.getWholeSeriesBookingQuestions, { path })).task;
|
|
3430
3427
|
},
|
|
3431
|
-
async
|
|
3432
|
-
const path = buildPath(PORTAL.
|
|
3433
|
-
return (await request(PORTAL.
|
|
3428
|
+
async updatePortalWholeSeriesBookingQuestions(enrollmentId, data) {
|
|
3429
|
+
const path = buildPath(PORTAL.updateWholeSeriesBookingQuestions.path, { enrollmentId });
|
|
3430
|
+
return (await request(PORTAL.updateWholeSeriesBookingQuestions, {
|
|
3434
3431
|
path,
|
|
3435
3432
|
body: data
|
|
3436
3433
|
})).task;
|
|
3437
3434
|
},
|
|
3438
|
-
async
|
|
3439
|
-
const path = buildPath(PORTAL.
|
|
3440
|
-
return (await request(PORTAL.
|
|
3435
|
+
async cancelWholeSeriesRegistration(enrollmentId, options) {
|
|
3436
|
+
const path = buildPath(PORTAL.cancelWholeSeriesRegistration.path, { enrollmentId });
|
|
3437
|
+
return (await request(PORTAL.cancelWholeSeriesRegistration, {
|
|
3441
3438
|
path,
|
|
3442
3439
|
body: options ?? {}
|
|
3443
3440
|
})).result;
|
|
@@ -5284,7 +5281,7 @@ function useBookingSubmission(_siteId) {
|
|
|
5284
5281
|
};
|
|
5285
5282
|
}
|
|
5286
5283
|
//#endregion
|
|
5287
|
-
//#region ../blocks/src/system/runtime/api/types.ts
|
|
5284
|
+
//#region ../blocks/src/system/runtime/api/types/discounts.ts
|
|
5288
5285
|
function discountAvailabilityHasDiscounts(availability) {
|
|
5289
5286
|
return availability.type !== "none";
|
|
5290
5287
|
}
|
|
@@ -5316,7 +5313,7 @@ function getDiscountContextKey(context) {
|
|
|
5316
5313
|
context.ticketsCount ?? ""
|
|
5317
5314
|
].join(":");
|
|
5318
5315
|
case "appointment": return [context.type, context.serviceId].join(":");
|
|
5319
|
-
case "
|
|
5316
|
+
case "whole_series": return [context.type, context.eventSeriesId].join(":");
|
|
5320
5317
|
case "pass": return [context.type, context.passId].join(":");
|
|
5321
5318
|
case "membership": return [context.type, context.membershipId].join(":");
|
|
5322
5319
|
case "product": return [
|
|
@@ -13868,6 +13865,33 @@ const eventRegistrationSubmitDeps = { savePendingRegistration };
|
|
|
13868
13865
|
function useEventRegistrationSubmit(options) {
|
|
13869
13866
|
return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
|
|
13870
13867
|
}
|
|
13868
|
+
/**
|
|
13869
|
+
* Describe a completed registration to the success step.
|
|
13870
|
+
*
|
|
13871
|
+
* Only pass redemptions adopt the server's message: it names the credits spent
|
|
13872
|
+
* and the balance left, which the block's copy cannot. Every other method keeps
|
|
13873
|
+
* whatever success message the site configured.
|
|
13874
|
+
*/
|
|
13875
|
+
function toRegistrationResult(result) {
|
|
13876
|
+
if (result.alreadyRegistered) {
|
|
13877
|
+
const waitlisted = result.status === "waitlist";
|
|
13878
|
+
return {
|
|
13879
|
+
status: result.status,
|
|
13880
|
+
variant: "info",
|
|
13881
|
+
title: waitlisted ? "Already waitlisted" : "Already registered",
|
|
13882
|
+
message: result.message ?? (waitlisted ? "You are already on the waitlist for this event." : "You are already registered for this event.")
|
|
13883
|
+
};
|
|
13884
|
+
}
|
|
13885
|
+
if (result.status === "waitlist") return {
|
|
13886
|
+
status: "waitlist",
|
|
13887
|
+
title: "Added to waitlist",
|
|
13888
|
+
message: result.message ?? (typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.")
|
|
13889
|
+
};
|
|
13890
|
+
return {
|
|
13891
|
+
status: result.status,
|
|
13892
|
+
message: result.paymentMethod === "pass" ? result.message : void 0
|
|
13893
|
+
};
|
|
13894
|
+
}
|
|
13871
13895
|
function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
13872
13896
|
return async (method, passId, membershipId, selection, submitOptions) => {
|
|
13873
13897
|
const submitOccurrenceId = options.registrationTarget?.occurrenceId;
|
|
@@ -13977,23 +14001,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
13977
14001
|
}
|
|
13978
14002
|
};
|
|
13979
14003
|
}
|
|
13980
|
-
|
|
13981
|
-
const title = result.status === "waitlist" ? "Already waitlisted" : "Already registered";
|
|
13982
|
-
const fallbackMessage = result.status === "waitlist" ? "You are already on the waitlist for this event." : "You are already registered for this event.";
|
|
13983
|
-
options.setRegistrationResult({
|
|
13984
|
-
status: result.status,
|
|
13985
|
-
variant: "info",
|
|
13986
|
-
title,
|
|
13987
|
-
message: result.message ?? fallbackMessage
|
|
13988
|
-
});
|
|
13989
|
-
} else if (result.status === "waitlist") {
|
|
13990
|
-
const waitlistMessage = typeof result.waitlistPosition === "number" ? `You've been added to the waitlist (position ${result.waitlistPosition}).` : "You've been added to the waitlist.";
|
|
13991
|
-
options.setRegistrationResult({
|
|
13992
|
-
status: "waitlist",
|
|
13993
|
-
title: "Added to waitlist",
|
|
13994
|
-
message: result.message ?? waitlistMessage
|
|
13995
|
-
});
|
|
13996
|
-
} else options.setRegistrationResult({ status: result.status });
|
|
14004
|
+
options.setRegistrationResult(toRegistrationResult(result));
|
|
13997
14005
|
options.setStep("success");
|
|
13998
14006
|
return {
|
|
13999
14007
|
ok: true,
|
|
@@ -14359,16 +14367,15 @@ const coursePricingSchema = z$1.object({
|
|
|
14359
14367
|
/**
|
|
14360
14368
|
* Zod schema for public course data
|
|
14361
14369
|
*/
|
|
14362
|
-
const
|
|
14363
|
-
|
|
14364
|
-
|
|
14370
|
+
const publicWholeSeriesOfferingSchema = z$1.object({
|
|
14371
|
+
eventSeriesId: z$1.string(),
|
|
14372
|
+
eventOfferingId: z$1.string(),
|
|
14365
14373
|
title: z$1.string(),
|
|
14366
14374
|
slug: z$1.string(),
|
|
14367
14375
|
description: z$1.unknown().nullable(),
|
|
14368
14376
|
teamMembers: z$1.array(courseTeamMemberSummarySchema).optional(),
|
|
14369
14377
|
enrollmentOpen: z$1.boolean(),
|
|
14370
|
-
pricing: coursePricingSchema
|
|
14371
|
-
priceCents: z$1.number().nullable(),
|
|
14378
|
+
pricing: coursePricingSchema,
|
|
14372
14379
|
currency: z$1.string(),
|
|
14373
14380
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
14374
14381
|
enrollmentCapacity: z$1.number().nullable(),
|
|
@@ -14382,15 +14389,15 @@ const publicCourseSchema = z$1.object({
|
|
|
14382
14389
|
enrolledCount: z$1.number(),
|
|
14383
14390
|
availableSpots: z$1.number().nullable(),
|
|
14384
14391
|
sessions: z$1.array(courseSessionSchema),
|
|
14385
|
-
venue: courseVenueSchema.nullable()
|
|
14386
|
-
contentEntryId: z$1.string().nullable()
|
|
14392
|
+
venue: courseVenueSchema.nullable()
|
|
14387
14393
|
});
|
|
14388
|
-
z$1.array(
|
|
14394
|
+
z$1.array(publicWholeSeriesOfferingSchema);
|
|
14389
14395
|
//#endregion
|
|
14390
14396
|
//#region ../blocks/src/system/blocks/events/shared/schemas.ts
|
|
14391
14397
|
const eventPresetSchema = z$1.enum([
|
|
14392
14398
|
"event",
|
|
14393
14399
|
"class",
|
|
14400
|
+
"course",
|
|
14394
14401
|
"workshop",
|
|
14395
14402
|
"retreat",
|
|
14396
14403
|
"performance"
|
|
@@ -14657,7 +14664,7 @@ const publicTeamMemberSummarySchema = z$1.object({
|
|
|
14657
14664
|
* Zod schema for public event data
|
|
14658
14665
|
*/
|
|
14659
14666
|
const publicEventSchema = z$1.object({
|
|
14660
|
-
|
|
14667
|
+
bookingScope: z$1.enum(["single_occurrence", "whole_series"]),
|
|
14661
14668
|
eventPreset: eventPresetSchema.optional(),
|
|
14662
14669
|
eventDestinationMode: eventDestinationModeSchema.optional(),
|
|
14663
14670
|
scheduleScope: eventScheduleScopeSchema.optional(),
|
|
@@ -14705,34 +14712,14 @@ const publicEventSchema = z$1.object({
|
|
|
14705
14712
|
requireGuestDetails: z$1.boolean().optional(),
|
|
14706
14713
|
acceptsPasses: z$1.boolean().optional(),
|
|
14707
14714
|
acceptsMemberships: z$1.boolean().optional(),
|
|
14708
|
-
|
|
14709
|
-
|
|
14710
|
-
pricing: coursePricingSchema
|
|
14711
|
-
priceCents: z$1.number().nullable(),
|
|
14715
|
+
wholeSeries: z$1.object({
|
|
14716
|
+
eventSeriesId: z$1.string(),
|
|
14717
|
+
pricing: coursePricingSchema,
|
|
14712
14718
|
currency: z$1.string(),
|
|
14713
14719
|
enrollmentOpen: z$1.boolean()
|
|
14714
14720
|
}).nullable().optional()
|
|
14715
14721
|
});
|
|
14716
14722
|
z$1.array(publicEventSchema);
|
|
14717
|
-
//#endregion
|
|
14718
|
-
//#region ../blocks/src/system/constants/events.ts
|
|
14719
|
-
/**
|
|
14720
|
-
* Content type slugs that represent event content.
|
|
14721
|
-
* These are the standard slugs used when creating event content types in the CMS.
|
|
14722
|
-
*
|
|
14723
|
-
* Used by:
|
|
14724
|
-
* - Occurrence resolution to detect event pages
|
|
14725
|
-
* - Event Calendar block to identify event content
|
|
14726
|
-
* - Content type definitions
|
|
14727
|
-
*/
|
|
14728
|
-
const EVENT_CONTENT_TYPE_SLUGS = ["event", "events"];
|
|
14729
|
-
/**
|
|
14730
|
-
* Check if a content type slug represents an event type
|
|
14731
|
-
*/
|
|
14732
|
-
function isEventContentType(slug) {
|
|
14733
|
-
if (!slug) return false;
|
|
14734
|
-
return EVENT_CONTENT_TYPE_SLUGS.includes(slug);
|
|
14735
|
-
}
|
|
14736
14723
|
const unsupportedEventRegistrationPageSurfaceSubjectSchema = z$1.object({
|
|
14737
14724
|
kind: z$1.literal("unsupported"),
|
|
14738
14725
|
reason: z$1.enum([
|
|
@@ -14793,12 +14780,6 @@ function resolveEventRegistrationScope(context) {
|
|
|
14793
14780
|
kind: "unsupportedPageSurfaceSubject",
|
|
14794
14781
|
reason: context.subject.reason
|
|
14795
14782
|
};
|
|
14796
|
-
const entrySlug = context.contentEntry?.slug;
|
|
14797
|
-
const entryContentType = context.contentEntry?.contentTypeSlug;
|
|
14798
|
-
if (entrySlug && entryContentType && isEventContentType(entryContentType)) return {
|
|
14799
|
-
kind: "legacyEventSlug",
|
|
14800
|
-
slug: entrySlug
|
|
14801
|
-
};
|
|
14802
14783
|
return { kind: "unscoped" };
|
|
14803
14784
|
}
|
|
14804
14785
|
function applyEventRegistrationScope(events, scope) {
|
|
@@ -14809,7 +14790,6 @@ function applyEventRegistrationScope(events, scope) {
|
|
|
14809
14790
|
const seriesIds = new Set(scope.seriesIds);
|
|
14810
14791
|
return events.filter((event) => seriesIds.has(event.seriesId));
|
|
14811
14792
|
}
|
|
14812
|
-
case "legacyEventSlug": return events.filter((event) => event.slug === scope.slug);
|
|
14813
14793
|
case "unsupportedPageSurfaceSubject": return [];
|
|
14814
14794
|
case "unscoped": return [...events];
|
|
14815
14795
|
}
|
|
@@ -14859,7 +14839,6 @@ function getEventRegistrationOverrideInput(props) {
|
|
|
14859
14839
|
events,
|
|
14860
14840
|
...props.stage ? { stage: props.stage } : {},
|
|
14861
14841
|
...props.occurrenceContext ? { occurrenceContext: props.occurrenceContext } : {},
|
|
14862
|
-
...isEventRegistrationContentEntryLike(props.contentEntry) ? { contentEntry: props.contentEntry } : {},
|
|
14863
14842
|
...subject ? { subject } : {},
|
|
14864
14843
|
...content.maxTickets != null ? { maxTickets: content.maxTickets } : {},
|
|
14865
14844
|
...content.showVenue != null ? { showVenue: content.showVenue } : {},
|
|
@@ -14886,9 +14865,6 @@ function normalizePublicEventLike(value) {
|
|
|
14886
14865
|
const parsed = publicEventSchema.safeParse(candidate);
|
|
14887
14866
|
return parsed.success ? parsed.data : null;
|
|
14888
14867
|
}
|
|
14889
|
-
function isEventRegistrationContentEntryLike(value) {
|
|
14890
|
-
return isRecord(value) && typeof value.id === "string" && typeof value.slug === "string" && typeof value.contentTypeSlug === "string";
|
|
14891
|
-
}
|
|
14892
14868
|
//#endregion
|
|
14893
14869
|
//#region ../blocks/src/system/runtime/nodes/event-registration/event-registration.headless.planning.ts
|
|
14894
14870
|
function getRegistrableStatuses(isPreview) {
|
|
@@ -15228,16 +15204,13 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
15228
15204
|
const scopedEvents = useMemo(() => {
|
|
15229
15205
|
return resolveEventRegistrationScopedEvents(registrationEvents, {
|
|
15230
15206
|
occurrenceContext: options.occurrenceContext,
|
|
15231
|
-
subject: options.subject
|
|
15232
|
-
contentEntry: options.contentEntry
|
|
15207
|
+
subject: options.subject
|
|
15233
15208
|
});
|
|
15234
15209
|
}, [
|
|
15235
15210
|
registrationEvents,
|
|
15236
15211
|
options.occurrenceContext?.seriesId,
|
|
15237
15212
|
options.subject?.kind,
|
|
15238
|
-
options.subject?.kind === "eventSeries" ? options.subject.eventSeriesId : options.subject?.kind === "eventOffering" ? `${options.subject.eventOfferingId}:${options.subject.availableEventSeriesIds.join(",")}` : options.subject?.reason
|
|
15239
|
-
options.contentEntry?.slug,
|
|
15240
|
-
options.contentEntry?.contentTypeSlug
|
|
15213
|
+
options.subject?.kind === "eventSeries" ? options.subject.eventSeriesId : options.subject?.kind === "eventOffering" ? `${options.subject.eventOfferingId}:${options.subject.availableEventSeriesIds.join(",")}` : options.subject?.reason
|
|
15241
15214
|
]);
|
|
15242
15215
|
const preSelectedEvent = useMemo(() => findPreSelectedEvent({
|
|
15243
15216
|
scopedEvents,
|
|
@@ -15777,7 +15750,6 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
15777
15750
|
anchorId: options.anchorId,
|
|
15778
15751
|
occurrenceContext: options.occurrenceContext,
|
|
15779
15752
|
registrationTarget,
|
|
15780
|
-
contentEntry: options.contentEntry,
|
|
15781
15753
|
subject: options.subject,
|
|
15782
15754
|
events: options.events,
|
|
15783
15755
|
maxTicketsNum: waitlistClaim.claim ? 1 : options.maxTicketsNum,
|
|
@@ -16083,8 +16055,7 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
16083
16055
|
preSelected: wizard.preSelectedEvent,
|
|
16084
16056
|
hasPreSelectedContext: wizard.hasPreSelectedContext,
|
|
16085
16057
|
target: wizard.registrationTarget,
|
|
16086
|
-
occurrenceContext: wizard.occurrenceContext
|
|
16087
|
-
contentEntry: wizard.contentEntry
|
|
16058
|
+
occurrenceContext: wizard.occurrenceContext
|
|
16088
16059
|
},
|
|
16089
16060
|
tickets: {
|
|
16090
16061
|
count: wizard.ticketsCount,
|
|
@@ -16169,7 +16140,6 @@ function useEventRegistrationWizardControllerWithDeps(options, deps) {
|
|
|
16169
16140
|
return { wizard: deps.useEventRegistrationWizard({
|
|
16170
16141
|
anchorId: options.anchorId ?? "event-registration",
|
|
16171
16142
|
occurrenceContext: options.occurrenceContext ?? null,
|
|
16172
|
-
contentEntry: options.contentEntry ?? null,
|
|
16173
16143
|
events: [...options.events ?? []],
|
|
16174
16144
|
maxTicketsNum
|
|
16175
16145
|
}) };
|
|
@@ -16230,6 +16200,209 @@ function resolveHeadlessDirectPaymentOptions(wizard) {
|
|
|
16230
16200
|
}).options;
|
|
16231
16201
|
}
|
|
16232
16202
|
//#endregion
|
|
16203
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/utils.ts
|
|
16204
|
+
/**
|
|
16205
|
+
* Anchor ID for the registration block, used for scroll targeting.
|
|
16206
|
+
*/
|
|
16207
|
+
const COURSE_REGISTRATION_ANCHOR_ID = "course-registration";
|
|
16208
|
+
//#endregion
|
|
16209
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/pricing.ts
|
|
16210
|
+
function parseCurrencyInputToCents(value) {
|
|
16211
|
+
const trimmed = value.trim();
|
|
16212
|
+
if (!trimmed) return null;
|
|
16213
|
+
const amount = Number(trimmed);
|
|
16214
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
16215
|
+
return Math.round(amount * 100);
|
|
16216
|
+
}
|
|
16217
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
16218
|
+
const major = amount / 100;
|
|
16219
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
16220
|
+
}
|
|
16221
|
+
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
16222
|
+
if (pricing?.requiresSelection && !pricing.selectedOption) return pricing.slidingScale ? "Choose an amount to continue." : "Choose a pricing option to continue.";
|
|
16223
|
+
const selectedAmount = pricing?.selectedSlidingAmount;
|
|
16224
|
+
const scale = pricing?.slidingScale;
|
|
16225
|
+
if (scale && selectedAmount !== null && selectedAmount !== void 0 && (selectedAmount < scale.minAmount || selectedAmount > scale.maxAmount)) return "Choose an amount within the sliding scale.";
|
|
16226
|
+
return null;
|
|
16227
|
+
}
|
|
16228
|
+
function buildCoursePricingOptionPayload(pricing) {
|
|
16229
|
+
if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
|
|
16230
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
16231
|
+
return {};
|
|
16232
|
+
}
|
|
16233
|
+
function defaultCoursePricingSelection(pricing, previousOptionId) {
|
|
16234
|
+
return {
|
|
16235
|
+
pricingOptionId: previousOptionId && pricing.selectableOptions.some((option) => option.id === previousOptionId) ? previousOptionId : pricing.selectedOption?.id ?? null,
|
|
16236
|
+
slidingAmountInput: pricing.slidingScale?.suggestedAmount !== null && pricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(pricing.slidingScale.suggestedAmount) : ""
|
|
16237
|
+
};
|
|
16238
|
+
}
|
|
16239
|
+
//#endregion
|
|
16240
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/wizardSteps.ts
|
|
16241
|
+
/**
|
|
16242
|
+
* Step labels for the wizard indicator
|
|
16243
|
+
*/
|
|
16244
|
+
const STEP_LABELS = {
|
|
16245
|
+
"select-course": "Course",
|
|
16246
|
+
"enter-details": "Details",
|
|
16247
|
+
"booking-mode": "Method",
|
|
16248
|
+
"select-payment": "Payment",
|
|
16249
|
+
submitting: "Booking",
|
|
16250
|
+
redirecting: "Redirecting",
|
|
16251
|
+
"verifying-payment": "Verifying",
|
|
16252
|
+
"verifying-timeout": "Timeout",
|
|
16253
|
+
"payment-failed": "Failed",
|
|
16254
|
+
success: "Complete",
|
|
16255
|
+
waitlist: "Waitlist",
|
|
16256
|
+
error: "Error"
|
|
16257
|
+
};
|
|
16258
|
+
/**
|
|
16259
|
+
* Determine which wizard steps to show based on context and eligibility.
|
|
16260
|
+
*
|
|
16261
|
+
* @param hasPreSelectedCourse - Whether course is pre-selected (skips course selection)
|
|
16262
|
+
* @param requiresPayment - Whether the course requires payment
|
|
16263
|
+
* @param hasEligibleMemberships - Whether user has eligible memberships
|
|
16264
|
+
* @param bookingMode - Current booking mode selection
|
|
16265
|
+
* @param isMembershipFastTrack - Whether user qualifies for single-step membership flow
|
|
16266
|
+
* @returns Array of wizard steps to display
|
|
16267
|
+
*/
|
|
16268
|
+
function getWizardStepsForContext(hasPreSelectedCourse, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
|
|
16269
|
+
if (isMembershipFastTrack) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
|
|
16270
|
+
if (!requiresPayment) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
|
|
16271
|
+
if (hasEligibleMemberships) {
|
|
16272
|
+
const skipPayment = bookingMode === "membership";
|
|
16273
|
+
if (hasPreSelectedCourse) return skipPayment ? ["enter-details", "booking-mode"] : [
|
|
16274
|
+
"enter-details",
|
|
16275
|
+
"booking-mode",
|
|
16276
|
+
"select-payment"
|
|
16277
|
+
];
|
|
16278
|
+
return skipPayment ? [
|
|
16279
|
+
"select-course",
|
|
16280
|
+
"enter-details",
|
|
16281
|
+
"booking-mode"
|
|
16282
|
+
] : [
|
|
16283
|
+
"select-course",
|
|
16284
|
+
"enter-details",
|
|
16285
|
+
"booking-mode",
|
|
16286
|
+
"select-payment"
|
|
16287
|
+
];
|
|
16288
|
+
}
|
|
16289
|
+
return hasPreSelectedCourse ? ["enter-details", "select-payment"] : [
|
|
16290
|
+
"select-course",
|
|
16291
|
+
"enter-details",
|
|
16292
|
+
"select-payment"
|
|
16293
|
+
];
|
|
16294
|
+
}
|
|
16295
|
+
/**
|
|
16296
|
+
* Get labels for a list of wizard steps
|
|
16297
|
+
*/
|
|
16298
|
+
function getStepLabels(steps) {
|
|
16299
|
+
return steps.map((step) => STEP_LABELS[step] ?? step);
|
|
16300
|
+
}
|
|
16301
|
+
//#endregion
|
|
16302
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/courseRegistrationViewState.ts
|
|
16303
|
+
function deriveCourseRegistrationViewState(input) {
|
|
16304
|
+
const hasCoursePayment = resolveCoursePaymentRequirement(input.pricing);
|
|
16305
|
+
const canUseMembership = hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
|
|
16306
|
+
const hasPreSelectedCourse = input.scopedCourses.length === 1;
|
|
16307
|
+
const fastTrack = canUseMembership && input.eligibleMembershipCount === 1 && input.bookingMode === "membership";
|
|
16308
|
+
const wizardSteps = getWizardStepsForContext(hasPreSelectedCourse, hasCoursePayment, canUseMembership, input.bookingMode, fastTrack);
|
|
16309
|
+
const showPortalAuthSidebar = shouldShowPortalAuthSidebar({
|
|
16310
|
+
...input,
|
|
16311
|
+
hasCoursePayment
|
|
16312
|
+
});
|
|
16313
|
+
return {
|
|
16314
|
+
hasCoursePayment,
|
|
16315
|
+
canUseMembership,
|
|
16316
|
+
hasPreSelectedCourse,
|
|
16317
|
+
wizardSteps,
|
|
16318
|
+
currentStepNumber: getStepNumber(input.step, wizardSteps),
|
|
16319
|
+
totalSteps: wizardSteps.length,
|
|
16320
|
+
stepLabels: getStepLabels(wizardSteps),
|
|
16321
|
+
showPortalAuthSidebar
|
|
16322
|
+
};
|
|
16323
|
+
}
|
|
16324
|
+
function resolveCoursePaymentRequirement(pricing) {
|
|
16325
|
+
if (!pricing) return false;
|
|
16326
|
+
return pricing.selectedOption ? pricing.selectedRequiresPayment : pricing.hasPaidSelection;
|
|
16327
|
+
}
|
|
16328
|
+
function shouldShowPortalAuthSidebar(input) {
|
|
16329
|
+
if (input.portalAuthState !== "unauthenticated") return false;
|
|
16330
|
+
if (input.step === "success" || input.step === "waitlist" || input.step === "error") return false;
|
|
16331
|
+
return input.waitlistRequiresPortalLogin || input.hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.step !== "select-course";
|
|
16332
|
+
}
|
|
16333
|
+
//#endregion
|
|
16334
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseEligibility.ts
|
|
16335
|
+
function shouldFetchEligibility(input) {
|
|
16336
|
+
if (!input.course || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
|
|
16337
|
+
const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.course.acceptsMemberships;
|
|
16338
|
+
const capacityCheck = input.course.availableSpots !== null && input.course.availableSpots <= 0;
|
|
16339
|
+
return membershipCheck || capacityCheck;
|
|
16340
|
+
}
|
|
16341
|
+
function useCourseEligibility(input) {
|
|
16342
|
+
const [loading, setLoading] = useState(false);
|
|
16343
|
+
const [error, setError] = useState(null);
|
|
16344
|
+
const [eligibility, setEligibility] = useState(null);
|
|
16345
|
+
const [memberships, setMemberships] = useState([]);
|
|
16346
|
+
const [paymentChoice, setPaymentChoice] = useState("checkout");
|
|
16347
|
+
const [selectedMembershipId, setSelectedMembershipId] = useState(null);
|
|
16348
|
+
const choosePaymentChoice = useCallback((choice) => {
|
|
16349
|
+
setPaymentChoice(choice);
|
|
16350
|
+
}, []);
|
|
16351
|
+
const chooseMembership = useCallback((membershipId) => {
|
|
16352
|
+
setSelectedMembershipId(membershipId);
|
|
16353
|
+
}, []);
|
|
16354
|
+
useEffect(() => {
|
|
16355
|
+
let cancelled = false;
|
|
16356
|
+
setEligibility(null);
|
|
16357
|
+
setMemberships([]);
|
|
16358
|
+
setSelectedMembershipId(null);
|
|
16359
|
+
setError(null);
|
|
16360
|
+
setPaymentChoice("checkout");
|
|
16361
|
+
const eligibilityInput = {
|
|
16362
|
+
course: input.selectedCourse,
|
|
16363
|
+
hasPaidSelection: input.hasPaidSelection,
|
|
16364
|
+
portalAuthState: input.portalAuthState,
|
|
16365
|
+
hasWaitlistClaimToken: input.waitlistClaimToken !== null
|
|
16366
|
+
};
|
|
16367
|
+
if (!shouldFetchEligibility(eligibilityInput)) return;
|
|
16368
|
+
const course = eligibilityInput.course;
|
|
16369
|
+
setLoading(true);
|
|
16370
|
+
input.api.checkWholeSeriesEligibility({ eventSeriesId: course.eventSeriesId }).then((result) => {
|
|
16371
|
+
if (cancelled) return;
|
|
16372
|
+
const eligibleMemberships = result.eligibleMemberships ?? [];
|
|
16373
|
+
setEligibility(result);
|
|
16374
|
+
setMemberships(eligibleMemberships);
|
|
16375
|
+
if (input.portalAuthState === "authenticated" && eligibleMemberships.length > 0) {
|
|
16376
|
+
setPaymentChoice("membership");
|
|
16377
|
+
if (eligibleMemberships.length === 1) setSelectedMembershipId(eligibleMemberships[0]?.customerMembershipId ?? null);
|
|
16378
|
+
}
|
|
16379
|
+
}).catch((cause) => {
|
|
16380
|
+
if (!cancelled) setError(cause instanceof Error ? cause.message : "Failed to check membership eligibility");
|
|
16381
|
+
}).finally(() => {
|
|
16382
|
+
if (!cancelled) setLoading(false);
|
|
16383
|
+
});
|
|
16384
|
+
return () => {
|
|
16385
|
+
cancelled = true;
|
|
16386
|
+
};
|
|
16387
|
+
}, [
|
|
16388
|
+
input.api,
|
|
16389
|
+
input.hasPaidSelection,
|
|
16390
|
+
input.portalAuthState,
|
|
16391
|
+
input.selectedCourse,
|
|
16392
|
+
input.waitlistClaimToken
|
|
16393
|
+
]);
|
|
16394
|
+
return {
|
|
16395
|
+
eligibilityLoading: loading,
|
|
16396
|
+
eligibilityError: error,
|
|
16397
|
+
courseEligibility: eligibility,
|
|
16398
|
+
eligibleMemberships: memberships,
|
|
16399
|
+
paymentChoice,
|
|
16400
|
+
choosePaymentChoice,
|
|
16401
|
+
selectedMembershipId,
|
|
16402
|
+
chooseMembership
|
|
16403
|
+
};
|
|
16404
|
+
}
|
|
16405
|
+
//#endregion
|
|
16233
16406
|
//#region ../blocks/src/system/blocks/courses/shared/pricing.ts
|
|
16234
16407
|
function isSaleWindowOpen(option, now) {
|
|
16235
16408
|
if (!option.isActive) return false;
|
|
@@ -16249,7 +16422,7 @@ function toExactOrFreeDisplay(amount, currency) {
|
|
|
16249
16422
|
};
|
|
16250
16423
|
}
|
|
16251
16424
|
function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
16252
|
-
if (
|
|
16425
|
+
if (course.pricing.pricingStrategy !== "tiered") return [];
|
|
16253
16426
|
return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
|
|
16254
16427
|
if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
|
|
16255
16428
|
if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
|
|
@@ -16259,23 +16432,7 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
16259
16432
|
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
16260
16433
|
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
16261
16434
|
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
16262
|
-
const currency = course.pricing
|
|
16263
|
-
if (!course.pricing) {
|
|
16264
|
-
const legacyAmount = course.priceCents ?? 0;
|
|
16265
|
-
return {
|
|
16266
|
-
currency,
|
|
16267
|
-
display: toExactOrFreeDisplay(legacyAmount, currency),
|
|
16268
|
-
selectableOptions: [],
|
|
16269
|
-
requiresSelection: false,
|
|
16270
|
-
selectedOption: null,
|
|
16271
|
-
slidingScale: null,
|
|
16272
|
-
selectedSlidingAmount: null,
|
|
16273
|
-
selectedPriceAmount: legacyAmount,
|
|
16274
|
-
selectedRequiresPayment: legacyAmount > 0,
|
|
16275
|
-
hasPaidSelection: legacyAmount > 0,
|
|
16276
|
-
hasFreeSelection: legacyAmount <= 0
|
|
16277
|
-
};
|
|
16278
|
-
}
|
|
16435
|
+
const currency = course.pricing.currency;
|
|
16279
16436
|
switch (course.pricing.pricingStrategy) {
|
|
16280
16437
|
case "free": return {
|
|
16281
16438
|
currency,
|
|
@@ -16383,74 +16540,6 @@ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlid
|
|
|
16383
16540
|
}
|
|
16384
16541
|
}
|
|
16385
16542
|
//#endregion
|
|
16386
|
-
//#region ../blocks/src/system/runtime/nodes/course-registration/utils.ts
|
|
16387
|
-
/**
|
|
16388
|
-
* Anchor ID for the registration block, used for scroll targeting.
|
|
16389
|
-
*/
|
|
16390
|
-
const COURSE_REGISTRATION_ANCHOR_ID = "course-registration";
|
|
16391
|
-
//#endregion
|
|
16392
|
-
//#region ../blocks/src/system/runtime/nodes/course-registration/wizardSteps.ts
|
|
16393
|
-
/**
|
|
16394
|
-
* Step labels for the wizard indicator
|
|
16395
|
-
*/
|
|
16396
|
-
const STEP_LABELS = {
|
|
16397
|
-
"select-course": "Course",
|
|
16398
|
-
"enter-details": "Details",
|
|
16399
|
-
"booking-mode": "Method",
|
|
16400
|
-
"select-payment": "Payment",
|
|
16401
|
-
submitting: "Booking",
|
|
16402
|
-
redirecting: "Redirecting",
|
|
16403
|
-
"verifying-payment": "Verifying",
|
|
16404
|
-
"verifying-timeout": "Timeout",
|
|
16405
|
-
"payment-failed": "Failed",
|
|
16406
|
-
success: "Complete",
|
|
16407
|
-
waitlist: "Waitlist",
|
|
16408
|
-
error: "Error"
|
|
16409
|
-
};
|
|
16410
|
-
/**
|
|
16411
|
-
* Determine which wizard steps to show based on context and eligibility.
|
|
16412
|
-
*
|
|
16413
|
-
* @param hasPreSelectedCourse - Whether course is pre-selected (skips course selection)
|
|
16414
|
-
* @param requiresPayment - Whether the course requires payment
|
|
16415
|
-
* @param hasEligibleMemberships - Whether user has eligible memberships
|
|
16416
|
-
* @param bookingMode - Current booking mode selection
|
|
16417
|
-
* @param isMembershipFastTrack - Whether user qualifies for single-step membership flow
|
|
16418
|
-
* @returns Array of wizard steps to display
|
|
16419
|
-
*/
|
|
16420
|
-
function getWizardStepsForContext(hasPreSelectedCourse, requiresPayment, hasEligibleMemberships, bookingMode, isMembershipFastTrack) {
|
|
16421
|
-
if (isMembershipFastTrack) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
|
|
16422
|
-
if (!requiresPayment) return hasPreSelectedCourse ? ["enter-details"] : ["select-course", "enter-details"];
|
|
16423
|
-
if (hasEligibleMemberships) {
|
|
16424
|
-
const skipPayment = bookingMode === "membership";
|
|
16425
|
-
if (hasPreSelectedCourse) return skipPayment ? ["enter-details", "booking-mode"] : [
|
|
16426
|
-
"enter-details",
|
|
16427
|
-
"booking-mode",
|
|
16428
|
-
"select-payment"
|
|
16429
|
-
];
|
|
16430
|
-
return skipPayment ? [
|
|
16431
|
-
"select-course",
|
|
16432
|
-
"enter-details",
|
|
16433
|
-
"booking-mode"
|
|
16434
|
-
] : [
|
|
16435
|
-
"select-course",
|
|
16436
|
-
"enter-details",
|
|
16437
|
-
"booking-mode",
|
|
16438
|
-
"select-payment"
|
|
16439
|
-
];
|
|
16440
|
-
}
|
|
16441
|
-
return hasPreSelectedCourse ? ["enter-details", "select-payment"] : [
|
|
16442
|
-
"select-course",
|
|
16443
|
-
"enter-details",
|
|
16444
|
-
"select-payment"
|
|
16445
|
-
];
|
|
16446
|
-
}
|
|
16447
|
-
/**
|
|
16448
|
-
* Get labels for a list of wizard steps
|
|
16449
|
-
*/
|
|
16450
|
-
function getStepLabels(steps) {
|
|
16451
|
-
return steps.map((step) => STEP_LABELS[step] ?? step);
|
|
16452
|
-
}
|
|
16453
|
-
//#endregion
|
|
16454
16543
|
//#region ../blocks/src/system/runtime/nodes/course-page-surface-scope.ts
|
|
16455
16544
|
/**
|
|
16456
16545
|
* Resolves native course-page ownership without falling back to entry or slug
|
|
@@ -16468,7 +16557,7 @@ function resolveCoursePageSurfaceScope(courses, subjectValue) {
|
|
|
16468
16557
|
return {
|
|
16469
16558
|
kind: "scoped",
|
|
16470
16559
|
subject: parsed.value,
|
|
16471
|
-
courses: courses.filter((course) => allowedSeriesIds.has(course.
|
|
16560
|
+
courses: courses.filter((course) => allowedSeriesIds.has(course.eventSeriesId))
|
|
16472
16561
|
};
|
|
16473
16562
|
}
|
|
16474
16563
|
function eventSeriesIdsForSubject(subject) {
|
|
@@ -16479,654 +16568,504 @@ function eventSeriesIdsForSubject(subject) {
|
|
|
16479
16568
|
}
|
|
16480
16569
|
}
|
|
16481
16570
|
//#endregion
|
|
16482
|
-
//#region ../blocks/src/system/runtime/nodes/course-registration/
|
|
16483
|
-
function
|
|
16484
|
-
const
|
|
16485
|
-
if (
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
return Math.round(amount * 100);
|
|
16489
|
-
}
|
|
16490
|
-
function formatCentsAsCurrencyInput(amount) {
|
|
16491
|
-
const major = amount / 100;
|
|
16492
|
-
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
16493
|
-
}
|
|
16494
|
-
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
16495
|
-
if (!course || portalAuthState === "checking") return false;
|
|
16496
|
-
if (hasWaitlistClaimToken) return false;
|
|
16497
|
-
const needsMembershipEligibility = portalAuthState === "authenticated" && hasPaidSelection && course.acceptsMemberships;
|
|
16498
|
-
const needsWaitlistAvailabilityCheck = course.availableSpots !== null && course.availableSpots <= 0;
|
|
16499
|
-
return needsMembershipEligibility || needsWaitlistAvailabilityCheck;
|
|
16571
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.ts
|
|
16572
|
+
function selectScopedCourses(props) {
|
|
16573
|
+
const surfaceScope = resolveCoursePageSurfaceScope(props.courses ?? [], props.subject);
|
|
16574
|
+
if (surfaceScope.kind === "unsupported") return [];
|
|
16575
|
+
if (surfaceScope.kind === "scoped") return surfaceScope.courses;
|
|
16576
|
+
return [];
|
|
16500
16577
|
}
|
|
16501
|
-
|
|
16502
|
-
* Extracts session_id from URL, checking both query params and hash fragment.
|
|
16503
|
-
*
|
|
16504
|
-
* Stripe appends session_id to the success URL, but if our URL contains a hash
|
|
16505
|
-
* (e.g., #course-registration), Stripe ends up appending session_id after the hash:
|
|
16506
|
-
* Expected: ?enrollment=success&session_id=cs_test_...#course-registration
|
|
16507
|
-
* Actual: ?enrollment=success#course-registration&session_id=cs_test_...
|
|
16508
|
-
*
|
|
16509
|
-
* This helper checks both locations to handle this edge case.
|
|
16510
|
-
*/
|
|
16511
|
-
function getSessionIdFromUrl() {
|
|
16578
|
+
function getCourseCheckoutSessionId() {
|
|
16512
16579
|
const fromSearch = new URLSearchParams(window.location.search).get("session_id");
|
|
16513
16580
|
if (fromSearch) return fromSearch;
|
|
16514
16581
|
return window.location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
|
|
16515
16582
|
}
|
|
16516
|
-
function
|
|
16517
|
-
if (
|
|
16518
|
-
|
|
16519
|
-
return "Choose a pricing option to continue.";
|
|
16520
|
-
}
|
|
16521
|
-
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) return "Choose an amount within the sliding scale.";
|
|
16522
|
-
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) return "Choose an amount within the sliding scale.";
|
|
16523
|
-
return null;
|
|
16524
|
-
}
|
|
16525
|
-
function buildCoursePricingOptionPayload(pricing) {
|
|
16526
|
-
if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
|
|
16527
|
-
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
16528
|
-
return {};
|
|
16529
|
-
}
|
|
16530
|
-
function resolveHasCoursePayment(pricing) {
|
|
16531
|
-
if (!pricing) return false;
|
|
16532
|
-
if (pricing.selectedOption) return pricing.selectedRequiresPayment;
|
|
16533
|
-
return pricing.hasPaidSelection;
|
|
16583
|
+
function initialStep(courses) {
|
|
16584
|
+
if (new URLSearchParams(window.location.search).get("enrollment") === "success" && getCourseCheckoutSessionId()) return "verifying-payment";
|
|
16585
|
+
return courses.length === 1 ? "enter-details" : "select-course";
|
|
16534
16586
|
}
|
|
16535
|
-
function
|
|
16536
|
-
const
|
|
16537
|
-
const
|
|
16538
|
-
const scopedCourses = useMemo(() => {
|
|
16539
|
-
const allCourses = courses ?? [];
|
|
16540
|
-
if (entrySubrouteContext?.kind === "course-run") {
|
|
16541
|
-
const matched = allCourses.find((c) => c.id === entrySubrouteContext.run.courseId) ?? null;
|
|
16542
|
-
if (matched) return [matched];
|
|
16543
|
-
}
|
|
16544
|
-
const pageSurfaceScope = resolveCoursePageSurfaceScope(allCourses, subject);
|
|
16545
|
-
if (pageSurfaceScope.kind === "unsupported") return [];
|
|
16546
|
-
if (pageSurfaceScope.kind === "scoped") return [...pageSurfaceScope.courses];
|
|
16547
|
-
if (contentEntry?.id) {
|
|
16548
|
-
const matchedCourses = allCourses.filter((c) => c.contentEntryId === contentEntry.id);
|
|
16549
|
-
if (matchedCourses.length > 0) return matchedCourses;
|
|
16550
|
-
}
|
|
16551
|
-
if (contentEntry?.slug) {
|
|
16552
|
-
const matchedCourse = allCourses.find((c) => c.slug === contentEntry.slug);
|
|
16553
|
-
if (matchedCourse) return [matchedCourse];
|
|
16554
|
-
}
|
|
16555
|
-
return allCourses;
|
|
16556
|
-
}, [
|
|
16557
|
-
courses,
|
|
16558
|
-
contentEntry?.id,
|
|
16559
|
-
contentEntry?.slug,
|
|
16560
|
-
entrySubrouteContext,
|
|
16561
|
-
subject
|
|
16562
|
-
]);
|
|
16563
|
-
const [step, setStep] = useState(() => {
|
|
16564
|
-
const enrollment = new URLSearchParams(window.location.search).get("enrollment");
|
|
16565
|
-
const sessionId = getSessionIdFromUrl();
|
|
16566
|
-
if (enrollment === "success" && sessionId) return "verifying-payment";
|
|
16567
|
-
return scopedCourses.length === 1 ? "enter-details" : "select-course";
|
|
16568
|
-
});
|
|
16587
|
+
function useCourseRegistrationSelection(props) {
|
|
16588
|
+
const scopedCourses = useMemo(() => selectScopedCourses(props), [props.courses, props.subject]);
|
|
16589
|
+
const [step, setStep] = useState(() => initialStep(scopedCourses));
|
|
16569
16590
|
const [selectedCourse, setSelectedCourse] = useState(scopedCourses.length === 1 ? scopedCourses[0] ?? null : null);
|
|
16570
16591
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
|
|
16571
16592
|
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
|
|
16572
|
-
const
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
});
|
|
16578
|
-
const
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
const
|
|
16582
|
-
|
|
16583
|
-
|
|
16584
|
-
const [eligibilityLoading, setEligibilityLoading] = useState(false);
|
|
16585
|
-
const [eligibilityError, setEligibilityError] = useState(null);
|
|
16586
|
-
const [courseEligibility, setCourseEligibility] = useState(null);
|
|
16587
|
-
const [eligibleMemberships, setEligibleMemberships] = useState([]);
|
|
16588
|
-
const [paymentChoice, setPaymentChoice] = useState("checkout");
|
|
16589
|
-
const [selectedMembershipId, setSelectedMembershipId] = useState(null);
|
|
16590
|
-
const [bookingMode, setBookingMode] = useState(null);
|
|
16591
|
-
const waitlistClaim = useWaitlistClaim();
|
|
16593
|
+
const goToStep = useCallback((nextStep) => {
|
|
16594
|
+
setStep(nextStep);
|
|
16595
|
+
}, []);
|
|
16596
|
+
const chooseCourse = useCallback((course) => {
|
|
16597
|
+
setSelectedCourse(course);
|
|
16598
|
+
}, []);
|
|
16599
|
+
const choosePricingOption = useCallback((pricingOptionId) => {
|
|
16600
|
+
setSelectedPricingOptionId(pricingOptionId);
|
|
16601
|
+
}, []);
|
|
16602
|
+
const changeSlidingAmount = useCallback((amount) => {
|
|
16603
|
+
setSelectedSlidingAmountInput(amount);
|
|
16604
|
+
}, []);
|
|
16592
16605
|
const selectedCoursePricing = useMemo(() => selectedCourse ? resolveCoursePricingState(selectedCourse, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
|
|
16593
16606
|
selectedCourse,
|
|
16594
16607
|
selectedPricingOptionId,
|
|
16595
16608
|
selectedSlidingAmountInput
|
|
16596
16609
|
]);
|
|
16597
|
-
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(selectedCoursePricing);
|
|
16598
|
-
const selectedCoursePricingPayload = buildCoursePricingOptionPayload(selectedCoursePricing);
|
|
16599
|
-
const showSoldOutCourseError = () => {
|
|
16600
|
-
setErrorMessage(courseEligibility?.reason ?? "This course is fully booked.");
|
|
16601
|
-
setStep("error");
|
|
16602
|
-
return true;
|
|
16603
|
-
};
|
|
16604
|
-
useEffect(() => {
|
|
16605
|
-
let cancelled = false;
|
|
16606
|
-
async function checkPortalAuth() {
|
|
16607
|
-
if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
|
|
16608
|
-
setPortalAuthState("unauthenticated");
|
|
16609
|
-
return;
|
|
16610
|
-
}
|
|
16611
|
-
setPortalAuthState("checking");
|
|
16612
|
-
try {
|
|
16613
|
-
const me = await api.getPortalProfile();
|
|
16614
|
-
if (cancelled) return;
|
|
16615
|
-
setPortalAuthState("authenticated");
|
|
16616
|
-
setFormData((prev) => ({
|
|
16617
|
-
...prev,
|
|
16618
|
-
email: me.profile.email,
|
|
16619
|
-
name: prev.name || me.profile.name,
|
|
16620
|
-
phone: prev.phone || me.profile.phone || ""
|
|
16621
|
-
}));
|
|
16622
|
-
} catch {
|
|
16623
|
-
if (cancelled) return;
|
|
16624
|
-
setPortalAuthState("unauthenticated");
|
|
16625
|
-
}
|
|
16626
|
-
}
|
|
16627
|
-
checkPortalAuth();
|
|
16628
|
-
return () => {
|
|
16629
|
-
cancelled = true;
|
|
16630
|
-
};
|
|
16631
|
-
}, [api]);
|
|
16632
|
-
useEffect(() => {
|
|
16633
|
-
const claim = waitlistClaim.claim;
|
|
16634
|
-
if (!claim || claim.subject.kind !== "course") return;
|
|
16635
|
-
const courseId = claim.subject.courseId;
|
|
16636
|
-
const matchedCourse = scopedCourses.find((course) => course.id === courseId) ?? null;
|
|
16637
|
-
if (!matchedCourse) {
|
|
16638
|
-
setErrorMessage("This waitlist claim is for a different course.");
|
|
16639
|
-
setStep("error");
|
|
16640
|
-
return;
|
|
16641
|
-
}
|
|
16642
|
-
setSelectedCourse(matchedCourse);
|
|
16643
|
-
setFormData((prev) => ({
|
|
16644
|
-
...prev,
|
|
16645
|
-
email: claim.prefill.email,
|
|
16646
|
-
name: claim.prefill.name,
|
|
16647
|
-
phone: claim.prefill.phone ?? "",
|
|
16648
|
-
notes: claim.prefill.notes ?? ""
|
|
16649
|
-
}));
|
|
16650
|
-
if (step === "select-course") setStep("enter-details");
|
|
16651
|
-
}, [
|
|
16652
|
-
waitlistClaim.claim,
|
|
16653
|
-
scopedCourses,
|
|
16654
|
-
step
|
|
16655
|
-
]);
|
|
16656
|
-
useEffect(() => {
|
|
16657
|
-
if (waitlistClaim.requiresPortalLogin) return;
|
|
16658
|
-
if (!waitlistClaim.error) return;
|
|
16659
|
-
setErrorMessage(waitlistClaim.error);
|
|
16660
|
-
setStep("error");
|
|
16661
|
-
}, [waitlistClaim.error, waitlistClaim.requiresPortalLogin]);
|
|
16662
16610
|
useEffect(() => {
|
|
16663
16611
|
if (!selectedCourse) {
|
|
16664
16612
|
setSelectedPricingOptionId(null);
|
|
16665
16613
|
setSelectedSlidingAmountInput("");
|
|
16666
16614
|
return;
|
|
16667
16615
|
}
|
|
16668
|
-
const
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) return previous;
|
|
16672
|
-
return defaultPricing.selectedOption?.id ?? null;
|
|
16673
|
-
});
|
|
16616
|
+
const selection = defaultCoursePricingSelection(resolveCoursePricingState(selectedCourse, null), selectedPricingOptionId);
|
|
16617
|
+
setSelectedPricingOptionId(selection.pricingOptionId);
|
|
16618
|
+
setSelectedSlidingAmountInput(selection.slidingAmountInput);
|
|
16674
16619
|
}, [selectedCourse]);
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16620
|
+
return {
|
|
16621
|
+
scopedCourses,
|
|
16622
|
+
step,
|
|
16623
|
+
goToStep,
|
|
16624
|
+
selectedCourse,
|
|
16625
|
+
chooseCourse,
|
|
16626
|
+
selectedPricingOptionId,
|
|
16627
|
+
choosePricingOption,
|
|
16628
|
+
selectedSlidingAmountInput,
|
|
16629
|
+
changeSlidingAmount,
|
|
16630
|
+
selectedCoursePricing
|
|
16631
|
+
};
|
|
16632
|
+
}
|
|
16633
|
+
//#endregion
|
|
16634
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.ts
|
|
16635
|
+
function applyTerminalStatus(status, setters) {
|
|
16636
|
+
if (status === "enrolled" || status === "completed") {
|
|
16637
|
+
setters.setEnrollmentResult({
|
|
16638
|
+
status: "enrolled",
|
|
16639
|
+
usedMembership: false
|
|
16640
|
+
});
|
|
16641
|
+
setters.setStep("success");
|
|
16642
|
+
return true;
|
|
16643
|
+
}
|
|
16644
|
+
if (status === "waitlist") {
|
|
16645
|
+
setters.setEnrollmentResult({
|
|
16646
|
+
status: "waitlist",
|
|
16647
|
+
usedMembership: false
|
|
16648
|
+
});
|
|
16649
|
+
setters.setStep("waitlist");
|
|
16650
|
+
return true;
|
|
16651
|
+
}
|
|
16652
|
+
setters.setErrorMessage("Payment did not complete. Please try again.");
|
|
16653
|
+
setters.setStep("error");
|
|
16654
|
+
return true;
|
|
16655
|
+
}
|
|
16656
|
+
async function pollCourseRegistrationStatus(api, sessionId, setters, isCancelled) {
|
|
16657
|
+
const startedAt = Date.now();
|
|
16658
|
+
while (!isCancelled()) {
|
|
16659
|
+
try {
|
|
16660
|
+
const result = await api.getWholeSeriesRegistrationStatus({ sessionId });
|
|
16661
|
+
if (isCancelled()) return;
|
|
16662
|
+
if (result.status !== "pending_payment") {
|
|
16663
|
+
applyTerminalStatus(result.status, setters);
|
|
16664
|
+
return;
|
|
16702
16665
|
}
|
|
16666
|
+
} catch (cause) {
|
|
16667
|
+
setters.setErrorMessage(cause instanceof Error ? cause.message : "Failed to verify payment");
|
|
16703
16668
|
}
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
waitlistClaim.token
|
|
16714
|
-
]);
|
|
16669
|
+
if (Date.now() - startedAt > 3e4) {
|
|
16670
|
+
setters.setErrorMessage("Payment is still processing. Please check your email for confirmation.");
|
|
16671
|
+
setters.setStep("error");
|
|
16672
|
+
return;
|
|
16673
|
+
}
|
|
16674
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
16675
|
+
}
|
|
16676
|
+
}
|
|
16677
|
+
function useCoursePaymentVerification(api, setters) {
|
|
16715
16678
|
useEffect(() => {
|
|
16716
16679
|
let cancelled = false;
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
if (enrollment === "cancelled") {
|
|
16721
|
-
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
16722
|
-
setErrorMessage("Payment was cancelled. You can try again.");
|
|
16723
|
-
setStep("error");
|
|
16724
|
-
return;
|
|
16725
|
-
}
|
|
16726
|
-
if (enrollment !== "success" || !sessionId) return;
|
|
16680
|
+
const enrollment = new URLSearchParams(window.location.search).get("enrollment");
|
|
16681
|
+
const sessionId = getCourseCheckoutSessionId();
|
|
16682
|
+
if (enrollment === "cancelled") {
|
|
16727
16683
|
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
while (!cancelled) {
|
|
16732
|
-
try {
|
|
16733
|
-
const status = await api.getCourseRegistrationStatus({ sessionId });
|
|
16734
|
-
if (cancelled) return;
|
|
16735
|
-
if (status.status === "enrolled" || status.status === "completed") {
|
|
16736
|
-
setEnrollmentResult({
|
|
16737
|
-
status: "enrolled",
|
|
16738
|
-
usedMembership: false
|
|
16739
|
-
});
|
|
16740
|
-
setStep("success");
|
|
16741
|
-
return;
|
|
16742
|
-
}
|
|
16743
|
-
if (status.status === "waitlist") {
|
|
16744
|
-
setEnrollmentResult({
|
|
16745
|
-
status: "waitlist",
|
|
16746
|
-
usedMembership: false
|
|
16747
|
-
});
|
|
16748
|
-
setStep("waitlist");
|
|
16749
|
-
return;
|
|
16750
|
-
}
|
|
16751
|
-
if (status.status === "cancelled") {
|
|
16752
|
-
setErrorMessage("Payment did not complete. Please try again.");
|
|
16753
|
-
setStep("error");
|
|
16754
|
-
return;
|
|
16755
|
-
}
|
|
16756
|
-
} catch (error) {
|
|
16757
|
-
setErrorMessage(error instanceof Error ? error.message : "Failed to verify payment");
|
|
16758
|
-
}
|
|
16759
|
-
if (Date.now() - startedAt > timeoutMs) {
|
|
16760
|
-
setErrorMessage("Payment is still processing. Please check your email for confirmation.");
|
|
16761
|
-
setStep("error");
|
|
16762
|
-
return;
|
|
16763
|
-
}
|
|
16764
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
16765
|
-
}
|
|
16684
|
+
setters.setErrorMessage("Payment was cancelled. You can try again.");
|
|
16685
|
+
setters.setStep("error");
|
|
16686
|
+
return;
|
|
16766
16687
|
}
|
|
16767
|
-
|
|
16688
|
+
if (enrollment !== "success" || !sessionId) return;
|
|
16689
|
+
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
16690
|
+
setters.setStep("verifying-payment");
|
|
16691
|
+
pollCourseRegistrationStatus(api, sessionId, setters, () => cancelled);
|
|
16768
16692
|
return () => {
|
|
16769
16693
|
cancelled = true;
|
|
16770
16694
|
};
|
|
16771
|
-
}, [
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16695
|
+
}, [
|
|
16696
|
+
api,
|
|
16697
|
+
setters.setEnrollmentResult,
|
|
16698
|
+
setters.setErrorMessage,
|
|
16699
|
+
setters.setStep
|
|
16700
|
+
]);
|
|
16701
|
+
}
|
|
16702
|
+
//#endregion
|
|
16703
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.ts
|
|
16704
|
+
function blocked(message, setters) {
|
|
16705
|
+
setters.setErrorMessage(message);
|
|
16706
|
+
setters.setStep("error");
|
|
16707
|
+
return {
|
|
16708
|
+
kind: "blocked",
|
|
16709
|
+
message
|
|
16776
16710
|
};
|
|
16777
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16711
|
+
}
|
|
16712
|
+
function validateSubmission(state, setters) {
|
|
16713
|
+
if (!state.selectedCourse) return {
|
|
16714
|
+
kind: "blocked",
|
|
16715
|
+
message: "Choose an available set of dates to continue."
|
|
16780
16716
|
};
|
|
16781
|
-
const
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
}
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16717
|
+
const errors = validateFormData$1(state.formData);
|
|
16718
|
+
setters.setErrors(errors);
|
|
16719
|
+
if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
|
|
16720
|
+
const pricingMessage = getMissingCoursePricingSelectionMessage(state.pricing);
|
|
16721
|
+
if (pricingMessage) return blocked(pricingMessage, setters);
|
|
16722
|
+
if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This course is fully booked.", setters);
|
|
16723
|
+
if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
|
|
16724
|
+
return null;
|
|
16725
|
+
}
|
|
16726
|
+
function enrollmentPayload(state, payment) {
|
|
16727
|
+
return {
|
|
16728
|
+
...registrantPayload(state),
|
|
16729
|
+
paymentMethod: payment.method,
|
|
16730
|
+
...payment.method === "membership" ? { customerMembershipId: payment.membershipId } : {}
|
|
16731
|
+
};
|
|
16732
|
+
}
|
|
16733
|
+
function registrantPayload(state) {
|
|
16734
|
+
return {
|
|
16735
|
+
eventSeriesId: state.selectedCourse.eventSeriesId,
|
|
16736
|
+
...buildCoursePricingOptionPayload(state.pricing),
|
|
16737
|
+
email: state.formData.email.trim().toLowerCase(),
|
|
16738
|
+
name: state.formData.name.trim(),
|
|
16739
|
+
phone: state.formData.phone.trim() || void 0,
|
|
16740
|
+
formData: { notes: state.formData.notes.trim() || void 0 },
|
|
16741
|
+
altchaSolution: state.altchaSolution,
|
|
16742
|
+
claimToken: state.claimToken ?? void 0
|
|
16743
|
+
};
|
|
16744
|
+
}
|
|
16745
|
+
async function enroll(state, setters, payment) {
|
|
16746
|
+
setters.setStep("submitting");
|
|
16747
|
+
try {
|
|
16748
|
+
const result = await state.api.registerForWholeSeries(enrollmentPayload(state, payment));
|
|
16749
|
+
setters.setEnrollmentResult({
|
|
16750
|
+
status: result.status,
|
|
16751
|
+
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
16752
|
+
usedMembership: payment.method === "membership"
|
|
16753
|
+
});
|
|
16754
|
+
setters.setStep(result.status === "waitlist" ? "waitlist" : "success");
|
|
16755
|
+
return { kind: "state-updated" };
|
|
16756
|
+
} catch (cause) {
|
|
16757
|
+
const message = cause instanceof Error ? cause.message : "Booking failed";
|
|
16758
|
+
setters.setErrorMessage(message);
|
|
16759
|
+
setters.setStep("error");
|
|
16760
|
+
return {
|
|
16761
|
+
kind: "failed",
|
|
16762
|
+
message
|
|
16809
16763
|
};
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
16827
|
-
usedMembership: false
|
|
16828
|
-
});
|
|
16829
|
-
setStep(result.status === "waitlist" ? "waitlist" : "success");
|
|
16830
|
-
return { kind: "state-updated" };
|
|
16831
|
-
} catch (error) {
|
|
16832
|
-
const message = error instanceof Error ? error.message : "Booking failed";
|
|
16833
|
-
setErrorMessage(message);
|
|
16834
|
-
setStep("error");
|
|
16835
|
-
return {
|
|
16836
|
-
kind: "failed",
|
|
16837
|
-
message
|
|
16838
|
-
};
|
|
16839
|
-
}
|
|
16840
|
-
}
|
|
16841
|
-
if (requiresPayment && canUseMembership) {
|
|
16842
|
-
setStep("select-payment");
|
|
16843
|
-
return { kind: "state-updated" };
|
|
16844
|
-
}
|
|
16845
|
-
if (requiresPayment) {
|
|
16846
|
-
setStep("submitting");
|
|
16847
|
-
try {
|
|
16848
|
-
const { successUrl, cancelUrl } = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
16849
|
-
const checkoutResult = await api.createCourseCheckout({
|
|
16850
|
-
courseId: selectedCourse.id,
|
|
16851
|
-
...selectedCoursePricingPayload,
|
|
16852
|
-
email: formData.email.trim().toLowerCase(),
|
|
16853
|
-
name: formData.name.trim(),
|
|
16854
|
-
phone: formData.phone.trim() || void 0,
|
|
16855
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
16856
|
-
altchaSolution,
|
|
16857
|
-
discountCode: discountCode.trim() ? discountCode.trim() : void 0,
|
|
16858
|
-
successUrl,
|
|
16859
|
-
cancelUrl,
|
|
16860
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
16861
|
-
});
|
|
16862
|
-
if (checkoutResult.bypassed) {
|
|
16863
|
-
setEnrollmentResult({
|
|
16864
|
-
status: "enrolled",
|
|
16865
|
-
waitlistPosition: void 0,
|
|
16866
|
-
usedMembership: false
|
|
16867
|
-
});
|
|
16868
|
-
setStep("success");
|
|
16869
|
-
return { kind: "state-updated" };
|
|
16870
|
-
}
|
|
16871
|
-
if (!checkoutResult.checkoutUrl) throw new Error("Checkout URL missing");
|
|
16872
|
-
setStep("redirecting");
|
|
16873
|
-
if (options.onCheckoutRedirect) options.onCheckoutRedirect(checkoutResult.checkoutUrl);
|
|
16874
|
-
else window.location.href = checkoutResult.checkoutUrl;
|
|
16875
|
-
return {
|
|
16876
|
-
kind: "checkout-redirect",
|
|
16877
|
-
checkoutUrl: checkoutResult.checkoutUrl
|
|
16878
|
-
};
|
|
16879
|
-
} catch (error) {
|
|
16880
|
-
const message = error instanceof Error ? error.message : "Checkout failed";
|
|
16881
|
-
setErrorMessage(message);
|
|
16882
|
-
setStep("error");
|
|
16883
|
-
return {
|
|
16884
|
-
kind: "failed",
|
|
16885
|
-
message
|
|
16886
|
-
};
|
|
16887
|
-
}
|
|
16888
|
-
}
|
|
16889
|
-
setStep("submitting");
|
|
16890
|
-
try {
|
|
16891
|
-
const result = await api.enrollInCourse({
|
|
16892
|
-
courseId: selectedCourse.id,
|
|
16893
|
-
...selectedCoursePricingPayload,
|
|
16894
|
-
email: formData.email.trim().toLowerCase(),
|
|
16895
|
-
name: formData.name.trim(),
|
|
16896
|
-
phone: formData.phone.trim() || void 0,
|
|
16897
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
16898
|
-
altchaSolution,
|
|
16899
|
-
paymentMethod: "free",
|
|
16900
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
16901
|
-
});
|
|
16902
|
-
setEnrollmentResult({
|
|
16903
|
-
status: result.status,
|
|
16904
|
-
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
16905
|
-
usedMembership: result.paymentMethod === "membership"
|
|
16764
|
+
}
|
|
16765
|
+
}
|
|
16766
|
+
async function checkout(state, setters) {
|
|
16767
|
+
setters.setStep("submitting");
|
|
16768
|
+
try {
|
|
16769
|
+
const urls = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
16770
|
+
const result = await state.api.createWholeSeriesCheckout({
|
|
16771
|
+
...registrantPayload(state),
|
|
16772
|
+
discountCode: state.discountCode.trim() || void 0,
|
|
16773
|
+
successUrl: urls.successUrl,
|
|
16774
|
+
cancelUrl: urls.cancelUrl
|
|
16775
|
+
});
|
|
16776
|
+
if (result.bypassed) {
|
|
16777
|
+
setters.setEnrollmentResult({
|
|
16778
|
+
status: "enrolled",
|
|
16779
|
+
usedMembership: false
|
|
16906
16780
|
});
|
|
16907
|
-
setStep(
|
|
16781
|
+
setters.setStep("success");
|
|
16908
16782
|
return { kind: "state-updated" };
|
|
16909
|
-
} catch (error) {
|
|
16910
|
-
const message = error instanceof Error ? error.message : "Booking failed";
|
|
16911
|
-
setErrorMessage(message);
|
|
16912
|
-
setStep("error");
|
|
16913
|
-
return {
|
|
16914
|
-
kind: "failed",
|
|
16915
|
-
message
|
|
16916
|
-
};
|
|
16917
16783
|
}
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
if (
|
|
16921
|
-
|
|
16922
|
-
|
|
16784
|
+
if (!result.checkoutUrl) throw new Error("Checkout URL missing");
|
|
16785
|
+
setters.setStep("redirecting");
|
|
16786
|
+
if (state.options.onCheckoutRedirect) state.options.onCheckoutRedirect(result.checkoutUrl);
|
|
16787
|
+
else window.location.href = result.checkoutUrl;
|
|
16788
|
+
return {
|
|
16789
|
+
kind: "checkout-redirect",
|
|
16790
|
+
checkoutUrl: result.checkoutUrl
|
|
16923
16791
|
};
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
};
|
|
16932
|
-
}
|
|
16933
|
-
const requiresPayment = selectedCoursePricing?.selectedRequiresPayment ?? false;
|
|
16934
|
-
if (!waitlistClaim.claim && courseEligibility?.isFull && !courseEligibility.canJoinWaitlist && showSoldOutCourseError()) return {
|
|
16935
|
-
kind: "blocked",
|
|
16936
|
-
message: courseEligibility.reason ?? "This course is fully booked."
|
|
16792
|
+
} catch (cause) {
|
|
16793
|
+
const message = cause instanceof Error ? cause.message : "Checkout failed";
|
|
16794
|
+
setters.setErrorMessage(message);
|
|
16795
|
+
setters.setStep("error");
|
|
16796
|
+
return {
|
|
16797
|
+
kind: "failed",
|
|
16798
|
+
message
|
|
16937
16799
|
};
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16946
|
-
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
|
|
16982
|
-
|
|
16983
|
-
|
|
16984
|
-
|
|
16985
|
-
setStep("error");
|
|
16986
|
-
return {
|
|
16987
|
-
kind: "failed",
|
|
16988
|
-
message
|
|
16989
|
-
};
|
|
16990
|
-
}
|
|
16991
|
-
}
|
|
16992
|
-
setStep("submitting");
|
|
16993
|
-
try {
|
|
16994
|
-
const { successUrl, cancelUrl } = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
16995
|
-
const checkoutResult = await api.createCourseCheckout({
|
|
16996
|
-
courseId: selectedCourse.id,
|
|
16997
|
-
...selectedCoursePricingPayload,
|
|
16998
|
-
email: formData.email.trim().toLowerCase(),
|
|
16999
|
-
name: formData.name.trim(),
|
|
17000
|
-
phone: formData.phone.trim() || void 0,
|
|
17001
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
17002
|
-
altchaSolution,
|
|
17003
|
-
discountCode: discountCode.trim() ? discountCode.trim() : void 0,
|
|
17004
|
-
successUrl,
|
|
17005
|
-
cancelUrl,
|
|
17006
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
17007
|
-
});
|
|
17008
|
-
if (checkoutResult.bypassed) {
|
|
17009
|
-
setEnrollmentResult({
|
|
17010
|
-
status: "enrolled",
|
|
17011
|
-
waitlistPosition: void 0,
|
|
17012
|
-
usedMembership: false
|
|
17013
|
-
});
|
|
17014
|
-
setStep("success");
|
|
17015
|
-
return { kind: "state-updated" };
|
|
17016
|
-
}
|
|
17017
|
-
if (!checkoutResult.checkoutUrl) throw new Error("Checkout URL missing");
|
|
17018
|
-
setStep("redirecting");
|
|
17019
|
-
if (options.onCheckoutRedirect) options.onCheckoutRedirect(checkoutResult.checkoutUrl);
|
|
17020
|
-
else window.location.href = checkoutResult.checkoutUrl;
|
|
17021
|
-
return {
|
|
17022
|
-
kind: "checkout-redirect",
|
|
17023
|
-
checkoutUrl: checkoutResult.checkoutUrl
|
|
17024
|
-
};
|
|
17025
|
-
} catch (error) {
|
|
17026
|
-
const message = error instanceof Error ? error.message : "Checkout failed";
|
|
17027
|
-
setErrorMessage(message);
|
|
17028
|
-
setStep("error");
|
|
17029
|
-
return {
|
|
17030
|
-
kind: "failed",
|
|
17031
|
-
message
|
|
17032
|
-
};
|
|
17033
|
-
}
|
|
16800
|
+
}
|
|
16801
|
+
}
|
|
16802
|
+
async function submitDetails(state, setters) {
|
|
16803
|
+
const invalid = validateSubmission(state, setters);
|
|
16804
|
+
if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
|
|
16805
|
+
if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
|
|
16806
|
+
const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
|
|
16807
|
+
const canUseMembership = requiresPayment && state.selectedCourse.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
|
|
16808
|
+
if (requiresPayment && canUseMembership) {
|
|
16809
|
+
setters.setStep("select-payment");
|
|
16810
|
+
return { kind: "state-updated" };
|
|
16811
|
+
}
|
|
16812
|
+
if (requiresPayment) return checkout(state, setters);
|
|
16813
|
+
return enroll(state, setters, { method: "free" });
|
|
16814
|
+
}
|
|
16815
|
+
async function continuePayment(state, setters) {
|
|
16816
|
+
const invalid = validateSubmission(state, setters);
|
|
16817
|
+
if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
|
|
16818
|
+
if (!state.pricing?.selectedRequiresPayment) {
|
|
16819
|
+
setters.setStep("enter-details");
|
|
16820
|
+
return { kind: "state-updated" };
|
|
16821
|
+
}
|
|
16822
|
+
const selectedState = state;
|
|
16823
|
+
if (state.paymentChoice === "membership") {
|
|
16824
|
+
if (!state.selectedMembershipId) return blocked("Select a membership to sign up.", setters);
|
|
16825
|
+
return enroll(selectedState, setters, {
|
|
16826
|
+
method: "membership",
|
|
16827
|
+
membershipId: state.selectedMembershipId
|
|
16828
|
+
});
|
|
16829
|
+
}
|
|
16830
|
+
return checkout(selectedState, setters);
|
|
16831
|
+
}
|
|
16832
|
+
function useCourseRegistrationActions(state, setStep) {
|
|
16833
|
+
const [errors, setErrors] = useState({});
|
|
16834
|
+
const [enrollmentResult, setEnrollmentResult] = useState(null);
|
|
16835
|
+
const [errorMessage, setErrorMessage] = useState("");
|
|
16836
|
+
const reportError = useCallback((message) => {
|
|
16837
|
+
setErrorMessage(message);
|
|
16838
|
+
}, []);
|
|
16839
|
+
const recordEnrollmentResult = useCallback((result) => {
|
|
16840
|
+
setEnrollmentResult(result);
|
|
16841
|
+
}, []);
|
|
16842
|
+
const setters = {
|
|
16843
|
+
setStep,
|
|
16844
|
+
setErrors,
|
|
16845
|
+
setEnrollmentResult,
|
|
16846
|
+
setErrorMessage
|
|
17034
16847
|
};
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
16848
|
+
return {
|
|
16849
|
+
errors,
|
|
16850
|
+
enrollmentResult,
|
|
16851
|
+
errorMessage,
|
|
16852
|
+
reportError,
|
|
16853
|
+
recordEnrollmentResult,
|
|
16854
|
+
handleSubmit: () => submitDetails(state, setters),
|
|
16855
|
+
handlePaymentContinue: () => continuePayment(state, setters)
|
|
17038
16856
|
};
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
16857
|
+
}
|
|
16858
|
+
//#endregion
|
|
16859
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationPortal.ts
|
|
16860
|
+
const EMPTY_FORM = {
|
|
16861
|
+
name: "",
|
|
16862
|
+
email: "",
|
|
16863
|
+
phone: "",
|
|
16864
|
+
notes: ""
|
|
16865
|
+
};
|
|
16866
|
+
function useCourseRegistrationPortal(api) {
|
|
16867
|
+
const [formData, setFormData] = useState(EMPTY_FORM);
|
|
16868
|
+
const [portalAuthState, setPortalAuthState] = useState("checking");
|
|
16869
|
+
const updateFormData = useCallback((updater) => {
|
|
16870
|
+
setFormData(updater);
|
|
16871
|
+
}, []);
|
|
16872
|
+
useEffect(() => {
|
|
16873
|
+
let cancelled = false;
|
|
16874
|
+
if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
|
|
16875
|
+
setPortalAuthState("unauthenticated");
|
|
16876
|
+
return;
|
|
16877
|
+
}
|
|
16878
|
+
setPortalAuthState("checking");
|
|
16879
|
+
api.getPortalProfile().then((result) => {
|
|
16880
|
+
if (cancelled) return;
|
|
16881
|
+
setPortalAuthState("authenticated");
|
|
16882
|
+
setFormData((current) => ({
|
|
16883
|
+
...current,
|
|
16884
|
+
email: result.profile.email,
|
|
16885
|
+
name: current.name || result.profile.name,
|
|
16886
|
+
phone: current.phone || result.profile.phone || ""
|
|
16887
|
+
}));
|
|
16888
|
+
}).catch(() => {
|
|
16889
|
+
if (!cancelled) setPortalAuthState("unauthenticated");
|
|
16890
|
+
});
|
|
16891
|
+
return () => {
|
|
16892
|
+
cancelled = true;
|
|
16893
|
+
};
|
|
16894
|
+
}, [api]);
|
|
16895
|
+
return {
|
|
16896
|
+
formData,
|
|
16897
|
+
updateFormData,
|
|
16898
|
+
portalAuthState
|
|
17043
16899
|
};
|
|
16900
|
+
}
|
|
16901
|
+
//#endregion
|
|
16902
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseWaitlistSelection.ts
|
|
16903
|
+
function useCourseWaitlistSelection(input) {
|
|
16904
|
+
useEffect(() => {
|
|
16905
|
+
const claim = input.waitlistClaim.claim;
|
|
16906
|
+
if (!claim || claim.subject.kind !== "whole_series") return;
|
|
16907
|
+
const eventSeriesId = claim.subject.eventSeriesId;
|
|
16908
|
+
const course = input.scopedCourses.find((candidate) => candidate.eventSeriesId === eventSeriesId);
|
|
16909
|
+
if (!course) {
|
|
16910
|
+
input.reportError("This waitlist claim is for a different course.");
|
|
16911
|
+
input.goToStep("error");
|
|
16912
|
+
return;
|
|
16913
|
+
}
|
|
16914
|
+
input.chooseCourse(course);
|
|
16915
|
+
input.updateFormData((current) => ({
|
|
16916
|
+
...current,
|
|
16917
|
+
email: claim.prefill.email,
|
|
16918
|
+
name: claim.prefill.name,
|
|
16919
|
+
phone: claim.prefill.phone ?? "",
|
|
16920
|
+
notes: claim.prefill.notes ?? ""
|
|
16921
|
+
}));
|
|
16922
|
+
if (input.step === "select-course") input.goToStep("enter-details");
|
|
16923
|
+
}, [
|
|
16924
|
+
input.chooseCourse,
|
|
16925
|
+
input.goToStep,
|
|
16926
|
+
input.reportError,
|
|
16927
|
+
input.scopedCourses,
|
|
16928
|
+
input.step,
|
|
16929
|
+
input.updateFormData,
|
|
16930
|
+
input.waitlistClaim.claim
|
|
16931
|
+
]);
|
|
16932
|
+
useEffect(() => {
|
|
16933
|
+
if (input.waitlistClaim.requiresPortalLogin || !input.waitlistClaim.error) return;
|
|
16934
|
+
input.reportError(input.waitlistClaim.error);
|
|
16935
|
+
input.goToStep("error");
|
|
16936
|
+
}, [
|
|
16937
|
+
input.goToStep,
|
|
16938
|
+
input.reportError,
|
|
16939
|
+
input.waitlistClaim.error,
|
|
16940
|
+
input.waitlistClaim.requiresPortalLogin
|
|
16941
|
+
]);
|
|
16942
|
+
}
|
|
16943
|
+
//#endregion
|
|
16944
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
16945
|
+
function useCourseRegistrationWizard(props, options = {}) {
|
|
16946
|
+
const api = useBlockApi();
|
|
16947
|
+
const selection = useCourseRegistrationSelection(props);
|
|
16948
|
+
const portal = useCourseRegistrationPortal(api);
|
|
16949
|
+
const waitlistClaim = useWaitlistClaim();
|
|
16950
|
+
const [bookingMode, setBookingMode] = useState(null);
|
|
16951
|
+
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
16952
|
+
const eligibility = useCourseEligibility({
|
|
16953
|
+
api,
|
|
16954
|
+
selectedCourse: selection.selectedCourse,
|
|
16955
|
+
hasPaidSelection: selection.selectedCoursePricing?.hasPaidSelection ?? false,
|
|
16956
|
+
portalAuthState: portal.portalAuthState,
|
|
16957
|
+
waitlistClaimToken: waitlistClaim.token
|
|
16958
|
+
});
|
|
17044
16959
|
const discountUi = useDiscountCodeUi({
|
|
17045
16960
|
api,
|
|
17046
|
-
discountContext: useMemo(() => {
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17053
|
-
};
|
|
17054
|
-
}, [
|
|
17055
|
-
selectedCourse,
|
|
17056
|
-
selectedCoursePricing?.selectedRequiresPayment,
|
|
17057
|
-
paymentChoice
|
|
16961
|
+
discountContext: useMemo(() => selection.selectedCourse && selection.selectedCoursePricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
|
|
16962
|
+
type: "whole_series",
|
|
16963
|
+
eventSeriesId: selection.selectedCourse.eventSeriesId
|
|
16964
|
+
} : null, [
|
|
16965
|
+
eligibility.paymentChoice,
|
|
16966
|
+
selection.selectedCourse,
|
|
16967
|
+
selection.selectedCoursePricing?.selectedRequiresPayment
|
|
17058
16968
|
]),
|
|
17059
|
-
subtotalCents: selectedCoursePricing?.selectedPriceAmount ?? void 0
|
|
16969
|
+
subtotalCents: selection.selectedCoursePricing?.selectedPriceAmount ?? void 0
|
|
17060
16970
|
});
|
|
17061
|
-
const
|
|
17062
|
-
const hasCoursePayment = resolveHasCoursePayment(selectedCoursePricing);
|
|
17063
|
-
const canUseMembership = hasCoursePayment && selectedCourse?.acceptsMemberships === true && portalAuthState === "authenticated" && eligibleMemberships.length > 0;
|
|
17064
|
-
const hasPreSelectedCourse = scopedCourses.length === 1;
|
|
17065
|
-
const isMembershipFastTrack = canUseMembership && eligibleMemberships.length === 1 && bookingMode === "membership";
|
|
17066
|
-
const wizardSteps = useMemo(() => getWizardStepsForContext(hasPreSelectedCourse, hasCoursePayment, canUseMembership, bookingMode, isMembershipFastTrack), [
|
|
17067
|
-
hasPreSelectedCourse,
|
|
17068
|
-
hasCoursePayment,
|
|
17069
|
-
canUseMembership,
|
|
17070
|
-
bookingMode,
|
|
17071
|
-
isMembershipFastTrack
|
|
17072
|
-
]);
|
|
17073
|
-
const currentStepNumber = getStepNumber(step, wizardSteps);
|
|
17074
|
-
const totalSteps = wizardSteps.length;
|
|
17075
|
-
const stepLabels = getStepLabels(wizardSteps);
|
|
17076
|
-
const canShowPortalAuthSidebarOnCurrentStep = step !== "success" && step !== "waitlist" && step !== "error";
|
|
17077
|
-
const showPortalAuthSidebar = portalAuthState === "unauthenticated" && waitlistClaim.requiresPortalLogin && canShowPortalAuthSidebarOnCurrentStep || portalAuthState === "unauthenticated" && hasCoursePayment && selectedCourse?.acceptsMemberships === true && step !== "select-course" && canShowPortalAuthSidebarOnCurrentStep;
|
|
17078
|
-
return {
|
|
16971
|
+
const actions = useCourseRegistrationActions({
|
|
17079
16972
|
api,
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
formData,
|
|
17091
|
-
setFormData,
|
|
17092
|
-
errors,
|
|
17093
|
-
enrollmentResult,
|
|
17094
|
-
errorMessage,
|
|
17095
|
-
portalAuthState,
|
|
17096
|
-
handleLogout: portalAuthState === "authenticated" ? () => logoutPortal(COURSE_REGISTRATION_ANCHOR_ID) : void 0,
|
|
16973
|
+
selectedCourse: selection.selectedCourse,
|
|
16974
|
+
pricing: selection.selectedCoursePricing,
|
|
16975
|
+
formData: portal.formData,
|
|
16976
|
+
portalAuthState: portal.portalAuthState,
|
|
16977
|
+
eligibility: eligibility.courseEligibility,
|
|
16978
|
+
eligibleMemberships: eligibility.eligibleMemberships,
|
|
16979
|
+
paymentChoice: eligibility.paymentChoice,
|
|
16980
|
+
selectedMembershipId: eligibility.selectedMembershipId,
|
|
16981
|
+
claimToken: waitlistClaim.token,
|
|
16982
|
+
hasClaim: waitlistClaim.claim !== null,
|
|
17097
16983
|
altchaSolution,
|
|
17098
|
-
setAltchaSolution,
|
|
17099
|
-
showSpamProtection,
|
|
17100
|
-
eligibilityLoading,
|
|
17101
|
-
eligibilityError,
|
|
17102
|
-
courseEligibility,
|
|
17103
|
-
eligibleMemberships,
|
|
17104
|
-
paymentChoice,
|
|
17105
|
-
setPaymentChoice,
|
|
17106
|
-
selectedMembershipId,
|
|
17107
|
-
setSelectedMembershipId,
|
|
17108
|
-
discountUiOpen: discountUi.discountUiOpen,
|
|
17109
|
-
setDiscountUiOpen: discountUi.setDiscountUiOpen,
|
|
17110
16984
|
discountCode: discountUi.discountCode,
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
16985
|
+
options
|
|
16986
|
+
}, selection.goToStep);
|
|
16987
|
+
useCourseRegistrationEffects({
|
|
16988
|
+
api,
|
|
16989
|
+
actions,
|
|
16990
|
+
portal,
|
|
16991
|
+
selection,
|
|
16992
|
+
waitlistClaim
|
|
16993
|
+
});
|
|
16994
|
+
return buildCourseRegistrationWizardResult({
|
|
16995
|
+
api,
|
|
16996
|
+
selection,
|
|
16997
|
+
portal,
|
|
16998
|
+
eligibility,
|
|
16999
|
+
actions,
|
|
17000
|
+
discountUi,
|
|
17116
17001
|
waitlistClaim,
|
|
17002
|
+
view: deriveCourseRegistrationViewState({
|
|
17003
|
+
scopedCourses: selection.scopedCourses,
|
|
17004
|
+
selectedCourse: selection.selectedCourse,
|
|
17005
|
+
pricing: selection.selectedCoursePricing,
|
|
17006
|
+
portalAuthState: portal.portalAuthState,
|
|
17007
|
+
eligibleMembershipCount: eligibility.eligibleMemberships.length,
|
|
17008
|
+
bookingMode,
|
|
17009
|
+
step: selection.step,
|
|
17010
|
+
waitlistRequiresPortalLogin: waitlistClaim.requiresPortalLogin
|
|
17011
|
+
}),
|
|
17117
17012
|
bookingMode,
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17013
|
+
setBookingMode,
|
|
17014
|
+
altchaSolution,
|
|
17015
|
+
setAltchaSolution
|
|
17016
|
+
});
|
|
17017
|
+
}
|
|
17018
|
+
function useCourseRegistrationEffects(input) {
|
|
17019
|
+
useCoursePaymentVerification(input.api, {
|
|
17020
|
+
setStep: input.selection.goToStep,
|
|
17021
|
+
setErrorMessage: input.actions.reportError,
|
|
17022
|
+
setEnrollmentResult: input.actions.recordEnrollmentResult
|
|
17023
|
+
});
|
|
17024
|
+
useCourseWaitlistSelection({
|
|
17025
|
+
waitlistClaim: input.waitlistClaim,
|
|
17026
|
+
scopedCourses: input.selection.scopedCourses,
|
|
17027
|
+
step: input.selection.step,
|
|
17028
|
+
goToStep: input.selection.goToStep,
|
|
17029
|
+
chooseCourse: input.selection.chooseCourse,
|
|
17030
|
+
updateFormData: input.portal.updateFormData,
|
|
17031
|
+
reportError: input.actions.reportError
|
|
17032
|
+
});
|
|
17033
|
+
}
|
|
17034
|
+
function buildCourseRegistrationWizardResult(parts) {
|
|
17035
|
+
const handleBookingModeChange = (mode) => {
|
|
17036
|
+
parts.setBookingMode(mode);
|
|
17037
|
+
parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
|
|
17038
|
+
};
|
|
17039
|
+
return {
|
|
17040
|
+
api: parts.api,
|
|
17041
|
+
...parts.selection,
|
|
17042
|
+
...parts.portal,
|
|
17043
|
+
...parts.eligibility,
|
|
17044
|
+
...parts.actions,
|
|
17045
|
+
waitlistClaim: parts.waitlistClaim,
|
|
17046
|
+
bookingMode: parts.bookingMode,
|
|
17047
|
+
altchaSolution: parts.altchaSolution,
|
|
17048
|
+
setAltchaSolution: parts.setAltchaSolution,
|
|
17049
|
+
showSpamProtection: isSpamProtectionEnabled(),
|
|
17050
|
+
discountUiOpen: parts.discountUi.discountUiOpen,
|
|
17051
|
+
setDiscountUiOpen: parts.discountUi.setDiscountUiOpen,
|
|
17052
|
+
discountCode: parts.discountUi.discountCode,
|
|
17053
|
+
setDiscountCode: parts.discountUi.setDiscountCode,
|
|
17054
|
+
discountsAvailable: parts.discountUi.discountsAvailable,
|
|
17055
|
+
manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
|
|
17056
|
+
discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
|
|
17057
|
+
...parts.view,
|
|
17058
|
+
handleCourseSelect: (course) => {
|
|
17059
|
+
parts.selection.chooseCourse(course);
|
|
17060
|
+
parts.selection.goToStep("enter-details");
|
|
17061
|
+
},
|
|
17062
|
+
handleRetry: () => {
|
|
17063
|
+
parts.selection.goToStep(parts.selection.scopedCourses.length === 1 ? "enter-details" : "select-course");
|
|
17064
|
+
parts.actions.reportError("");
|
|
17065
|
+
},
|
|
17066
|
+
handleBookingModeChange,
|
|
17067
|
+
handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(COURSE_REGISTRATION_ANCHOR_ID) : void 0,
|
|
17068
|
+
selectedCoursePricingPayload: buildCoursePricingOptionPayload(parts.selection.selectedCoursePricing)
|
|
17130
17069
|
};
|
|
17131
17070
|
}
|
|
17132
17071
|
//#endregion
|
|
@@ -17298,7 +17237,6 @@ function useHeadlessWholeSeriesRegistrationFlow(options) {
|
|
|
17298
17237
|
function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
17299
17238
|
const wizard = deps.useCourseRegistrationWizard({
|
|
17300
17239
|
courses: (options.runs ?? []).map(toPublicCourse),
|
|
17301
|
-
contentEntry: options.contentEntry ?? null,
|
|
17302
17240
|
subject: options.subject ?? null
|
|
17303
17241
|
}, { onCheckoutRedirect: () => {} });
|
|
17304
17242
|
const steps = useMemo(() => deriveWholeSeriesRegistrationSteps({
|
|
@@ -17312,23 +17250,23 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17312
17250
|
selectedMembershipId: wizard.selectedMembershipId,
|
|
17313
17251
|
required: wizard.selectedCoursePricing?.selectedRequiresPayment ?? false
|
|
17314
17252
|
});
|
|
17315
|
-
const updateRegistrant = useCallback((values) => wizard.
|
|
17253
|
+
const updateRegistrant = useCallback((values) => wizard.updateFormData(values), [wizard]);
|
|
17316
17254
|
const setSlidingAmountCents = useCallback((amount) => {
|
|
17317
|
-
wizard.
|
|
17255
|
+
wizard.changeSlidingAmount(amount === null || !Number.isFinite(amount) || amount < 0 ? "" : String(amount / 100));
|
|
17318
17256
|
}, [wizard]);
|
|
17319
17257
|
const selectPayment = useCallback((selection) => {
|
|
17320
17258
|
switch (selection.method) {
|
|
17321
17259
|
case "none":
|
|
17322
17260
|
wizard.handleBookingModeChange(null);
|
|
17323
|
-
wizard.
|
|
17261
|
+
wizard.chooseMembership(null);
|
|
17324
17262
|
return;
|
|
17325
17263
|
case "card":
|
|
17326
17264
|
wizard.handleBookingModeChange("card");
|
|
17327
|
-
wizard.
|
|
17265
|
+
wizard.chooseMembership(null);
|
|
17328
17266
|
return;
|
|
17329
17267
|
case "membership":
|
|
17330
17268
|
wizard.handleBookingModeChange("membership");
|
|
17331
|
-
wizard.
|
|
17269
|
+
wizard.chooseMembership(selection.membershipId);
|
|
17332
17270
|
return;
|
|
17333
17271
|
}
|
|
17334
17272
|
}, [wizard]);
|
|
@@ -17342,7 +17280,7 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17342
17280
|
reason: "blocked",
|
|
17343
17281
|
message: "Choose an available set of dates to continue."
|
|
17344
17282
|
};
|
|
17345
|
-
wizard.
|
|
17283
|
+
wizard.goToStep("enter-details");
|
|
17346
17284
|
return {
|
|
17347
17285
|
ok: true,
|
|
17348
17286
|
outcome: { kind: "state-updated" }
|
|
@@ -17367,13 +17305,13 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17367
17305
|
const back = useCallback(() => {
|
|
17368
17306
|
switch (wizard.step) {
|
|
17369
17307
|
case "enter-details":
|
|
17370
|
-
if (!wizard.hasPreSelectedCourse) wizard.
|
|
17308
|
+
if (!wizard.hasPreSelectedCourse) wizard.goToStep("select-course");
|
|
17371
17309
|
return;
|
|
17372
17310
|
case "booking-mode":
|
|
17373
|
-
wizard.
|
|
17311
|
+
wizard.goToStep("enter-details");
|
|
17374
17312
|
return;
|
|
17375
17313
|
case "select-payment":
|
|
17376
|
-
wizard.
|
|
17314
|
+
wizard.goToStep(wizard.canUseMembership ? "booking-mode" : "enter-details");
|
|
17377
17315
|
return;
|
|
17378
17316
|
case "select-course":
|
|
17379
17317
|
case "submitting":
|
|
@@ -17426,7 +17364,6 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17426
17364
|
scoped: wizard.scopedCourses.map(toWholeSeriesRegistrationRun),
|
|
17427
17365
|
selected: selectedRun ? toWholeSeriesRegistrationRun(selectedRun) : null,
|
|
17428
17366
|
hasPreSelectedRun: wizard.hasPreSelectedCourse,
|
|
17429
|
-
contentEntry: options.contentEntry ?? null,
|
|
17430
17367
|
subject: options.subject ?? null
|
|
17431
17368
|
},
|
|
17432
17369
|
registrant: {
|
|
@@ -17465,11 +17402,11 @@ function useWholeSeriesRegistrationControllerWithDeps(options, deps) {
|
|
|
17465
17402
|
},
|
|
17466
17403
|
actions: {
|
|
17467
17404
|
selectRun: (runId) => {
|
|
17468
|
-
const run = wizard.scopedCourses.find((candidate) => candidate.
|
|
17405
|
+
const run = wizard.scopedCourses.find((candidate) => candidate.eventSeriesId === runId) ?? null;
|
|
17469
17406
|
if (run) wizard.handleCourseSelect(run);
|
|
17470
17407
|
},
|
|
17471
17408
|
updateRegistrant,
|
|
17472
|
-
selectPricingOption: wizard.
|
|
17409
|
+
selectPricingOption: wizard.choosePricingOption,
|
|
17473
17410
|
setSlidingAmountCents,
|
|
17474
17411
|
selectPayment,
|
|
17475
17412
|
setDiscountCode: wizard.setDiscountCode,
|
|
@@ -17513,15 +17450,14 @@ function toHeadlessActionResult(result) {
|
|
|
17513
17450
|
function toPublicCourse(run) {
|
|
17514
17451
|
const pricing = toCoursePricing(run.pricing);
|
|
17515
17452
|
return {
|
|
17516
|
-
|
|
17517
|
-
|
|
17453
|
+
eventSeriesId: run.registrationTarget.eventSeriesId,
|
|
17454
|
+
eventOfferingId: run.eventOfferingId,
|
|
17518
17455
|
title: run.title,
|
|
17519
17456
|
slug: run.slug,
|
|
17520
17457
|
description: run.description,
|
|
17521
17458
|
teamMembers: run.teamMembers ? [...run.teamMembers] : void 0,
|
|
17522
17459
|
enrollmentOpen: run.registrationOpen,
|
|
17523
17460
|
pricing,
|
|
17524
|
-
priceCents: run.pricing.pricingStrategy === "single" ? run.pricing.amountCents : null,
|
|
17525
17461
|
currency: run.pricing.currency,
|
|
17526
17462
|
paymentTerms: run.pricing.paymentTerms,
|
|
17527
17463
|
enrollmentCapacity: run.capacity,
|
|
@@ -17534,8 +17470,7 @@ function toPublicCourse(run) {
|
|
|
17534
17470
|
...date,
|
|
17535
17471
|
overrides: date.overrides ? { ...date.overrides } : date.overrides
|
|
17536
17472
|
})),
|
|
17537
|
-
venue: run.venue
|
|
17538
|
-
contentEntryId: run.contentEntryId
|
|
17473
|
+
venue: run.venue
|
|
17539
17474
|
};
|
|
17540
17475
|
}
|
|
17541
17476
|
function toCoursePricing(pricing) {
|
|
@@ -17573,7 +17508,7 @@ function toCoursePricing(pricing) {
|
|
|
17573
17508
|
}
|
|
17574
17509
|
function toWholeSeriesRegistrationRun(run) {
|
|
17575
17510
|
return {
|
|
17576
|
-
id: run.
|
|
17511
|
+
id: run.eventSeriesId,
|
|
17577
17512
|
title: run.title,
|
|
17578
17513
|
slug: run.slug,
|
|
17579
17514
|
description: run.description,
|