@riverbankcms/sdk 0.121.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-lZ600tJx.mjs → PreviewEditorSidebar-DBmAJJkQ.mjs} +24 -41
- package/dist/{PreviewEditorUI-CTBWzLSb.mjs → PreviewEditorUI-CfGaz9cY.mjs} +3 -3
- package/dist/{PreviewQueryProvider-BHT8CJvZ.mjs → PreviewQueryProvider-BH-3-jSj.mjs} +1 -1
- package/dist/{SdkPreviewModeRuntime-DhPU58s7.mjs → SdkPreviewModeRuntime-BW9Z8j8T.mjs} +1020 -1234
- package/dist/{SiteChromeCustomizeContext-BkNvpzNZ.mjs → SiteChromeCustomizeContext-2z8moxYf.mjs} +1902 -1961
- 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 +100 -75
- 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 +10 -12
- 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 +6 -7
- 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 +1587 -115
- 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 +7392 -10989
- 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 +7398 -7687
- 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 -1043
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/middleware.mjs +1116 -1044
- package/dist/{previewAuthStore-31xH13Jc.mjs → previewAuthStore-CJX21dGi.mjs} +1119 -1044
- package/dist/{sdk-runtime-BE_vcGua.mjs → sdk-runtime-OnPM8Z69.mjs} +2 -2
- package/dist/{separator-CiffYtk3.mjs → separator-CPtfzHqA.mjs} +1 -1
- package/dist/server/components.mjs +11120 -12601
- 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 +1499 -1488
- package/dist/server/next.mjs +18291 -21201
- package/dist/server/page-converter.mjs +1898 -2040
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +19666 -21153
- package/dist/server/rendering.mjs +17117 -18651
- package/dist/server/routing.mjs +3614 -2509
- package/dist/server/server.mjs +3298 -3478
- 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
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { n as formatCoursePriceDisplay, r as resolveCoursePricingState, t as formatCoursePriceAmount } from "./pricing-
|
|
4
|
-
import { n as useBlockApi, t as BlockApiProvider } from "./context-
|
|
2
|
+
import { At as formatBookingTime, Dt as formatBookingDate, Ft as toBookingTimeZone, Gt as assertNever, It as toScheduledBookingDateTime, Lt as parseEventPageSurfaceSubject, X as themeButtonClassName, t as defineIslandPropsDecoder } from "./propsDecoder-DeunRj6m.mjs";
|
|
3
|
+
import { n as formatCoursePriceDisplay, r as resolveCoursePricingState, t as formatCoursePriceAmount } from "./pricing-BYWN_ATa.mjs";
|
|
4
|
+
import { n as useBlockApi, t as BlockApiProvider } from "./context-CJz1Vlsz.mjs";
|
|
5
5
|
import { n as isSpamProtectionEnabled, r as AltchaWidget, t as getChallengeUrl } from "./src-B833rYRr.mjs";
|
|
6
|
-
import { i as CheckIcon, n as TerminalPanel, r as StateIcon, t as useDiscountCodeUi } from "./useDiscountCodeUi-
|
|
7
|
-
import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-
|
|
8
|
-
import { n as SpinnerNode, r as formatPrice, t as StepIndicator$1 } from "./StepIndicator-
|
|
6
|
+
import { i as CheckIcon, n as TerminalPanel, r as StateIcon, t as useDiscountCodeUi } from "./useDiscountCodeUi-I-92-x2V.mjs";
|
|
7
|
+
import { t as DiscountCodeDisclosure } from "./DiscountCodeDisclosure-DxvjKvck.mjs";
|
|
8
|
+
import { n as SpinnerNode, r as formatPrice, t as StepIndicator$1 } from "./StepIndicator-CTcGf8Be.mjs";
|
|
9
9
|
import { t as FeedbackMessage } from "./FeedbackMessage-ByMrs3cr.mjs";
|
|
10
10
|
import { n as getFieldValidationControlProps, t as FieldValidationMessage } from "./FieldValidationMessage-AYanWFb-.mjs";
|
|
11
11
|
import { t as buildCheckoutReturnUrls } from "./checkoutUrls-Ct8Mxna3.mjs";
|
|
12
12
|
import { t as scrollToBlock } from "./scrollToBlock-C86BYkyV.mjs";
|
|
13
|
-
import { a as ClockIcon, i as LoggedInAsUser, n as logoutPortal, r as useWaitlistClaim, t as MagicLinkForm } from "./MagicLinkForm-
|
|
13
|
+
import { a as ClockIcon, i as LoggedInAsUser, n as logoutPortal, r as useWaitlistClaim, t as MagicLinkForm } from "./MagicLinkForm-BzyRJ8VF.mjs";
|
|
14
14
|
import { t as CrossIcon } from "./CrossIcon-Dn1KRKW5.mjs";
|
|
15
15
|
import { t as mountReactIsland } from "./reactMount-SY8AVRof.mjs";
|
|
16
16
|
import { t as buildRouteIslandApiConfig } from "./routeIslandApiConfig-UNsfPcYq.mjs";
|
|
17
17
|
import { t as ModalShell } from "./ModalShell-CqkBvBIC.mjs";
|
|
18
|
-
import React, { Component, useEffect, useMemo, useState } from "react";
|
|
18
|
+
import React, { Component, useCallback, useEffect, useMemo, useState } from "react";
|
|
19
19
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
20
20
|
//#region ../blocks/src/system/runtime/shared/utils/validation.ts
|
|
21
21
|
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -491,6 +491,37 @@ function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading,
|
|
|
491
491
|
] });
|
|
492
492
|
}
|
|
493
493
|
//#endregion
|
|
494
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/pricing.ts
|
|
495
|
+
function parseCurrencyInputToCents(value) {
|
|
496
|
+
const trimmed = value.trim();
|
|
497
|
+
if (!trimmed) return null;
|
|
498
|
+
const amount = Number(trimmed);
|
|
499
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
500
|
+
return Math.round(amount * 100);
|
|
501
|
+
}
|
|
502
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
503
|
+
const major = amount / 100;
|
|
504
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
505
|
+
}
|
|
506
|
+
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
507
|
+
if (pricing?.requiresSelection && !pricing.selectedOption) return pricing.slidingScale ? "Choose an amount to continue." : "Choose a pricing option to continue.";
|
|
508
|
+
const selectedAmount = pricing?.selectedSlidingAmount;
|
|
509
|
+
const scale = pricing?.slidingScale;
|
|
510
|
+
if (scale && selectedAmount !== null && selectedAmount !== void 0 && (selectedAmount < scale.minAmount || selectedAmount > scale.maxAmount)) return "Choose an amount within the sliding scale.";
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
function buildCoursePricingOptionPayload(pricing) {
|
|
514
|
+
if (pricing?.selectedOption) return { pricingOptionId: pricing.selectedOption.id };
|
|
515
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
516
|
+
return {};
|
|
517
|
+
}
|
|
518
|
+
function defaultCoursePricingSelection(pricing, previousOptionId) {
|
|
519
|
+
return {
|
|
520
|
+
pricingOptionId: previousOptionId && pricing.selectableOptions.some((option) => option.id === previousOptionId) ? previousOptionId : pricing.selectedOption?.id ?? null,
|
|
521
|
+
slidingAmountInput: pricing.slidingScale?.suggestedAmount !== null && pricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(pricing.slidingScale.suggestedAmount) : ""
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
//#endregion
|
|
494
525
|
//#region ../blocks/src/system/runtime/nodes/course-registration/wizardSteps.ts
|
|
495
526
|
/**
|
|
496
527
|
* Steps that are part of the main wizard and should show the step indicator.
|
|
@@ -563,6 +594,110 @@ function getStepLabels(steps) {
|
|
|
563
594
|
return steps.map((step) => STEP_LABELS[step] ?? step);
|
|
564
595
|
}
|
|
565
596
|
//#endregion
|
|
597
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/courseRegistrationViewState.ts
|
|
598
|
+
function deriveCourseRegistrationViewState(input) {
|
|
599
|
+
const hasCoursePayment = resolveCoursePaymentRequirement(input.pricing);
|
|
600
|
+
const canUseMembership = hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.portalAuthState === "authenticated" && input.eligibleMembershipCount > 0;
|
|
601
|
+
const hasPreSelectedCourse = input.scopedCourses.length === 1;
|
|
602
|
+
const fastTrack = canUseMembership && input.eligibleMembershipCount === 1 && input.bookingMode === "membership";
|
|
603
|
+
const wizardSteps = getWizardStepsForContext(hasPreSelectedCourse, hasCoursePayment, canUseMembership, input.bookingMode, fastTrack);
|
|
604
|
+
const showPortalAuthSidebar = shouldShowPortalAuthSidebar({
|
|
605
|
+
...input,
|
|
606
|
+
hasCoursePayment
|
|
607
|
+
});
|
|
608
|
+
return {
|
|
609
|
+
hasCoursePayment,
|
|
610
|
+
canUseMembership,
|
|
611
|
+
hasPreSelectedCourse,
|
|
612
|
+
wizardSteps,
|
|
613
|
+
currentStepNumber: getStepNumber(input.step, wizardSteps),
|
|
614
|
+
totalSteps: wizardSteps.length,
|
|
615
|
+
stepLabels: getStepLabels(wizardSteps),
|
|
616
|
+
showPortalAuthSidebar
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function resolveCoursePaymentRequirement(pricing) {
|
|
620
|
+
if (!pricing) return false;
|
|
621
|
+
return pricing.selectedOption ? pricing.selectedRequiresPayment : pricing.hasPaidSelection;
|
|
622
|
+
}
|
|
623
|
+
function shouldShowPortalAuthSidebar(input) {
|
|
624
|
+
if (input.portalAuthState !== "unauthenticated") return false;
|
|
625
|
+
if (input.step === "success" || input.step === "waitlist" || input.step === "error") return false;
|
|
626
|
+
return input.waitlistRequiresPortalLogin || input.hasCoursePayment && input.selectedCourse?.acceptsMemberships === true && input.step !== "select-course";
|
|
627
|
+
}
|
|
628
|
+
//#endregion
|
|
629
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseEligibility.ts
|
|
630
|
+
function shouldFetchEligibility(input) {
|
|
631
|
+
if (!input.course || input.portalAuthState === "checking" || input.hasWaitlistClaimToken) return false;
|
|
632
|
+
const membershipCheck = input.portalAuthState === "authenticated" && input.hasPaidSelection && input.course.acceptsMemberships;
|
|
633
|
+
const capacityCheck = input.course.availableSpots !== null && input.course.availableSpots <= 0;
|
|
634
|
+
return membershipCheck || capacityCheck;
|
|
635
|
+
}
|
|
636
|
+
function useCourseEligibility(input) {
|
|
637
|
+
const [loading, setLoading] = useState(false);
|
|
638
|
+
const [error, setError] = useState(null);
|
|
639
|
+
const [eligibility, setEligibility] = useState(null);
|
|
640
|
+
const [memberships, setMemberships] = useState([]);
|
|
641
|
+
const [paymentChoice, setPaymentChoice] = useState("checkout");
|
|
642
|
+
const [selectedMembershipId, setSelectedMembershipId] = useState(null);
|
|
643
|
+
const choosePaymentChoice = useCallback((choice) => {
|
|
644
|
+
setPaymentChoice(choice);
|
|
645
|
+
}, []);
|
|
646
|
+
const chooseMembership = useCallback((membershipId) => {
|
|
647
|
+
setSelectedMembershipId(membershipId);
|
|
648
|
+
}, []);
|
|
649
|
+
useEffect(() => {
|
|
650
|
+
let cancelled = false;
|
|
651
|
+
setEligibility(null);
|
|
652
|
+
setMemberships([]);
|
|
653
|
+
setSelectedMembershipId(null);
|
|
654
|
+
setError(null);
|
|
655
|
+
setPaymentChoice("checkout");
|
|
656
|
+
const eligibilityInput = {
|
|
657
|
+
course: input.selectedCourse,
|
|
658
|
+
hasPaidSelection: input.hasPaidSelection,
|
|
659
|
+
portalAuthState: input.portalAuthState,
|
|
660
|
+
hasWaitlistClaimToken: input.waitlistClaimToken !== null
|
|
661
|
+
};
|
|
662
|
+
if (!shouldFetchEligibility(eligibilityInput)) return;
|
|
663
|
+
const course = eligibilityInput.course;
|
|
664
|
+
setLoading(true);
|
|
665
|
+
input.api.checkWholeSeriesEligibility({ eventSeriesId: course.eventSeriesId }).then((result) => {
|
|
666
|
+
if (cancelled) return;
|
|
667
|
+
const eligibleMemberships = result.eligibleMemberships ?? [];
|
|
668
|
+
setEligibility(result);
|
|
669
|
+
setMemberships(eligibleMemberships);
|
|
670
|
+
if (input.portalAuthState === "authenticated" && eligibleMemberships.length > 0) {
|
|
671
|
+
setPaymentChoice("membership");
|
|
672
|
+
if (eligibleMemberships.length === 1) setSelectedMembershipId(eligibleMemberships[0]?.customerMembershipId ?? null);
|
|
673
|
+
}
|
|
674
|
+
}).catch((cause) => {
|
|
675
|
+
if (!cancelled) setError(cause instanceof Error ? cause.message : "Failed to check membership eligibility");
|
|
676
|
+
}).finally(() => {
|
|
677
|
+
if (!cancelled) setLoading(false);
|
|
678
|
+
});
|
|
679
|
+
return () => {
|
|
680
|
+
cancelled = true;
|
|
681
|
+
};
|
|
682
|
+
}, [
|
|
683
|
+
input.api,
|
|
684
|
+
input.hasPaidSelection,
|
|
685
|
+
input.portalAuthState,
|
|
686
|
+
input.selectedCourse,
|
|
687
|
+
input.waitlistClaimToken
|
|
688
|
+
]);
|
|
689
|
+
return {
|
|
690
|
+
eligibilityLoading: loading,
|
|
691
|
+
eligibilityError: error,
|
|
692
|
+
courseEligibility: eligibility,
|
|
693
|
+
eligibleMemberships: memberships,
|
|
694
|
+
paymentChoice,
|
|
695
|
+
choosePaymentChoice,
|
|
696
|
+
selectedMembershipId,
|
|
697
|
+
chooseMembership
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
//#endregion
|
|
566
701
|
//#region ../blocks/src/system/runtime/nodes/course-page-surface-scope.ts
|
|
567
702
|
/**
|
|
568
703
|
* Resolves native course-page ownership without falling back to entry or slug
|
|
@@ -580,7 +715,7 @@ function resolveCoursePageSurfaceScope(courses, subjectValue) {
|
|
|
580
715
|
return {
|
|
581
716
|
kind: "scoped",
|
|
582
717
|
subject: parsed.value,
|
|
583
|
-
courses: courses.filter((course) => allowedSeriesIds.has(course.
|
|
718
|
+
courses: courses.filter((course) => allowedSeriesIds.has(course.eventSeriesId))
|
|
584
719
|
};
|
|
585
720
|
}
|
|
586
721
|
function eventSeriesIdsForSubject(subject) {
|
|
@@ -591,654 +726,504 @@ function eventSeriesIdsForSubject(subject) {
|
|
|
591
726
|
}
|
|
592
727
|
}
|
|
593
728
|
//#endregion
|
|
594
|
-
//#region ../blocks/src/system/runtime/nodes/course-registration/
|
|
595
|
-
function
|
|
596
|
-
const
|
|
597
|
-
if (
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
return Math.round(amount * 100);
|
|
601
|
-
}
|
|
602
|
-
function formatCentsAsCurrencyInput(amount) {
|
|
603
|
-
const major = amount / 100;
|
|
604
|
-
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
729
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationSelection.ts
|
|
730
|
+
function selectScopedCourses(props) {
|
|
731
|
+
const surfaceScope = resolveCoursePageSurfaceScope(props.courses ?? [], props.subject);
|
|
732
|
+
if (surfaceScope.kind === "unsupported") return [];
|
|
733
|
+
if (surfaceScope.kind === "scoped") return surfaceScope.courses;
|
|
734
|
+
return [];
|
|
605
735
|
}
|
|
606
|
-
function
|
|
607
|
-
if (!course || portalAuthState === "checking") return false;
|
|
608
|
-
if (hasWaitlistClaimToken) return false;
|
|
609
|
-
const needsMembershipEligibility = portalAuthState === "authenticated" && hasPaidSelection && course.acceptsMemberships;
|
|
610
|
-
const needsWaitlistAvailabilityCheck = course.availableSpots !== null && course.availableSpots <= 0;
|
|
611
|
-
return needsMembershipEligibility || needsWaitlistAvailabilityCheck;
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* Extracts session_id from URL, checking both query params and hash fragment.
|
|
615
|
-
*
|
|
616
|
-
* Stripe appends session_id to the success URL, but if our URL contains a hash
|
|
617
|
-
* (e.g., #course-registration), Stripe ends up appending session_id after the hash:
|
|
618
|
-
* Expected: ?enrollment=success&session_id=cs_test_...#course-registration
|
|
619
|
-
* Actual: ?enrollment=success#course-registration&session_id=cs_test_...
|
|
620
|
-
*
|
|
621
|
-
* This helper checks both locations to handle this edge case.
|
|
622
|
-
*/
|
|
623
|
-
function getSessionIdFromUrl() {
|
|
736
|
+
function getCourseCheckoutSessionId() {
|
|
624
737
|
const fromSearch = new URLSearchParams(window.location.search).get("session_id");
|
|
625
738
|
if (fromSearch) return fromSearch;
|
|
626
739
|
return window.location.hash.match(/[?&]session_id=([^&]+)/)?.[1] ?? null;
|
|
627
740
|
}
|
|
628
|
-
function
|
|
629
|
-
if (
|
|
630
|
-
|
|
631
|
-
return "Choose a pricing option to continue.";
|
|
632
|
-
}
|
|
633
|
-
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) return "Choose an amount within the sliding scale.";
|
|
634
|
-
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) return "Choose an amount within the sliding scale.";
|
|
635
|
-
return null;
|
|
741
|
+
function initialStep(courses) {
|
|
742
|
+
if (new URLSearchParams(window.location.search).get("enrollment") === "success" && getCourseCheckoutSessionId()) return "verifying-payment";
|
|
743
|
+
return courses.length === 1 ? "enter-details" : "select-course";
|
|
636
744
|
}
|
|
637
|
-
function
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return {};
|
|
641
|
-
}
|
|
642
|
-
function resolveHasCoursePayment(pricing) {
|
|
643
|
-
if (!pricing) return false;
|
|
644
|
-
if (pricing.selectedOption) return pricing.selectedRequiresPayment;
|
|
645
|
-
return pricing.hasPaidSelection;
|
|
646
|
-
}
|
|
647
|
-
function useCourseRegistrationWizard(props, options = {}) {
|
|
648
|
-
const api = useBlockApi();
|
|
649
|
-
const { contentEntry, courses, entrySubrouteContext, subject } = props;
|
|
650
|
-
const scopedCourses = useMemo(() => {
|
|
651
|
-
const allCourses = courses ?? [];
|
|
652
|
-
if (entrySubrouteContext?.kind === "course-run") {
|
|
653
|
-
const matched = allCourses.find((c) => c.id === entrySubrouteContext.run.courseId) ?? null;
|
|
654
|
-
if (matched) return [matched];
|
|
655
|
-
}
|
|
656
|
-
const pageSurfaceScope = resolveCoursePageSurfaceScope(allCourses, subject);
|
|
657
|
-
if (pageSurfaceScope.kind === "unsupported") return [];
|
|
658
|
-
if (pageSurfaceScope.kind === "scoped") return [...pageSurfaceScope.courses];
|
|
659
|
-
if (contentEntry?.id) {
|
|
660
|
-
const matchedCourses = allCourses.filter((c) => c.contentEntryId === contentEntry.id);
|
|
661
|
-
if (matchedCourses.length > 0) return matchedCourses;
|
|
662
|
-
}
|
|
663
|
-
if (contentEntry?.slug) {
|
|
664
|
-
const matchedCourse = allCourses.find((c) => c.slug === contentEntry.slug);
|
|
665
|
-
if (matchedCourse) return [matchedCourse];
|
|
666
|
-
}
|
|
667
|
-
return allCourses;
|
|
668
|
-
}, [
|
|
669
|
-
courses,
|
|
670
|
-
contentEntry?.id,
|
|
671
|
-
contentEntry?.slug,
|
|
672
|
-
entrySubrouteContext,
|
|
673
|
-
subject
|
|
674
|
-
]);
|
|
675
|
-
const [step, setStep] = useState(() => {
|
|
676
|
-
const enrollment = new URLSearchParams(window.location.search).get("enrollment");
|
|
677
|
-
const sessionId = getSessionIdFromUrl();
|
|
678
|
-
if (enrollment === "success" && sessionId) return "verifying-payment";
|
|
679
|
-
return scopedCourses.length === 1 ? "enter-details" : "select-course";
|
|
680
|
-
});
|
|
745
|
+
function useCourseRegistrationSelection(props) {
|
|
746
|
+
const scopedCourses = useMemo(() => selectScopedCourses(props), [props.courses, props.subject]);
|
|
747
|
+
const [step, setStep] = useState(() => initialStep(scopedCourses));
|
|
681
748
|
const [selectedCourse, setSelectedCourse] = useState(scopedCourses.length === 1 ? scopedCourses[0] ?? null : null);
|
|
682
749
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
|
|
683
750
|
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
});
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
const [eligibilityLoading, setEligibilityLoading] = useState(false);
|
|
697
|
-
const [eligibilityError, setEligibilityError] = useState(null);
|
|
698
|
-
const [courseEligibility, setCourseEligibility] = useState(null);
|
|
699
|
-
const [eligibleMemberships, setEligibleMemberships] = useState([]);
|
|
700
|
-
const [paymentChoice, setPaymentChoice] = useState("checkout");
|
|
701
|
-
const [selectedMembershipId, setSelectedMembershipId] = useState(null);
|
|
702
|
-
const [bookingMode, setBookingMode] = useState(null);
|
|
703
|
-
const waitlistClaim = useWaitlistClaim();
|
|
751
|
+
const goToStep = useCallback((nextStep) => {
|
|
752
|
+
setStep(nextStep);
|
|
753
|
+
}, []);
|
|
754
|
+
const chooseCourse = useCallback((course) => {
|
|
755
|
+
setSelectedCourse(course);
|
|
756
|
+
}, []);
|
|
757
|
+
const choosePricingOption = useCallback((pricingOptionId) => {
|
|
758
|
+
setSelectedPricingOptionId(pricingOptionId);
|
|
759
|
+
}, []);
|
|
760
|
+
const changeSlidingAmount = useCallback((amount) => {
|
|
761
|
+
setSelectedSlidingAmountInput(amount);
|
|
762
|
+
}, []);
|
|
704
763
|
const selectedCoursePricing = useMemo(() => selectedCourse ? resolveCoursePricingState(selectedCourse, selectedPricingOptionId, parseCurrencyInputToCents(selectedSlidingAmountInput)) : null, [
|
|
705
764
|
selectedCourse,
|
|
706
765
|
selectedPricingOptionId,
|
|
707
766
|
selectedSlidingAmountInput
|
|
708
767
|
]);
|
|
709
|
-
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(selectedCoursePricing);
|
|
710
|
-
const selectedCoursePricingPayload = buildCoursePricingOptionPayload(selectedCoursePricing);
|
|
711
|
-
const showSoldOutCourseError = () => {
|
|
712
|
-
setErrorMessage(courseEligibility?.reason ?? "This course is fully booked.");
|
|
713
|
-
setStep("error");
|
|
714
|
-
return true;
|
|
715
|
-
};
|
|
716
|
-
useEffect(() => {
|
|
717
|
-
let cancelled = false;
|
|
718
|
-
async function checkPortalAuth() {
|
|
719
|
-
if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
|
|
720
|
-
setPortalAuthState("unauthenticated");
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
setPortalAuthState("checking");
|
|
724
|
-
try {
|
|
725
|
-
const me = await api.getPortalProfile();
|
|
726
|
-
if (cancelled) return;
|
|
727
|
-
setPortalAuthState("authenticated");
|
|
728
|
-
setFormData((prev) => ({
|
|
729
|
-
...prev,
|
|
730
|
-
email: me.profile.email,
|
|
731
|
-
name: prev.name || me.profile.name,
|
|
732
|
-
phone: prev.phone || me.profile.phone || ""
|
|
733
|
-
}));
|
|
734
|
-
} catch {
|
|
735
|
-
if (cancelled) return;
|
|
736
|
-
setPortalAuthState("unauthenticated");
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
checkPortalAuth();
|
|
740
|
-
return () => {
|
|
741
|
-
cancelled = true;
|
|
742
|
-
};
|
|
743
|
-
}, [api]);
|
|
744
|
-
useEffect(() => {
|
|
745
|
-
const claim = waitlistClaim.claim;
|
|
746
|
-
if (!claim || claim.subject.kind !== "course") return;
|
|
747
|
-
const courseId = claim.subject.courseId;
|
|
748
|
-
const matchedCourse = scopedCourses.find((course) => course.id === courseId) ?? null;
|
|
749
|
-
if (!matchedCourse) {
|
|
750
|
-
setErrorMessage("This waitlist claim is for a different course.");
|
|
751
|
-
setStep("error");
|
|
752
|
-
return;
|
|
753
|
-
}
|
|
754
|
-
setSelectedCourse(matchedCourse);
|
|
755
|
-
setFormData((prev) => ({
|
|
756
|
-
...prev,
|
|
757
|
-
email: claim.prefill.email,
|
|
758
|
-
name: claim.prefill.name,
|
|
759
|
-
phone: claim.prefill.phone ?? "",
|
|
760
|
-
notes: claim.prefill.notes ?? ""
|
|
761
|
-
}));
|
|
762
|
-
if (step === "select-course") setStep("enter-details");
|
|
763
|
-
}, [
|
|
764
|
-
waitlistClaim.claim,
|
|
765
|
-
scopedCourses,
|
|
766
|
-
step
|
|
767
|
-
]);
|
|
768
|
-
useEffect(() => {
|
|
769
|
-
if (waitlistClaim.requiresPortalLogin) return;
|
|
770
|
-
if (!waitlistClaim.error) return;
|
|
771
|
-
setErrorMessage(waitlistClaim.error);
|
|
772
|
-
setStep("error");
|
|
773
|
-
}, [waitlistClaim.error, waitlistClaim.requiresPortalLogin]);
|
|
774
768
|
useEffect(() => {
|
|
775
769
|
if (!selectedCourse) {
|
|
776
770
|
setSelectedPricingOptionId(null);
|
|
777
771
|
setSelectedSlidingAmountInput("");
|
|
778
772
|
return;
|
|
779
773
|
}
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) return previous;
|
|
784
|
-
return defaultPricing.selectedOption?.id ?? null;
|
|
785
|
-
});
|
|
774
|
+
const selection = defaultCoursePricingSelection(resolveCoursePricingState(selectedCourse, null), selectedPricingOptionId);
|
|
775
|
+
setSelectedPricingOptionId(selection.pricingOptionId);
|
|
776
|
+
setSelectedSlidingAmountInput(selection.slidingAmountInput);
|
|
786
777
|
}, [selectedCourse]);
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
778
|
+
return {
|
|
779
|
+
scopedCourses,
|
|
780
|
+
step,
|
|
781
|
+
goToStep,
|
|
782
|
+
selectedCourse,
|
|
783
|
+
chooseCourse,
|
|
784
|
+
selectedPricingOptionId,
|
|
785
|
+
choosePricingOption,
|
|
786
|
+
selectedSlidingAmountInput,
|
|
787
|
+
changeSlidingAmount,
|
|
788
|
+
selectedCoursePricing
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
//#endregion
|
|
792
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCoursePaymentVerification.ts
|
|
793
|
+
function applyTerminalStatus(status, setters) {
|
|
794
|
+
if (status === "enrolled" || status === "completed") {
|
|
795
|
+
setters.setEnrollmentResult({
|
|
796
|
+
status: "enrolled",
|
|
797
|
+
usedMembership: false
|
|
798
|
+
});
|
|
799
|
+
setters.setStep("success");
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
if (status === "waitlist") {
|
|
803
|
+
setters.setEnrollmentResult({
|
|
804
|
+
status: "waitlist",
|
|
805
|
+
usedMembership: false
|
|
806
|
+
});
|
|
807
|
+
setters.setStep("waitlist");
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
setters.setErrorMessage("Payment did not complete. Please try again.");
|
|
811
|
+
setters.setStep("error");
|
|
812
|
+
return true;
|
|
813
|
+
}
|
|
814
|
+
async function pollCourseRegistrationStatus(api, sessionId, setters, isCancelled) {
|
|
815
|
+
const startedAt = Date.now();
|
|
816
|
+
while (!isCancelled()) {
|
|
817
|
+
try {
|
|
818
|
+
const result = await api.getWholeSeriesRegistrationStatus({ sessionId });
|
|
819
|
+
if (isCancelled()) return;
|
|
820
|
+
if (result.status !== "pending_payment") {
|
|
821
|
+
applyTerminalStatus(result.status, setters);
|
|
822
|
+
return;
|
|
814
823
|
}
|
|
824
|
+
} catch (cause) {
|
|
825
|
+
setters.setErrorMessage(cause instanceof Error ? cause.message : "Failed to verify payment");
|
|
815
826
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
waitlistClaim.token
|
|
826
|
-
]);
|
|
827
|
+
if (Date.now() - startedAt > 3e4) {
|
|
828
|
+
setters.setErrorMessage("Payment is still processing. Please check your email for confirmation.");
|
|
829
|
+
setters.setStep("error");
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
function useCoursePaymentVerification(api, setters) {
|
|
827
836
|
useEffect(() => {
|
|
828
837
|
let cancelled = false;
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
if (enrollment === "cancelled") {
|
|
833
|
-
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
834
|
-
setErrorMessage("Payment was cancelled. You can try again.");
|
|
835
|
-
setStep("error");
|
|
836
|
-
return;
|
|
837
|
-
}
|
|
838
|
-
if (enrollment !== "success" || !sessionId) return;
|
|
838
|
+
const enrollment = new URLSearchParams(window.location.search).get("enrollment");
|
|
839
|
+
const sessionId = getCourseCheckoutSessionId();
|
|
840
|
+
if (enrollment === "cancelled") {
|
|
839
841
|
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
while (!cancelled) {
|
|
844
|
-
try {
|
|
845
|
-
const status = await api.getCourseRegistrationStatus({ sessionId });
|
|
846
|
-
if (cancelled) return;
|
|
847
|
-
if (status.status === "enrolled" || status.status === "completed") {
|
|
848
|
-
setEnrollmentResult({
|
|
849
|
-
status: "enrolled",
|
|
850
|
-
usedMembership: false
|
|
851
|
-
});
|
|
852
|
-
setStep("success");
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
if (status.status === "waitlist") {
|
|
856
|
-
setEnrollmentResult({
|
|
857
|
-
status: "waitlist",
|
|
858
|
-
usedMembership: false
|
|
859
|
-
});
|
|
860
|
-
setStep("waitlist");
|
|
861
|
-
return;
|
|
862
|
-
}
|
|
863
|
-
if (status.status === "cancelled") {
|
|
864
|
-
setErrorMessage("Payment did not complete. Please try again.");
|
|
865
|
-
setStep("error");
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
} catch (error) {
|
|
869
|
-
setErrorMessage(error instanceof Error ? error.message : "Failed to verify payment");
|
|
870
|
-
}
|
|
871
|
-
if (Date.now() - startedAt > timeoutMs) {
|
|
872
|
-
setErrorMessage("Payment is still processing. Please check your email for confirmation.");
|
|
873
|
-
setStep("error");
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
877
|
-
}
|
|
842
|
+
setters.setErrorMessage("Payment was cancelled. You can try again.");
|
|
843
|
+
setters.setStep("error");
|
|
844
|
+
return;
|
|
878
845
|
}
|
|
879
|
-
|
|
846
|
+
if (enrollment !== "success" || !sessionId) return;
|
|
847
|
+
scrollToBlock(COURSE_REGISTRATION_ANCHOR_ID);
|
|
848
|
+
setters.setStep("verifying-payment");
|
|
849
|
+
pollCourseRegistrationStatus(api, sessionId, setters, () => cancelled);
|
|
880
850
|
return () => {
|
|
881
851
|
cancelled = true;
|
|
882
852
|
};
|
|
883
|
-
}, [
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
853
|
+
}, [
|
|
854
|
+
api,
|
|
855
|
+
setters.setEnrollmentResult,
|
|
856
|
+
setters.setErrorMessage,
|
|
857
|
+
setters.setStep
|
|
858
|
+
]);
|
|
859
|
+
}
|
|
860
|
+
//#endregion
|
|
861
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationActions.ts
|
|
862
|
+
function blocked(message, setters) {
|
|
863
|
+
setters.setErrorMessage(message);
|
|
864
|
+
setters.setStep("error");
|
|
865
|
+
return {
|
|
866
|
+
kind: "blocked",
|
|
867
|
+
message
|
|
888
868
|
};
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
869
|
+
}
|
|
870
|
+
function validateSubmission(state, setters) {
|
|
871
|
+
if (!state.selectedCourse) return {
|
|
872
|
+
kind: "blocked",
|
|
873
|
+
message: "Choose an available set of dates to continue."
|
|
892
874
|
};
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
875
|
+
const errors = validateFormData(state.formData);
|
|
876
|
+
setters.setErrors(errors);
|
|
877
|
+
if (Object.keys(errors).length > 0) return { kind: "validation-failed" };
|
|
878
|
+
const pricingMessage = getMissingCoursePricingSelectionMessage(state.pricing);
|
|
879
|
+
if (pricingMessage) return blocked(pricingMessage, setters);
|
|
880
|
+
if (!state.hasClaim && state.eligibility?.isFull && !state.eligibility.canJoinWaitlist) return blocked(state.eligibility.reason ?? "This course is fully booked.", setters);
|
|
881
|
+
if (isSpamProtectionEnabled() && !state.altchaSolution) return blocked("Please complete the verification check.", setters);
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
function enrollmentPayload(state, payment) {
|
|
885
|
+
return {
|
|
886
|
+
...registrantPayload(state),
|
|
887
|
+
paymentMethod: payment.method,
|
|
888
|
+
...payment.method === "membership" ? { customerMembershipId: payment.membershipId } : {}
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
function registrantPayload(state) {
|
|
892
|
+
return {
|
|
893
|
+
eventSeriesId: state.selectedCourse.eventSeriesId,
|
|
894
|
+
...buildCoursePricingOptionPayload(state.pricing),
|
|
895
|
+
email: state.formData.email.trim().toLowerCase(),
|
|
896
|
+
name: state.formData.name.trim(),
|
|
897
|
+
phone: state.formData.phone.trim() || void 0,
|
|
898
|
+
formData: { notes: state.formData.notes.trim() || void 0 },
|
|
899
|
+
altchaSolution: state.altchaSolution,
|
|
900
|
+
claimToken: state.claimToken ?? void 0
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
async function enroll(state, setters, payment) {
|
|
904
|
+
setters.setStep("submitting");
|
|
905
|
+
try {
|
|
906
|
+
const result = await state.api.registerForWholeSeries(enrollmentPayload(state, payment));
|
|
907
|
+
setters.setEnrollmentResult({
|
|
908
|
+
status: result.status,
|
|
909
|
+
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
910
|
+
usedMembership: payment.method === "membership"
|
|
911
|
+
});
|
|
912
|
+
setters.setStep(result.status === "waitlist" ? "waitlist" : "success");
|
|
913
|
+
return { kind: "state-updated" };
|
|
914
|
+
} catch (cause) {
|
|
915
|
+
const message = cause instanceof Error ? cause.message : "Booking failed";
|
|
916
|
+
setters.setErrorMessage(message);
|
|
917
|
+
setters.setStep("error");
|
|
918
|
+
return {
|
|
919
|
+
kind: "failed",
|
|
920
|
+
message
|
|
921
921
|
};
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
939
|
-
usedMembership: false
|
|
940
|
-
});
|
|
941
|
-
setStep(result.status === "waitlist" ? "waitlist" : "success");
|
|
942
|
-
return { kind: "state-updated" };
|
|
943
|
-
} catch (error) {
|
|
944
|
-
const message = error instanceof Error ? error.message : "Booking failed";
|
|
945
|
-
setErrorMessage(message);
|
|
946
|
-
setStep("error");
|
|
947
|
-
return {
|
|
948
|
-
kind: "failed",
|
|
949
|
-
message
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
if (requiresPayment && canUseMembership) {
|
|
954
|
-
setStep("select-payment");
|
|
955
|
-
return { kind: "state-updated" };
|
|
956
|
-
}
|
|
957
|
-
if (requiresPayment) {
|
|
958
|
-
setStep("submitting");
|
|
959
|
-
try {
|
|
960
|
-
const { successUrl, cancelUrl } = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
961
|
-
const checkoutResult = await api.createCourseCheckout({
|
|
962
|
-
courseId: selectedCourse.id,
|
|
963
|
-
...selectedCoursePricingPayload,
|
|
964
|
-
email: formData.email.trim().toLowerCase(),
|
|
965
|
-
name: formData.name.trim(),
|
|
966
|
-
phone: formData.phone.trim() || void 0,
|
|
967
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
968
|
-
altchaSolution,
|
|
969
|
-
discountCode: discountCode.trim() ? discountCode.trim() : void 0,
|
|
970
|
-
successUrl,
|
|
971
|
-
cancelUrl,
|
|
972
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
973
|
-
});
|
|
974
|
-
if (checkoutResult.bypassed) {
|
|
975
|
-
setEnrollmentResult({
|
|
976
|
-
status: "enrolled",
|
|
977
|
-
waitlistPosition: void 0,
|
|
978
|
-
usedMembership: false
|
|
979
|
-
});
|
|
980
|
-
setStep("success");
|
|
981
|
-
return { kind: "state-updated" };
|
|
982
|
-
}
|
|
983
|
-
if (!checkoutResult.checkoutUrl) throw new Error("Checkout URL missing");
|
|
984
|
-
setStep("redirecting");
|
|
985
|
-
if (options.onCheckoutRedirect) options.onCheckoutRedirect(checkoutResult.checkoutUrl);
|
|
986
|
-
else window.location.href = checkoutResult.checkoutUrl;
|
|
987
|
-
return {
|
|
988
|
-
kind: "checkout-redirect",
|
|
989
|
-
checkoutUrl: checkoutResult.checkoutUrl
|
|
990
|
-
};
|
|
991
|
-
} catch (error) {
|
|
992
|
-
const message = error instanceof Error ? error.message : "Checkout failed";
|
|
993
|
-
setErrorMessage(message);
|
|
994
|
-
setStep("error");
|
|
995
|
-
return {
|
|
996
|
-
kind: "failed",
|
|
997
|
-
message
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
setStep("submitting");
|
|
1002
|
-
try {
|
|
1003
|
-
const result = await api.enrollInCourse({
|
|
1004
|
-
courseId: selectedCourse.id,
|
|
1005
|
-
...selectedCoursePricingPayload,
|
|
1006
|
-
email: formData.email.trim().toLowerCase(),
|
|
1007
|
-
name: formData.name.trim(),
|
|
1008
|
-
phone: formData.phone.trim() || void 0,
|
|
1009
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
1010
|
-
altchaSolution,
|
|
1011
|
-
paymentMethod: "free",
|
|
1012
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
1013
|
-
});
|
|
1014
|
-
setEnrollmentResult({
|
|
1015
|
-
status: result.status,
|
|
1016
|
-
waitlistPosition: result.waitlistPosition ?? void 0,
|
|
1017
|
-
usedMembership: result.paymentMethod === "membership"
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
async function checkout(state, setters) {
|
|
925
|
+
setters.setStep("submitting");
|
|
926
|
+
try {
|
|
927
|
+
const urls = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
928
|
+
const result = await state.api.createWholeSeriesCheckout({
|
|
929
|
+
...registrantPayload(state),
|
|
930
|
+
discountCode: state.discountCode.trim() || void 0,
|
|
931
|
+
successUrl: urls.successUrl,
|
|
932
|
+
cancelUrl: urls.cancelUrl
|
|
933
|
+
});
|
|
934
|
+
if (result.bypassed) {
|
|
935
|
+
setters.setEnrollmentResult({
|
|
936
|
+
status: "enrolled",
|
|
937
|
+
usedMembership: false
|
|
1018
938
|
});
|
|
1019
|
-
setStep(
|
|
939
|
+
setters.setStep("success");
|
|
1020
940
|
return { kind: "state-updated" };
|
|
1021
|
-
} catch (error) {
|
|
1022
|
-
const message = error instanceof Error ? error.message : "Booking failed";
|
|
1023
|
-
setErrorMessage(message);
|
|
1024
|
-
setStep("error");
|
|
1025
|
-
return {
|
|
1026
|
-
kind: "failed",
|
|
1027
|
-
message
|
|
1028
|
-
};
|
|
1029
941
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
if (
|
|
1033
|
-
|
|
1034
|
-
|
|
942
|
+
if (!result.checkoutUrl) throw new Error("Checkout URL missing");
|
|
943
|
+
setters.setStep("redirecting");
|
|
944
|
+
if (state.options.onCheckoutRedirect) state.options.onCheckoutRedirect(result.checkoutUrl);
|
|
945
|
+
else window.location.href = result.checkoutUrl;
|
|
946
|
+
return {
|
|
947
|
+
kind: "checkout-redirect",
|
|
948
|
+
checkoutUrl: result.checkoutUrl
|
|
1035
949
|
};
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
};
|
|
1044
|
-
}
|
|
1045
|
-
const requiresPayment = selectedCoursePricing?.selectedRequiresPayment ?? false;
|
|
1046
|
-
if (!waitlistClaim.claim && courseEligibility?.isFull && !courseEligibility.canJoinWaitlist && showSoldOutCourseError()) return {
|
|
1047
|
-
kind: "blocked",
|
|
1048
|
-
message: courseEligibility.reason ?? "This course is fully booked."
|
|
950
|
+
} catch (cause) {
|
|
951
|
+
const message = cause instanceof Error ? cause.message : "Checkout failed";
|
|
952
|
+
setters.setErrorMessage(message);
|
|
953
|
+
setters.setStep("error");
|
|
954
|
+
return {
|
|
955
|
+
kind: "failed",
|
|
956
|
+
message
|
|
1049
957
|
};
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
setStep("error");
|
|
1098
|
-
return {
|
|
1099
|
-
kind: "failed",
|
|
1100
|
-
message
|
|
1101
|
-
};
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
setStep("submitting");
|
|
1105
|
-
try {
|
|
1106
|
-
const { successUrl, cancelUrl } = buildCheckoutReturnUrls("enrollment", COURSE_REGISTRATION_ANCHOR_ID);
|
|
1107
|
-
const checkoutResult = await api.createCourseCheckout({
|
|
1108
|
-
courseId: selectedCourse.id,
|
|
1109
|
-
...selectedCoursePricingPayload,
|
|
1110
|
-
email: formData.email.trim().toLowerCase(),
|
|
1111
|
-
name: formData.name.trim(),
|
|
1112
|
-
phone: formData.phone.trim() || void 0,
|
|
1113
|
-
formData: { notes: formData.notes.trim() || void 0 },
|
|
1114
|
-
altchaSolution,
|
|
1115
|
-
discountCode: discountCode.trim() ? discountCode.trim() : void 0,
|
|
1116
|
-
successUrl,
|
|
1117
|
-
cancelUrl,
|
|
1118
|
-
claimToken: waitlistClaim.token ?? void 0
|
|
1119
|
-
});
|
|
1120
|
-
if (checkoutResult.bypassed) {
|
|
1121
|
-
setEnrollmentResult({
|
|
1122
|
-
status: "enrolled",
|
|
1123
|
-
waitlistPosition: void 0,
|
|
1124
|
-
usedMembership: false
|
|
1125
|
-
});
|
|
1126
|
-
setStep("success");
|
|
1127
|
-
return { kind: "state-updated" };
|
|
1128
|
-
}
|
|
1129
|
-
if (!checkoutResult.checkoutUrl) throw new Error("Checkout URL missing");
|
|
1130
|
-
setStep("redirecting");
|
|
1131
|
-
if (options.onCheckoutRedirect) options.onCheckoutRedirect(checkoutResult.checkoutUrl);
|
|
1132
|
-
else window.location.href = checkoutResult.checkoutUrl;
|
|
1133
|
-
return {
|
|
1134
|
-
kind: "checkout-redirect",
|
|
1135
|
-
checkoutUrl: checkoutResult.checkoutUrl
|
|
1136
|
-
};
|
|
1137
|
-
} catch (error) {
|
|
1138
|
-
const message = error instanceof Error ? error.message : "Checkout failed";
|
|
1139
|
-
setErrorMessage(message);
|
|
1140
|
-
setStep("error");
|
|
1141
|
-
return {
|
|
1142
|
-
kind: "failed",
|
|
1143
|
-
message
|
|
1144
|
-
};
|
|
1145
|
-
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
async function submitDetails(state, setters) {
|
|
961
|
+
const invalid = validateSubmission(state, setters);
|
|
962
|
+
if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
|
|
963
|
+
if (state.eligibility?.canJoinWaitlist) return enroll(state, setters, { method: "free" });
|
|
964
|
+
const requiresPayment = state.pricing?.selectedRequiresPayment ?? false;
|
|
965
|
+
const canUseMembership = requiresPayment && state.selectedCourse.acceptsMemberships && state.portalAuthState === "authenticated" && state.eligibleMemberships.length > 0;
|
|
966
|
+
if (requiresPayment && canUseMembership) {
|
|
967
|
+
setters.setStep("select-payment");
|
|
968
|
+
return { kind: "state-updated" };
|
|
969
|
+
}
|
|
970
|
+
if (requiresPayment) return checkout(state, setters);
|
|
971
|
+
return enroll(state, setters, { method: "free" });
|
|
972
|
+
}
|
|
973
|
+
async function continuePayment(state, setters) {
|
|
974
|
+
const invalid = validateSubmission(state, setters);
|
|
975
|
+
if (invalid || !state.selectedCourse) return invalid ?? { kind: "validation-failed" };
|
|
976
|
+
if (!state.pricing?.selectedRequiresPayment) {
|
|
977
|
+
setters.setStep("enter-details");
|
|
978
|
+
return { kind: "state-updated" };
|
|
979
|
+
}
|
|
980
|
+
const selectedState = state;
|
|
981
|
+
if (state.paymentChoice === "membership") {
|
|
982
|
+
if (!state.selectedMembershipId) return blocked("Select a membership to sign up.", setters);
|
|
983
|
+
return enroll(selectedState, setters, {
|
|
984
|
+
method: "membership",
|
|
985
|
+
membershipId: state.selectedMembershipId
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
return checkout(selectedState, setters);
|
|
989
|
+
}
|
|
990
|
+
function useCourseRegistrationActions(state, setStep) {
|
|
991
|
+
const [errors, setErrors] = useState({});
|
|
992
|
+
const [enrollmentResult, setEnrollmentResult] = useState(null);
|
|
993
|
+
const [errorMessage, setErrorMessage] = useState("");
|
|
994
|
+
const reportError = useCallback((message) => {
|
|
995
|
+
setErrorMessage(message);
|
|
996
|
+
}, []);
|
|
997
|
+
const recordEnrollmentResult = useCallback((result) => {
|
|
998
|
+
setEnrollmentResult(result);
|
|
999
|
+
}, []);
|
|
1000
|
+
const setters = {
|
|
1001
|
+
setStep,
|
|
1002
|
+
setErrors,
|
|
1003
|
+
setEnrollmentResult,
|
|
1004
|
+
setErrorMessage
|
|
1146
1005
|
};
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1006
|
+
return {
|
|
1007
|
+
errors,
|
|
1008
|
+
enrollmentResult,
|
|
1009
|
+
errorMessage,
|
|
1010
|
+
reportError,
|
|
1011
|
+
recordEnrollmentResult,
|
|
1012
|
+
handleSubmit: () => submitDetails(state, setters),
|
|
1013
|
+
handlePaymentContinue: () => continuePayment(state, setters)
|
|
1150
1014
|
};
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1015
|
+
}
|
|
1016
|
+
//#endregion
|
|
1017
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationPortal.ts
|
|
1018
|
+
const EMPTY_FORM = {
|
|
1019
|
+
name: "",
|
|
1020
|
+
email: "",
|
|
1021
|
+
phone: "",
|
|
1022
|
+
notes: ""
|
|
1023
|
+
};
|
|
1024
|
+
function useCourseRegistrationPortal(api) {
|
|
1025
|
+
const [formData, setFormData] = useState(EMPTY_FORM);
|
|
1026
|
+
const [portalAuthState, setPortalAuthState] = useState("checking");
|
|
1027
|
+
const updateFormData = useCallback((updater) => {
|
|
1028
|
+
setFormData(updater);
|
|
1029
|
+
}, []);
|
|
1030
|
+
useEffect(() => {
|
|
1031
|
+
let cancelled = false;
|
|
1032
|
+
if (!(api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer")) {
|
|
1033
|
+
setPortalAuthState("unauthenticated");
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
setPortalAuthState("checking");
|
|
1037
|
+
api.getPortalProfile().then((result) => {
|
|
1038
|
+
if (cancelled) return;
|
|
1039
|
+
setPortalAuthState("authenticated");
|
|
1040
|
+
setFormData((current) => ({
|
|
1041
|
+
...current,
|
|
1042
|
+
email: result.profile.email,
|
|
1043
|
+
name: current.name || result.profile.name,
|
|
1044
|
+
phone: current.phone || result.profile.phone || ""
|
|
1045
|
+
}));
|
|
1046
|
+
}).catch(() => {
|
|
1047
|
+
if (!cancelled) setPortalAuthState("unauthenticated");
|
|
1048
|
+
});
|
|
1049
|
+
return () => {
|
|
1050
|
+
cancelled = true;
|
|
1051
|
+
};
|
|
1052
|
+
}, [api]);
|
|
1053
|
+
return {
|
|
1054
|
+
formData,
|
|
1055
|
+
updateFormData,
|
|
1056
|
+
portalAuthState
|
|
1155
1057
|
};
|
|
1058
|
+
}
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseWaitlistSelection.ts
|
|
1061
|
+
function useCourseWaitlistSelection(input) {
|
|
1062
|
+
useEffect(() => {
|
|
1063
|
+
const claim = input.waitlistClaim.claim;
|
|
1064
|
+
if (!claim || claim.subject.kind !== "whole_series") return;
|
|
1065
|
+
const eventSeriesId = claim.subject.eventSeriesId;
|
|
1066
|
+
const course = input.scopedCourses.find((candidate) => candidate.eventSeriesId === eventSeriesId);
|
|
1067
|
+
if (!course) {
|
|
1068
|
+
input.reportError("This waitlist claim is for a different course.");
|
|
1069
|
+
input.goToStep("error");
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
input.chooseCourse(course);
|
|
1073
|
+
input.updateFormData((current) => ({
|
|
1074
|
+
...current,
|
|
1075
|
+
email: claim.prefill.email,
|
|
1076
|
+
name: claim.prefill.name,
|
|
1077
|
+
phone: claim.prefill.phone ?? "",
|
|
1078
|
+
notes: claim.prefill.notes ?? ""
|
|
1079
|
+
}));
|
|
1080
|
+
if (input.step === "select-course") input.goToStep("enter-details");
|
|
1081
|
+
}, [
|
|
1082
|
+
input.chooseCourse,
|
|
1083
|
+
input.goToStep,
|
|
1084
|
+
input.reportError,
|
|
1085
|
+
input.scopedCourses,
|
|
1086
|
+
input.step,
|
|
1087
|
+
input.updateFormData,
|
|
1088
|
+
input.waitlistClaim.claim
|
|
1089
|
+
]);
|
|
1090
|
+
useEffect(() => {
|
|
1091
|
+
if (input.waitlistClaim.requiresPortalLogin || !input.waitlistClaim.error) return;
|
|
1092
|
+
input.reportError(input.waitlistClaim.error);
|
|
1093
|
+
input.goToStep("error");
|
|
1094
|
+
}, [
|
|
1095
|
+
input.goToStep,
|
|
1096
|
+
input.reportError,
|
|
1097
|
+
input.waitlistClaim.error,
|
|
1098
|
+
input.waitlistClaim.requiresPortalLogin
|
|
1099
|
+
]);
|
|
1100
|
+
}
|
|
1101
|
+
//#endregion
|
|
1102
|
+
//#region ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
1103
|
+
function useCourseRegistrationWizard(props, options = {}) {
|
|
1104
|
+
const api = useBlockApi();
|
|
1105
|
+
const selection = useCourseRegistrationSelection(props);
|
|
1106
|
+
const portal = useCourseRegistrationPortal(api);
|
|
1107
|
+
const waitlistClaim = useWaitlistClaim();
|
|
1108
|
+
const [bookingMode, setBookingMode] = useState(null);
|
|
1109
|
+
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
1110
|
+
const eligibility = useCourseEligibility({
|
|
1111
|
+
api,
|
|
1112
|
+
selectedCourse: selection.selectedCourse,
|
|
1113
|
+
hasPaidSelection: selection.selectedCoursePricing?.hasPaidSelection ?? false,
|
|
1114
|
+
portalAuthState: portal.portalAuthState,
|
|
1115
|
+
waitlistClaimToken: waitlistClaim.token
|
|
1116
|
+
});
|
|
1156
1117
|
const discountUi = useDiscountCodeUi({
|
|
1157
1118
|
api,
|
|
1158
|
-
discountContext: useMemo(() => {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
};
|
|
1166
|
-
}, [
|
|
1167
|
-
selectedCourse,
|
|
1168
|
-
selectedCoursePricing?.selectedRequiresPayment,
|
|
1169
|
-
paymentChoice
|
|
1119
|
+
discountContext: useMemo(() => selection.selectedCourse && selection.selectedCoursePricing?.selectedRequiresPayment && eligibility.paymentChoice === "checkout" ? {
|
|
1120
|
+
type: "whole_series",
|
|
1121
|
+
eventSeriesId: selection.selectedCourse.eventSeriesId
|
|
1122
|
+
} : null, [
|
|
1123
|
+
eligibility.paymentChoice,
|
|
1124
|
+
selection.selectedCourse,
|
|
1125
|
+
selection.selectedCoursePricing?.selectedRequiresPayment
|
|
1170
1126
|
]),
|
|
1171
|
-
subtotalCents: selectedCoursePricing?.selectedPriceAmount ?? void 0
|
|
1127
|
+
subtotalCents: selection.selectedCoursePricing?.selectedPriceAmount ?? void 0
|
|
1172
1128
|
});
|
|
1173
|
-
const
|
|
1174
|
-
const hasCoursePayment = resolveHasCoursePayment(selectedCoursePricing);
|
|
1175
|
-
const canUseMembership = hasCoursePayment && selectedCourse?.acceptsMemberships === true && portalAuthState === "authenticated" && eligibleMemberships.length > 0;
|
|
1176
|
-
const hasPreSelectedCourse = scopedCourses.length === 1;
|
|
1177
|
-
const isMembershipFastTrack = canUseMembership && eligibleMemberships.length === 1 && bookingMode === "membership";
|
|
1178
|
-
const wizardSteps = useMemo(() => getWizardStepsForContext(hasPreSelectedCourse, hasCoursePayment, canUseMembership, bookingMode, isMembershipFastTrack), [
|
|
1179
|
-
hasPreSelectedCourse,
|
|
1180
|
-
hasCoursePayment,
|
|
1181
|
-
canUseMembership,
|
|
1182
|
-
bookingMode,
|
|
1183
|
-
isMembershipFastTrack
|
|
1184
|
-
]);
|
|
1185
|
-
const currentStepNumber = getStepNumber(step, wizardSteps);
|
|
1186
|
-
const totalSteps = wizardSteps.length;
|
|
1187
|
-
const stepLabels = getStepLabels(wizardSteps);
|
|
1188
|
-
const canShowPortalAuthSidebarOnCurrentStep = step !== "success" && step !== "waitlist" && step !== "error";
|
|
1189
|
-
const showPortalAuthSidebar = portalAuthState === "unauthenticated" && waitlistClaim.requiresPortalLogin && canShowPortalAuthSidebarOnCurrentStep || portalAuthState === "unauthenticated" && hasCoursePayment && selectedCourse?.acceptsMemberships === true && step !== "select-course" && canShowPortalAuthSidebarOnCurrentStep;
|
|
1190
|
-
return {
|
|
1129
|
+
const actions = useCourseRegistrationActions({
|
|
1191
1130
|
api,
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
formData,
|
|
1203
|
-
setFormData,
|
|
1204
|
-
errors,
|
|
1205
|
-
enrollmentResult,
|
|
1206
|
-
errorMessage,
|
|
1207
|
-
portalAuthState,
|
|
1208
|
-
handleLogout: portalAuthState === "authenticated" ? () => logoutPortal(COURSE_REGISTRATION_ANCHOR_ID) : void 0,
|
|
1131
|
+
selectedCourse: selection.selectedCourse,
|
|
1132
|
+
pricing: selection.selectedCoursePricing,
|
|
1133
|
+
formData: portal.formData,
|
|
1134
|
+
portalAuthState: portal.portalAuthState,
|
|
1135
|
+
eligibility: eligibility.courseEligibility,
|
|
1136
|
+
eligibleMemberships: eligibility.eligibleMemberships,
|
|
1137
|
+
paymentChoice: eligibility.paymentChoice,
|
|
1138
|
+
selectedMembershipId: eligibility.selectedMembershipId,
|
|
1139
|
+
claimToken: waitlistClaim.token,
|
|
1140
|
+
hasClaim: waitlistClaim.claim !== null,
|
|
1209
1141
|
altchaSolution,
|
|
1210
|
-
setAltchaSolution,
|
|
1211
|
-
showSpamProtection,
|
|
1212
|
-
eligibilityLoading,
|
|
1213
|
-
eligibilityError,
|
|
1214
|
-
courseEligibility,
|
|
1215
|
-
eligibleMemberships,
|
|
1216
|
-
paymentChoice,
|
|
1217
|
-
setPaymentChoice,
|
|
1218
|
-
selectedMembershipId,
|
|
1219
|
-
setSelectedMembershipId,
|
|
1220
|
-
discountUiOpen: discountUi.discountUiOpen,
|
|
1221
|
-
setDiscountUiOpen: discountUi.setDiscountUiOpen,
|
|
1222
1142
|
discountCode: discountUi.discountCode,
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1143
|
+
options
|
|
1144
|
+
}, selection.goToStep);
|
|
1145
|
+
useCourseRegistrationEffects({
|
|
1146
|
+
api,
|
|
1147
|
+
actions,
|
|
1148
|
+
portal,
|
|
1149
|
+
selection,
|
|
1150
|
+
waitlistClaim
|
|
1151
|
+
});
|
|
1152
|
+
return buildCourseRegistrationWizardResult({
|
|
1153
|
+
api,
|
|
1154
|
+
selection,
|
|
1155
|
+
portal,
|
|
1156
|
+
eligibility,
|
|
1157
|
+
actions,
|
|
1158
|
+
discountUi,
|
|
1228
1159
|
waitlistClaim,
|
|
1160
|
+
view: deriveCourseRegistrationViewState({
|
|
1161
|
+
scopedCourses: selection.scopedCourses,
|
|
1162
|
+
selectedCourse: selection.selectedCourse,
|
|
1163
|
+
pricing: selection.selectedCoursePricing,
|
|
1164
|
+
portalAuthState: portal.portalAuthState,
|
|
1165
|
+
eligibleMembershipCount: eligibility.eligibleMemberships.length,
|
|
1166
|
+
bookingMode,
|
|
1167
|
+
step: selection.step,
|
|
1168
|
+
waitlistRequiresPortalLogin: waitlistClaim.requiresPortalLogin
|
|
1169
|
+
}),
|
|
1229
1170
|
bookingMode,
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1171
|
+
setBookingMode,
|
|
1172
|
+
altchaSolution,
|
|
1173
|
+
setAltchaSolution
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
function useCourseRegistrationEffects(input) {
|
|
1177
|
+
useCoursePaymentVerification(input.api, {
|
|
1178
|
+
setStep: input.selection.goToStep,
|
|
1179
|
+
setErrorMessage: input.actions.reportError,
|
|
1180
|
+
setEnrollmentResult: input.actions.recordEnrollmentResult
|
|
1181
|
+
});
|
|
1182
|
+
useCourseWaitlistSelection({
|
|
1183
|
+
waitlistClaim: input.waitlistClaim,
|
|
1184
|
+
scopedCourses: input.selection.scopedCourses,
|
|
1185
|
+
step: input.selection.step,
|
|
1186
|
+
goToStep: input.selection.goToStep,
|
|
1187
|
+
chooseCourse: input.selection.chooseCourse,
|
|
1188
|
+
updateFormData: input.portal.updateFormData,
|
|
1189
|
+
reportError: input.actions.reportError
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
function buildCourseRegistrationWizardResult(parts) {
|
|
1193
|
+
const handleBookingModeChange = (mode) => {
|
|
1194
|
+
parts.setBookingMode(mode);
|
|
1195
|
+
parts.eligibility.choosePaymentChoice(mode === "membership" ? "membership" : "checkout");
|
|
1196
|
+
};
|
|
1197
|
+
return {
|
|
1198
|
+
api: parts.api,
|
|
1199
|
+
...parts.selection,
|
|
1200
|
+
...parts.portal,
|
|
1201
|
+
...parts.eligibility,
|
|
1202
|
+
...parts.actions,
|
|
1203
|
+
waitlistClaim: parts.waitlistClaim,
|
|
1204
|
+
bookingMode: parts.bookingMode,
|
|
1205
|
+
altchaSolution: parts.altchaSolution,
|
|
1206
|
+
setAltchaSolution: parts.setAltchaSolution,
|
|
1207
|
+
showSpamProtection: isSpamProtectionEnabled(),
|
|
1208
|
+
discountUiOpen: parts.discountUi.discountUiOpen,
|
|
1209
|
+
setDiscountUiOpen: parts.discountUi.setDiscountUiOpen,
|
|
1210
|
+
discountCode: parts.discountUi.discountCode,
|
|
1211
|
+
setDiscountCode: parts.discountUi.setDiscountCode,
|
|
1212
|
+
discountsAvailable: parts.discountUi.discountsAvailable,
|
|
1213
|
+
manualCodeEntryAllowed: parts.discountUi.manualCodeEntryAllowed,
|
|
1214
|
+
discountsAvailableLoading: parts.discountUi.discountsAvailableLoading,
|
|
1215
|
+
...parts.view,
|
|
1216
|
+
handleCourseSelect: (course) => {
|
|
1217
|
+
parts.selection.chooseCourse(course);
|
|
1218
|
+
parts.selection.goToStep("enter-details");
|
|
1219
|
+
},
|
|
1220
|
+
handleRetry: () => {
|
|
1221
|
+
parts.selection.goToStep(parts.selection.scopedCourses.length === 1 ? "enter-details" : "select-course");
|
|
1222
|
+
parts.actions.reportError("");
|
|
1223
|
+
},
|
|
1224
|
+
handleBookingModeChange,
|
|
1225
|
+
handleLogout: parts.portal.portalAuthState === "authenticated" ? () => logoutPortal(COURSE_REGISTRATION_ANCHOR_ID) : void 0,
|
|
1226
|
+
selectedCoursePricingPayload: buildCoursePricingOptionPayload(parts.selection.selectedCoursePricing)
|
|
1242
1227
|
};
|
|
1243
1228
|
}
|
|
1244
1229
|
//#endregion
|
|
@@ -1654,7 +1639,7 @@ function getCourseSlidingScaleMessage(pricing) {
|
|
|
1654
1639
|
}
|
|
1655
1640
|
function CourseRegistrationWizard(props) {
|
|
1656
1641
|
const { showSessions = true, showPrice = true, showCapacity = true, showVenue = true, successMessage = "You're booked in! Check your email for confirmation and session details.", waitlistMessage = "You've been added to the waitlist. We'll email you a claim link if a spot opens up.", membershipMessage = "Booked using your membership! Check your email for session details.", buttonText = "Sign up", buttonVariant = "primary", className } = props;
|
|
1657
|
-
const { api, scopedCourses, step,
|
|
1642
|
+
const { api, scopedCourses, step, goToStep, selectedCourse, selectedPricingOptionId, choosePricingOption, selectedSlidingAmountInput, changeSlidingAmount, selectedCoursePricing, formData, updateFormData, errors, enrollmentResult, errorMessage, portalAuthState, handleLogout, altchaSolution: _altchaSolution, setAltchaSolution, showSpamProtection, eligibilityLoading, eligibilityError, courseEligibility, eligibleMemberships, paymentChoice, choosePaymentChoice, selectedMembershipId, chooseMembership, discountUiOpen, setDiscountUiOpen, discountCode, setDiscountCode, discountsAvailable, manualCodeEntryAllowed, discountsAvailableLoading, waitlistClaim, canUseMembership: _canUseMembership, bookingMode, currentStepNumber, totalSteps, stepLabels, showPortalAuthSidebar, hasPreSelectedCourse: _hasPreSelectedCourse, hasCoursePayment: _hasCoursePayment, handleCourseSelect, handleSubmit, handlePaymentContinue, handleRetry, handleBookingModeChange } = useCourseRegistrationWizard(props);
|
|
1658
1643
|
const buttonClass = themeButtonClassName({
|
|
1659
1644
|
variant: buttonVariant,
|
|
1660
1645
|
size: "md"
|
|
@@ -1719,13 +1704,13 @@ function CourseRegistrationWizard(props) {
|
|
|
1719
1704
|
className: "cr-course-list",
|
|
1720
1705
|
children: scopedCourses.map((course) => /* @__PURE__ */ jsx(CourseCard, {
|
|
1721
1706
|
course,
|
|
1722
|
-
isSelected: selectedCourse?.
|
|
1707
|
+
isSelected: selectedCourse?.eventSeriesId === course.eventSeriesId,
|
|
1723
1708
|
onSelect: () => handleCourseSelect(course),
|
|
1724
1709
|
showSessions,
|
|
1725
1710
|
showPrice,
|
|
1726
1711
|
showCapacity,
|
|
1727
1712
|
showVenue
|
|
1728
|
-
}, course.
|
|
1713
|
+
}, course.eventSeriesId))
|
|
1729
1714
|
}),
|
|
1730
1715
|
step === "enter-details" && selectedCourseWithPricing && /* @__PURE__ */ jsxs("div", {
|
|
1731
1716
|
className: "cr-details",
|
|
@@ -1742,7 +1727,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1742
1727
|
className: "cr-actions",
|
|
1743
1728
|
children: /* @__PURE__ */ jsx("button", {
|
|
1744
1729
|
type: "button",
|
|
1745
|
-
onClick: () =>
|
|
1730
|
+
onClick: () => goToStep("select-course"),
|
|
1746
1731
|
className: "cr-back-btn",
|
|
1747
1732
|
children: "← Back"
|
|
1748
1733
|
})
|
|
@@ -1761,7 +1746,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1761
1746
|
/* @__PURE__ */ jsx(EnrollmentForm, {
|
|
1762
1747
|
formData,
|
|
1763
1748
|
errors,
|
|
1764
|
-
onChange:
|
|
1749
|
+
onChange: updateFormData,
|
|
1765
1750
|
isEmailLocked: portalAuthState === "authenticated" || waitlistClaim.claim !== null,
|
|
1766
1751
|
isLoading: portalAuthState === "checking" || waitlistClaim.isLoading,
|
|
1767
1752
|
onLogout: handleLogout
|
|
@@ -1769,12 +1754,12 @@ function CourseRegistrationWizard(props) {
|
|
|
1769
1754
|
/* @__PURE__ */ jsx(CoursePricingSelector, {
|
|
1770
1755
|
pricing: selectedCourseWithPricing.pricing,
|
|
1771
1756
|
selectedPricingOptionId,
|
|
1772
|
-
onSelect:
|
|
1757
|
+
onSelect: choosePricingOption
|
|
1773
1758
|
}),
|
|
1774
1759
|
/* @__PURE__ */ jsx(CourseSlidingScaleInput, {
|
|
1775
1760
|
pricing: selectedCourseWithPricing.pricing,
|
|
1776
1761
|
value: selectedSlidingAmountInput,
|
|
1777
|
-
onChange:
|
|
1762
|
+
onChange: changeSlidingAmount
|
|
1778
1763
|
}),
|
|
1779
1764
|
showSpamProtection && /* @__PURE__ */ jsx("div", {
|
|
1780
1765
|
className: "cr-altcha",
|
|
@@ -1799,7 +1784,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1799
1784
|
className: "cr-actions",
|
|
1800
1785
|
children: [scopedCourses.length > 1 && /* @__PURE__ */ jsx("button", {
|
|
1801
1786
|
type: "button",
|
|
1802
|
-
onClick: () =>
|
|
1787
|
+
onClick: () => goToStep("select-course"),
|
|
1803
1788
|
className: "cr-back-btn",
|
|
1804
1789
|
children: "← Back"
|
|
1805
1790
|
}), /* @__PURE__ */ jsx("button", {
|
|
@@ -1849,7 +1834,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1849
1834
|
onBookingModeChange: handleBookingModeChange,
|
|
1850
1835
|
eligibleMemberships,
|
|
1851
1836
|
selectedMembershipId,
|
|
1852
|
-
onMembershipSelect:
|
|
1837
|
+
onMembershipSelect: chooseMembership,
|
|
1853
1838
|
priceCents: selectedCoursePricing?.selectedPriceAmount ?? null,
|
|
1854
1839
|
currency: selectedCourseWithPricing.course.currency ?? "GBP"
|
|
1855
1840
|
}),
|
|
@@ -1857,7 +1842,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1857
1842
|
className: "cr-actions",
|
|
1858
1843
|
children: [/* @__PURE__ */ jsx("button", {
|
|
1859
1844
|
type: "button",
|
|
1860
|
-
onClick: () =>
|
|
1845
|
+
onClick: () => goToStep("enter-details"),
|
|
1861
1846
|
className: "cr-back-btn",
|
|
1862
1847
|
children: "← Back"
|
|
1863
1848
|
}), /* @__PURE__ */ jsx("button", {
|
|
@@ -1896,7 +1881,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1896
1881
|
type: "radio",
|
|
1897
1882
|
name: "paymentChoice",
|
|
1898
1883
|
checked: paymentChoice === "membership",
|
|
1899
|
-
onChange: () =>
|
|
1884
|
+
onChange: () => choosePaymentChoice("membership")
|
|
1900
1885
|
}), /* @__PURE__ */ jsx("span", { children: "Use a membership (free)" })]
|
|
1901
1886
|
}),
|
|
1902
1887
|
paymentChoice === "membership" && eligibleMemberships.length > 1 && /* @__PURE__ */ jsxs("div", {
|
|
@@ -1909,7 +1894,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1909
1894
|
id: "cr-membership",
|
|
1910
1895
|
className: "cr-form__input",
|
|
1911
1896
|
value: selectedMembershipId ?? "",
|
|
1912
|
-
onChange: (e) =>
|
|
1897
|
+
onChange: (e) => chooseMembership(e.target.value || null),
|
|
1913
1898
|
children: [/* @__PURE__ */ jsx("option", {
|
|
1914
1899
|
value: "",
|
|
1915
1900
|
disabled: true,
|
|
@@ -1926,7 +1911,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1926
1911
|
type: "radio",
|
|
1927
1912
|
name: "paymentChoice",
|
|
1928
1913
|
checked: paymentChoice === "checkout",
|
|
1929
|
-
onChange: () =>
|
|
1914
|
+
onChange: () => choosePaymentChoice("checkout")
|
|
1930
1915
|
}), /* @__PURE__ */ jsx("span", { children: "Pay by card" })]
|
|
1931
1916
|
})
|
|
1932
1917
|
]
|
|
@@ -1948,7 +1933,7 @@ function CourseRegistrationWizard(props) {
|
|
|
1948
1933
|
className: "cr-actions",
|
|
1949
1934
|
children: [/* @__PURE__ */ jsx("button", {
|
|
1950
1935
|
type: "button",
|
|
1951
|
-
onClick: () =>
|
|
1936
|
+
onClick: () => goToStep("enter-details"),
|
|
1952
1937
|
className: "cr-back-btn",
|
|
1953
1938
|
children: "← Back"
|
|
1954
1939
|
}), /* @__PURE__ */ jsx("button", {
|