@riverbankcms/sdk 0.147.0 → 0.149.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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/dist/{PreviewEditorSidebar-DtpB3_sS.mjs → PreviewEditorSidebar-DBKln68M.mjs} +301 -205
- package/dist/{PreviewEditorUI-DxTLgaHo.mjs → PreviewEditorUI-DpRX4Mum.mjs} +68 -63
- package/dist/{PreviewQueryProvider-Dd4dxOiU.mjs → PreviewQueryProvider-C0mndwHB.mjs} +3 -3
- package/dist/{SdkPreviewModeRuntime-DMMNCngt.mjs → SdkPreviewModeRuntime-DJPmPY-r.mjs} +1247 -541
- package/dist/{SiteChromeCustomizeContext-DQXZXiqS.mjs → SiteChromeCustomizeContext-JYA0cJ_Z.mjs} +209720 -204978
- package/dist/_dts/ai/src/contracts/proposals.d.ts +0 -33
- package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +0 -3
- package/dist/_dts/api/src/accessAdmin.d.ts +0 -4
- package/dist/_dts/api/src/accountApi.d.ts +1 -1
- package/dist/_dts/api/src/admin.d.ts +22 -22
- package/dist/_dts/api/src/aiPatch.d.ts +2 -2
- package/dist/_dts/api/src/aiPlayground.d.ts +1 -0
- package/dist/_dts/api/src/analytics.d.ts +2 -2
- package/dist/_dts/api/src/apiEndpointTypes.d.ts +2 -0
- package/dist/_dts/api/src/appointmentSetup.d.ts +2 -2
- package/dist/_dts/api/src/auth.d.ts +10 -10
- package/dist/_dts/api/src/availability.d.ts +6 -6
- package/dist/_dts/api/src/billing.d.ts +42 -15
- package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +8 -0
- package/dist/_dts/api/src/billingEndpointTypes.d.ts +15 -6
- package/dist/_dts/api/src/blocks.d.ts +15 -14
- package/dist/_dts/api/src/blocksKeys.d.ts +2 -0
- package/dist/_dts/api/src/bookingConfig.d.ts +33 -50
- package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +2 -6
- package/dist/_dts/api/src/bookingOperations.d.ts +9 -11
- package/dist/_dts/api/src/bookingRecords.d.ts +16 -11
- package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +5 -5
- package/dist/_dts/api/src/bookings.d.ts +7 -7
- package/dist/_dts/api/src/calendar.d.ts +9 -9
- package/dist/_dts/api/src/clientErrorReporting.d.ts +11 -0
- package/dist/_dts/api/src/commercePortalEndpoints.d.ts +7 -8
- package/dist/_dts/api/src/common/cancellation.d.ts +23 -0
- package/dist/_dts/api/src/common/envelope.d.ts +2 -2
- package/dist/_dts/api/src/content-editor.d.ts +2 -2
- package/dist/_dts/api/src/contentEntries.d.ts +17 -48
- package/dist/_dts/api/src/contentRuntime.d.ts +51 -37
- package/dist/_dts/api/src/contentTypes.d.ts +11 -11
- package/dist/_dts/api/src/contentVersionHistoryClient.d.ts +6 -6
- package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +1 -1
- package/dist/_dts/api/src/documentLifecycle.d.ts +67 -0
- package/dist/_dts/api/src/domains.d.ts +16 -16
- package/dist/_dts/api/src/editLeaseEndpoints.d.ts +72 -0
- package/dist/_dts/api/src/emailSettings.d.ts +4 -4
- package/dist/_dts/api/src/endpoints.d.ts +135 -51
- package/dist/_dts/api/src/eventEmailTemplates.d.ts +2 -2
- package/dist/_dts/api/src/eventManagementContracts.d.ts +29 -7
- package/dist/_dts/api/src/eventManagementEndpointDefinitions.d.ts +0 -8
- package/dist/_dts/api/src/eventPageWords.d.ts +7 -12
- package/dist/_dts/api/src/footerSettings.d.ts +6 -6
- package/dist/_dts/api/src/index.d.ts +8 -7
- package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -0
- package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
- package/dist/_dts/api/src/navigation.d.ts +5 -5
- package/dist/_dts/api/src/pageSurfaceEditorEndpoints.d.ts +55 -0
- package/dist/_dts/api/src/pageSurfaceEndpoints.d.ts +28 -7
- package/dist/_dts/api/src/pages.d.ts +7 -7
- package/dist/_dts/api/src/performance.d.ts +1 -1
- package/dist/_dts/api/src/public/index.d.ts +1 -1
- package/dist/_dts/api/src/publicAppointmentBookingContracts.d.ts +4 -2
- package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +6 -29
- package/dist/_dts/api/src/redirects.d.ts +3 -3
- package/dist/_dts/api/src/request.d.ts +11 -2
- package/dist/_dts/api/src/resources.d.ts +4 -4
- package/dist/_dts/api/src/routes.d.ts +8 -3
- package/dist/_dts/api/src/sdk-event-upsert.d.ts +1 -2
- package/dist/_dts/api/src/sdkBlockUpsertContracts.d.ts +21 -0
- package/dist/_dts/api/src/sdkContracts.d.ts +5 -28
- package/dist/_dts/api/src/sdkEventEndpointDefinitions.d.ts +1 -1
- package/dist/_dts/api/src/sdkEventOccurrenceRequestContracts.d.ts +43 -0
- package/dist/_dts/api/src/sdkManagedEventContracts.d.ts +4 -2
- package/dist/_dts/api/src/sdkPullEventContracts.d.ts +9 -2
- package/dist/_dts/api/src/seo.d.ts +4 -4
- package/dist/_dts/api/src/services.d.ts +4 -4
- package/dist/_dts/api/src/siteManagementEndpoints.d.ts +15 -8
- package/dist/_dts/api/src/siteMembers.d.ts +10 -10
- package/dist/_dts/api/src/siteOnboarding.d.ts +14 -0
- package/dist/_dts/api/src/siteOperations.d.ts +6 -2
- package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +7 -3
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +5 -12
- package/dist/_dts/api/src/siteRuntimeEntry.d.ts +31 -0
- package/dist/_dts/billing/src/checkout/platform.d.ts +77 -0
- package/dist/_dts/billing/src/components/index.d.ts +25 -40
- package/dist/_dts/billing/src/membership/index.d.ts +1 -3
- package/dist/_dts/billing/src/plans/entitlements.d.ts +80 -0
- package/dist/_dts/billing/src/plans/registry.d.ts +16 -16
- package/dist/_dts/billing/src/plans/standing.d.ts +9 -2
- package/dist/_dts/billing/src/plans/types.d.ts +5 -15
- package/dist/_dts/billing/src/site-arrangements.d.ts +2 -2
- package/dist/_dts/billing/src/subscriptions/standingEvidence.d.ts +2 -4
- package/dist/_dts/billing/src/subscriptions/store.d.ts +17 -11
- package/dist/_dts/block-form/src/backend/store-backend.d.ts +6 -7
- package/dist/_dts/block-form/src/backend/types.d.ts +7 -0
- package/dist/_dts/block-form/src/widgets/FieldFrame.d.ts +3 -1
- package/dist/_dts/blocks/src/client/events.d.ts +3 -0
- package/dist/_dts/blocks/src/contracts/index.d.ts +1 -1
- package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +2 -2
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +54 -14
- package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +4 -13
- package/dist/_dts/blocks/src/pageRendererContracts.d.ts +2 -0
- package/dist/_dts/blocks/src/portal/types.d.ts +9 -8
- package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +2 -1
- package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +3 -1
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +28 -28
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +7 -2
- package/dist/_dts/blocks/src/system/blocks/shared/bookingPaymentTerms.d.ts +84 -160
- package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -2
- package/dist/_dts/blocks/src/system/blocks/shop.shared.d.ts +31 -4
- package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +2 -2
- 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 +4 -2
- package/dist/_dts/blocks/src/system/runtime/api/types/core.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/api/types/shop.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/components/booking/SuccessMessage.d.ts +4 -1
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +72 -12
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +36 -6
- package/dist/_dts/blocks/src/system/runtime/hooks/useBookingNowIso.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +3 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/usePaymentVerification.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/usePolling.d.ts +7 -48
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.checkout-return-context.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.completion.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +9 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.payment-confirmation.d.ts +13 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +17 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-actions.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.submit-handler.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/checkout.server.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/commerce/shared/display.d.ts +9 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/presentation.d.ts +14 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationWizard.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/PaymentSelectionStep.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/SuccessStep.d.ts +4 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +9 -5
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/domain/dates.d.ts +37 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.client.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +16 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCardPresentations.d.ts +13 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +29 -29
- package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.d.ts +1 -14
- package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.d.ts +12 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +54 -6
- package/dist/_dts/blocks/src/system/runtime/shared/bookingPaymentOptions.d.ts +7 -2
- package/dist/_dts/blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.d.ts +22 -0
- package/dist/_dts/blocks/src/system/runtime/shared/components/DemoPortalSignInLink.d.ts +4 -0
- package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/shared/utils/demoBookingPassStorage.d.ts +10 -0
- package/dist/_dts/blocks/src/system/runtime/shared/utils/demoPortalMagicLink.d.ts +29 -0
- package/dist/_dts/commerce/src/purchase/bookingPaymentSelection.d.ts +54 -0
- package/dist/_dts/commerce/src/purchase/checkoutCommitPlan.d.ts +58 -13
- package/dist/_dts/commerce/src/purchase/checkoutErrorCodes.d.ts +1 -1
- package/dist/_dts/commerce/src/purchase/checkoutPaymentPlanPlanning.d.ts +16 -21
- package/dist/_dts/commerce/src/purchase/checkoutPaymentTerms.d.ts +23 -40
- package/dist/_dts/commerce/src/purchase/checkoutSessionMetadata.d.ts +2 -2
- package/dist/_dts/commerce/src/purchase/checkoutStripeSessionPlanning.d.ts +5 -4
- package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
- package/dist/_dts/commerce/src/purchase/index.d.ts +1 -3
- package/dist/_dts/commerce/src/purchase/membershipOrderItemMetadata.d.ts +4 -0
- package/dist/_dts/commerce/src/purchase/oneTimeCheckoutPlanning.d.ts +9 -4
- package/dist/_dts/commerce/src/purchase/orderInstalmentClosure.d.ts +13 -1
- package/dist/_dts/commerce/src/purchase/orderInstalmentLifecycle.d.ts +5 -0
- package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +3 -1
- package/dist/_dts/commerce/src/purchase/orderTypes.d.ts +7 -1
- package/dist/_dts/commerce/src/purchase/refundRailSplit.d.ts +1 -1
- package/dist/_dts/commerce/src/purchase/stateTransitions.d.ts +2 -2
- package/dist/_dts/commerce/src/purchase/stripeMinimumCharge.d.ts +6 -0
- package/dist/_dts/commerce/src/purchase/types.d.ts +2 -1
- package/dist/_dts/content-editor/src/components/ContentFieldsForm.d.ts +2 -7
- package/dist/_dts/content-editor/src/controller/EditLeaseController.d.ts +39 -0
- package/dist/_dts/content-editor/src/controller/EditorWriteGate.d.ts +38 -0
- package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +25 -61
- package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseBanner.d.ts +7 -0
- package/dist/_dts/content-editor/src/controller/LinkedEntryLeaseControllers.d.ts +14 -0
- package/dist/_dts/content-editor/src/controller/deriveEditorUnpublishedState.d.ts +6 -0
- package/dist/_dts/content-editor/src/controller/documentValueBaseline.d.ts +25 -0
- package/dist/_dts/content-editor/src/controller/editLeaseHandover.d.ts +30 -0
- package/dist/_dts/content-editor/src/controller/editLeaseLossSignal.d.ts +6 -0
- package/dist/_dts/content-editor/src/controller/editLeaseNotice.d.ts +28 -0
- package/dist/_dts/content-editor/src/controller/editorClientId.d.ts +2 -0
- package/dist/_dts/content-editor/src/controller/editorEditability.d.ts +38 -0
- package/dist/_dts/content-editor/src/controller/editorLeaseParticipation.d.ts +34 -0
- package/dist/_dts/content-editor/src/controller/normalizedMetadataBaseline.d.ts +29 -0
- package/dist/_dts/content-editor/src/controller/pageSurfaceDocumentBaselines.d.ts +14 -0
- package/dist/_dts/content-editor/src/controller/pageSurfaceLifecycle.d.ts +11 -0
- package/dist/_dts/content-editor/src/controller/planDocumentBaselineRefresh.d.ts +19 -0
- package/dist/_dts/content-editor/src/controller/readDocumentLeaseBaselines.d.ts +19 -0
- package/dist/_dts/content-editor/src/controller/refreshDocumentLeaseBaseline.d.ts +12 -0
- package/dist/_dts/content-editor/src/controller/refreshLinkedEntry.d.ts +17 -0
- package/dist/_dts/content-editor/src/controller/replayRestoredEditorEffects.d.ts +2 -3
- package/dist/_dts/content-editor/src/controller/routeWrites.d.ts +26 -0
- package/dist/_dts/content-editor/src/controller/useAutosaveTriggers.d.ts +16 -17
- package/dist/_dts/content-editor/src/controller/useBlockedPublishPlan.d.ts +6 -2
- package/dist/_dts/content-editor/src/controller/useBlocksList.d.ts +3 -3
- package/dist/_dts/content-editor/src/controller/useEntryValueAutosaves.d.ts +21 -0
- package/dist/_dts/content-editor/src/controller/useInitialEditorUiStore.d.ts +24 -0
- package/dist/_dts/content-editor/src/controller/useServerBaselineReconciliation.d.ts +17 -0
- package/dist/_dts/content-editor/src/footerComposerPanelTypes.d.ts +1 -1
- package/dist/_dts/content-editor/src/hooks/applyBlockedPublishPlan.d.ts +5 -1
- package/dist/_dts/content-editor/src/hooks/blockDraftLifecycle.d.ts +8 -47
- package/dist/_dts/content-editor/src/hooks/editLeaseMachine.d.ts +120 -0
- package/dist/_dts/content-editor/src/hooks/publishability.d.ts +6 -10
- package/dist/_dts/content-editor/src/hooks/useAutosaveStatus.d.ts +3 -0
- package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +5 -15
- package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +7 -5
- package/dist/_dts/content-editor/src/hooks/useEditLease.d.ts +28 -0
- package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +25 -39
- package/dist/_dts/content-editor/src/hooks/useEntryMutations.d.ts +17 -19
- package/dist/_dts/content-editor/src/hooks/useLinkedEntryAutosave.d.ts +5 -8
- package/dist/_dts/content-editor/src/hooks/useValueAutosave.d.ts +64 -0
- package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +0 -7
- package/dist/_dts/content-editor/src/index.d.ts +26 -7
- package/dist/_dts/content-editor/src/lib/browserStorage.d.ts +5 -0
- package/dist/_dts/content-editor/src/linkedEntries/domain.d.ts +12 -0
- package/dist/_dts/content-editor/src/linkedEntries/owner.d.ts +9 -0
- package/dist/_dts/content-editor/src/liveDrafts/draftProjection.d.ts +66 -0
- package/dist/_dts/content-editor/src/liveDrafts/linkedSaveHandovers.d.ts +37 -0
- package/dist/_dts/content-editor/src/liveDrafts/remoteDraftOverlay.d.ts +113 -0
- package/dist/_dts/content-editor/src/liveDrafts/useLiveDrafts.d.ts +32 -0
- package/dist/_dts/content-editor/src/liveDrafts/useRetentionTicks.d.ts +7 -0
- package/dist/_dts/content-editor/src/primitives/shared/activePreviewField.d.ts +6 -0
- package/dist/_dts/content-editor/src/primitives/shared/storeBinding.d.ts +1 -0
- package/dist/_dts/content-editor/src/services/contentEntryServices.d.ts +96 -19
- package/dist/_dts/content-editor/src/services/editorApiClient.d.ts +13 -0
- package/dist/_dts/content-editor/src/services/index.d.ts +2 -0
- package/dist/_dts/content-editor/src/services/pageSurfaceEditorServices.d.ts +23 -0
- package/dist/_dts/content-editor/src/sync/flushValues.d.ts +13 -0
- package/dist/_dts/content-editor/src/sync/lifecycleFailure.d.ts +51 -0
- package/dist/_dts/content-editor/src/sync/runLifecycle.d.ts +64 -0
- package/dist/_dts/content-editor/src/sync/schedulerValues.d.ts +27 -0
- package/dist/_dts/content-editor/src/sync/sendPlanning.d.ts +104 -0
- package/dist/_dts/content-editor/src/sync/valueSync.d.ts +114 -0
- package/dist/_dts/content-editor/src/ui/blockCollection.d.ts +8 -0
- package/dist/_dts/content-editor/src/ui/documentLifecycle.d.ts +18 -0
- package/dist/_dts/content-editor/src/ui/editorLeaseUiState.d.ts +7 -0
- package/dist/_dts/content-editor/src/ui/editorRefresh.d.ts +82 -0
- package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +102 -127
- package/dist/_dts/content-editor/src/ui/editorTransactionState.d.ts +1 -1
- package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +126 -72
- package/dist/_dts/content-editor/src/ui/editorValueSnapshot.d.ts +18 -0
- package/dist/_dts/content-editor/src/ui/serverBlockAdmission.d.ts +26 -0
- package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +16 -27
- package/dist/_dts/content-editor/src/ui/stores/blockVersionsStore.d.ts +24 -0
- package/dist/_dts/content-editor/src/ui/stores/linkedEntryLeaseStore.d.ts +54 -0
- package/dist/_dts/content-editor/src/ui/stores/linkedSaveHandoversStore.d.ts +11 -0
- package/dist/_dts/content-editor/src/ui/stores/remoteDraftsStore.d.ts +10 -0
- package/dist/_dts/content-editor/src/ui/stores/types.d.ts +63 -3
- package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +2 -2
- package/dist/_dts/content-editor/src/useFooterNavigationLayout.d.ts +1 -1
- package/dist/_dts/content-model/src/content-types/builtin-schemas.d.ts +4 -4
- package/dist/_dts/content-model/src/content-types/builtins.d.ts +4 -4
- package/dist/_dts/content-model/src/definitions/shared.d.ts +11 -2
- package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
- package/dist/_dts/content-model/src/entry-slots/serializeAllowedBlocks.d.ts +2 -0
- package/dist/_dts/content-model/src/metadataConfig.d.ts +10 -38
- package/dist/_dts/content-model/src/templates/defaults.d.ts +0 -1
- package/dist/_dts/content-model/src/types.d.ts +0 -1
- package/dist/_dts/core/src/block-content-identity.d.ts +49 -1
- package/dist/_dts/core/src/booking-flexible-balance.d.ts +2 -2
- package/dist/_dts/core/src/booking-instalment-deposit.d.ts +20 -0
- package/dist/_dts/core/src/booking-live-payment-terms.d.ts +72 -0
- package/dist/_dts/core/src/booking-payment-options.d.ts +24 -0
- package/dist/_dts/core/src/booking-payment-schemas.d.ts +522 -0
- package/dist/_dts/core/src/branded.d.ts +15 -0
- package/dist/_dts/core/src/currency-format.d.ts +8 -2
- package/dist/_dts/core/src/demo-lifecycle-status.d.ts +2 -2
- package/dist/_dts/core/src/demo-warm-pool-target.d.ts +8 -0
- package/dist/_dts/core/src/edit-lease.d.ts +60 -0
- package/dist/_dts/core/src/editor-state.d.ts +38 -13
- package/dist/_dts/core/src/editor-value-sync.d.ts +79 -0
- package/dist/_dts/core/src/html-entities.d.ts +6 -0
- package/dist/_dts/core/src/index.d.ts +7 -0
- package/dist/_dts/core/src/uuid.d.ts +7 -5
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +456 -189
- package/dist/_dts/editor/src/EditorProvider.d.ts +5 -0
- package/dist/_dts/editor/src/chrome/EditorChrome.d.ts +14 -0
- package/dist/_dts/editor/src/chrome/EditorStatusBar.d.ts +1 -0
- package/dist/_dts/editor/src/chrome/statusBarPresentation.d.ts +0 -1
- package/dist/_dts/editor/src/index.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +10 -9
- package/dist/_dts/editor-blocks/src/BlockForm.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/block-editor/BlockCardFrame.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/block-editor/applyExtendedFieldDefaults.d.ts +3 -4
- package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +4 -8
- package/dist/_dts/editor-blocks/src/block-editor/editorBlockItem.d.ts +23 -0
- package/dist/_dts/editor-blocks/src/block-editor/generatedIconApplyCoordination.d.ts +2 -7
- package/dist/_dts/editor-blocks/src/block-editor/hooks/applyBlockStructureChange.d.ts +4 -0
- package/dist/_dts/editor-blocks/src/block-editor/hooks/buildInsertBlockHistoryCommand.d.ts +14 -5
- package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +21 -19
- package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +2 -10
- package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +8 -16
- package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +6 -16
- package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +37 -9
- package/dist/_dts/editor-blocks/src/index.d.ts +2 -1
- package/dist/_dts/editor-blocks/src/widgets/entry-picker/loaders.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/widgets/link/loaders.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/widgets/reference/loaders.d.ts +1 -1
- package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +3 -2
- package/dist/_dts/media-core/src/fileStorage.d.ts +4 -0
- package/dist/_dts/media-editor/src/MediaPickerDialog.d.ts +3 -1
- package/dist/_dts/media-editor/src/MediaPickerMiniDialog.d.ts +10 -0
- package/dist/_dts/media-editor/src/context.d.ts +1 -1
- package/dist/_dts/media-editor/src/createMediaEditorProvider.d.ts +1 -2
- package/dist/_dts/media-editor/src/index.d.ts +2 -0
- package/dist/_dts/media-editor/src/provider.d.ts +3 -2
- package/dist/_dts/media-react/src/hooks/internal/classification.d.ts +1 -1
- package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +3 -1
- package/dist/_dts/preview-next/src/client/blocks/composer/mergeDrafts.d.ts +8 -3
- package/dist/_dts/preview-next/src/client/blocks/composer/types.d.ts +6 -3
- package/dist/_dts/preview-next/src/client/blocks/linkedEntryRenderOverlay.d.ts +22 -2
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/entryFieldRebinding.d.ts +13 -0
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/index.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/blocks/previewProjection/types.d.ts +11 -1
- package/dist/_dts/preview-next/src/client/blocks/renderPrecedence.d.ts +17 -0
- package/dist/_dts/preview-next/src/client/blocks/useLinkedSaveHandoverRetention.d.ts +20 -0
- package/dist/_dts/preview-next/src/client/index.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewAccessBanners.d.ts +7 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
- package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +23 -14
- package/dist/_dts/preview-next/src/client/preview/PreviewLeaseEditingMode.d.ts +2 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +9 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/previewCustomizeAutosave.d.ts +5 -0
- package/dist/_dts/preview-next/src/client/preview/previewCustomizeWorkflowState.d.ts +3 -4
- package/dist/_dts/preview-next/src/client/preview/sdkConfig.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/usePreviewCustomizeWorkflowState.d.ts +4 -0
- package/dist/_dts/preview-next/src/client/previewAuthStore.d.ts +7 -0
- package/dist/_dts/preview-next/src/constants.d.ts +4 -0
- package/dist/_dts/preview-next/src/keepAlive.d.ts +1 -0
- package/dist/_dts/realtime/src/client.d.ts +3 -0
- package/dist/_dts/realtime/src/draftChannel.d.ts +91 -0
- package/dist/_dts/realtime/src/drafts.d.ts +210 -0
- package/dist/_dts/realtime/src/index.d.ts +3 -0
- package/dist/_dts/realtime/src/leaseChangeSubscriptions.d.ts +8 -0
- package/dist/_dts/realtime/src/types.d.ts +113 -0
- package/dist/_dts/realtime/src/useDraftChannel.d.ts +34 -0
- package/dist/_dts/realtime/src/useSiteRealtimeReload.d.ts +27 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +6 -55
- package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +2 -0
- package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -12
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/surfaces/src/index.d.ts +1 -0
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +0 -5
- package/dist/_dts/ui/src/color-picker.d.ts +1 -1
- package/dist/_dts/ui/src/palette/useHexDraft.d.ts +7 -0
- package/dist/client/{BookingMailingListNote-1n4Ch_u_.mjs → BookingMailingListNote-Cr3EeTP5.mjs} +504 -163
- package/dist/client/DemoBookingPortalAccess-BFGB1Fay.mjs +344 -0
- package/dist/client/{EventCombined.client-C0pgma9y.mjs → EventCombined.client-DKYV0_ft.mjs} +6 -6
- package/dist/client/{EventListing.client-4fhLOvHP.mjs → EventListing.client-B9UIcEYc.mjs} +2 -2
- package/dist/client/{LeafletStaticMap-DScC4F3w.mjs → LeafletStaticMap-CFLPkP0K.mjs} +1 -1
- package/dist/client/{TerminalPanel-B5ZUsYhe.mjs → TerminalPanel-JjmgxEsR.mjs} +1 -1
- package/dist/client/{ThemedButton-DoVIV1Ao.mjs → ThemedButton-CKV1Jh2m.mjs} +1 -1
- package/dist/client/{accordion-CoT5g7zo.mjs → accordion-DXWIfT3T.mjs} +1 -1
- package/dist/client/{bookingForm-BWxB46xD.mjs → bookingForm-CjZgHNvv.mjs} +216 -63
- package/dist/client/bookings.mjs +1187 -692
- package/dist/client/{carousel-DtNYWFd3.mjs → carousel-DSLikmvZ.mjs} +1 -1
- package/dist/client/{cart-z4qZih1Y.mjs → cart-HDjWReFt.mjs} +3 -3
- package/dist/client/{checkout-DpL7euFH.mjs → checkout-CUvRZA3W.mjs} +3 -3
- package/dist/client/{checkoutUrls-BEfR7kVu.mjs → checkoutUrls-CXhko2Rv.mjs} +1 -1
- package/dist/client/client.mjs +2711 -1684
- package/dist/client/{context-C8TinPJc.mjs → context-DFmaZa-Q.mjs} +4 -3
- package/dist/client/{dates-vwwxTeB0.mjs → dates-BBep1JnF.mjs} +56 -11
- package/dist/client/{eventCalendar-DIbHfJXO.mjs → eventCalendar-zEobhxo4.mjs} +9 -9
- package/dist/client/{eventCombined-DoGMJ6cg.mjs → eventCombined-Dp7bz5k-.mjs} +4 -4
- package/dist/client/{eventDetails-BjN9v6a1.mjs → eventDetails-FE-zqTt7.mjs} +4 -4
- package/dist/client/{eventListing-DajjWgOv.mjs → eventListing-BMt5snal.mjs} +4 -4
- package/dist/client/{eventRegistration-DMq9gMA-.mjs → eventRegistration-O6ZxHfOb.mjs} +422 -570
- package/dist/client/{form-Qf6qTbos.mjs → form-DFa1D8vt.mjs} +3 -3
- package/dist/client/{headerSection-D7qJrqFX.mjs → headerSection-CmjHLR-N.mjs} +3 -3
- package/dist/client/hooks.mjs +414 -182
- package/dist/client/{locationMap-CCF9-t_0.mjs → locationMap-BXKP_lGh.mjs} +3 -3
- package/dist/client/{media-CwBGetqC.mjs → media-Cl38iOMI.mjs} +10 -3
- package/dist/client/{newsletterForm-DzCLSP4S.mjs → newsletterForm-CU-HmxGx.mjs} +3 -3
- package/dist/client/{pricing-Cgxv2KLC.mjs → pricing-KEAEsibq.mjs} +1 -1
- package/dist/client/{productDetail-ru9w5GHx.mjs → productDetail-Ckp7MGnt.mjs} +3 -3
- package/dist/client/{productList-zaapKSl-.mjs → productList-D91V0sYa.mjs} +3 -3
- package/dist/client/{propsDecoder-CwvvNOHx.mjs → propsDecoder-DZd6RJeA.mjs} +244 -94
- package/dist/client/rendering/client.mjs +2656 -1705
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +3430 -2352
- package/dist/client/{routeIslandApiConfig-BwVFo0Y4.mjs → routeIslandApiConfig-E1EkhhYY.mjs} +1 -1
- package/dist/client/{shop-mktkXvbV.mjs → shop-4F2jLQPI.mjs} +131 -85
- package/dist/client/{shop-commerce-De7gEnkA.mjs → shop-commerce-BbfCJjB3.mjs} +25 -13
- package/dist/client/{shop-commerce-store-B3MCxIBW.mjs → shop-commerce-store-vicweP2K.mjs} +1 -1
- package/dist/client/{shopShared-TqExh235.mjs → shopShared-DlONJt0T.mjs} +4 -4
- package/dist/client/{useEventFilters-n_OjkIjX.mjs → useEventFilters-COYyL3m7.mjs} +32 -17
- package/dist/preview-next/before-render.mjs +207 -105
- package/dist/preview-next/client/runtime.mjs +4 -4
- package/dist/preview-next/constants.mjs +5 -1
- package/dist/preview-next/index.mjs +5 -1
- package/dist/preview-next/keepAlive.mjs +341 -165
- package/dist/preview-next/middleware.mjs +207 -105
- package/dist/{previewAuthStore-C_EHQ5XA.mjs → previewAuthStore-BBmV7UsW.mjs} +243 -112
- package/dist/{sdk-runtime-BIkJg5y1.mjs → sdk-runtime-CwvFFjB-.mjs} +2 -2
- package/dist/{separator-C9qDP95Z.mjs → separator-ByL72zUT.mjs} +1 -1
- package/dist/server/components.mjs +1839 -1475
- package/dist/server/config-validation.mjs +381 -166
- package/dist/server/config.mjs +381 -166
- package/dist/server/data.mjs +381 -166
- package/dist/server/index.mjs +214 -110
- package/dist/server/next.mjs +663 -351
- package/dist/server/page-converter.mjs +198 -79
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +1536 -1169
- package/dist/server/rendering.mjs +2432 -2068
- package/dist/server/routing.mjs +456 -173
- package/dist/server/server.mjs +447 -267
- package/package.json +1 -1
- package/dist/_dts/api/src/bookingPaymentTermSchemas.d.ts +0 -123
- package/dist/_dts/billing/src/plans/display.d.ts +0 -15
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.mailing-list-note.d.ts +0 -3
- package/dist/_dts/commerce/src/purchase/checkoutPaymentTermPlanning.d.ts +0 -10
- package/dist/_dts/commerce/src/purchase/checkoutValidatedItemPlanning.d.ts +0 -55
- package/dist/_dts/commerce/src/purchase/orderInstalmentPayoff.d.ts +0 -24
- package/dist/_dts/content-editor/src/controller/buildBlockPublishedBaselines.d.ts +0 -4
- package/dist/_dts/content-editor/src/controller/buildPublishSuccessTransition.d.ts +0 -16
- package/dist/_dts/content-editor/src/controller/driver.d.ts +0 -14
- package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +0 -7
- package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +0 -29
- package/dist/_dts/content-editor/src/hooks/autosaveScopePlanning.d.ts +0 -26
- package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +0 -64
- package/dist/_dts/content-editor/src/hooks/useStoreAutosave.d.ts +0 -48
- package/dist/_dts/content-editor/src/types.d.ts +0 -44
- package/dist/client/DiscountCodeDisclosure-CKJtz0mY.mjs +0 -137
package/dist/client/bookings.mjs
CHANGED
|
@@ -2539,7 +2539,7 @@ function subtractDaysFromIso(isoString, dayCount) {
|
|
|
2539
2539
|
}
|
|
2540
2540
|
//#endregion
|
|
2541
2541
|
//#region ../core/src/assert-never.ts
|
|
2542
|
-
function assertNever$
|
|
2542
|
+
function assertNever$4(value, message = "Unexpected variant") {
|
|
2543
2543
|
throw new Error(`${message}: ${String(value)}`);
|
|
2544
2544
|
}
|
|
2545
2545
|
//#endregion
|
|
@@ -2563,6 +2563,19 @@ const CURRENCY_LOCALE_BY_CODE = {
|
|
|
2563
2563
|
function resolveCurrencyLocale(currencyCode, override) {
|
|
2564
2564
|
return override ?? CURRENCY_LOCALE_BY_CODE[currencyCode] ?? "en";
|
|
2565
2565
|
}
|
|
2566
|
+
function fractionDigitsFor(decimals, exactFormatter) {
|
|
2567
|
+
switch (decimals) {
|
|
2568
|
+
case "exact": return {};
|
|
2569
|
+
case "auto": return {
|
|
2570
|
+
minimumFractionDigits: 0,
|
|
2571
|
+
maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
|
|
2572
|
+
};
|
|
2573
|
+
case "whole": return {
|
|
2574
|
+
minimumFractionDigits: 0,
|
|
2575
|
+
maximumFractionDigits: 0
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2566
2579
|
/**
|
|
2567
2580
|
* The single currency-amount formatter for the product: minor units in,
|
|
2568
2581
|
* localized string out.
|
|
@@ -2573,6 +2586,13 @@ function resolveCurrencyLocale(currencyCode, override) {
|
|
|
2573
2586
|
* own `Intl.NumberFormat`.
|
|
2574
2587
|
*/
|
|
2575
2588
|
function formatCurrencyAmount(amountCents, currency, options) {
|
|
2589
|
+
return formatCurrencyMajorUnits(amountCents / 100, currency, options);
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* `formatCurrencyAmount` for an amount already in MAJOR units (29.99 = £29.99),
|
|
2593
|
+
* such as a registrar price. Prefer minor units everywhere else.
|
|
2594
|
+
*/
|
|
2595
|
+
function formatCurrencyMajorUnits(amount, currency, options) {
|
|
2576
2596
|
const currencyCode = currency.toUpperCase();
|
|
2577
2597
|
const locale = resolveCurrencyLocale(currencyCode, options?.locale);
|
|
2578
2598
|
try {
|
|
@@ -2580,17 +2600,13 @@ function formatCurrencyAmount(amountCents, currency, options) {
|
|
|
2580
2600
|
style: "currency",
|
|
2581
2601
|
currency: currencyCode
|
|
2582
2602
|
});
|
|
2583
|
-
const fractionDigits = options?.decimals === "auto" ? {
|
|
2584
|
-
minimumFractionDigits: 0,
|
|
2585
|
-
maximumFractionDigits: exactFormatter.resolvedOptions().maximumFractionDigits
|
|
2586
|
-
} : {};
|
|
2587
2603
|
return new Intl.NumberFormat(locale, {
|
|
2588
2604
|
style: "currency",
|
|
2589
2605
|
currency: currencyCode,
|
|
2590
|
-
...
|
|
2591
|
-
}).format(
|
|
2606
|
+
...fractionDigitsFor(options?.decimals ?? "exact", exactFormatter)
|
|
2607
|
+
}).format(amount);
|
|
2592
2608
|
} catch {
|
|
2593
|
-
return `${
|
|
2609
|
+
return `${amount.toFixed(2)} ${currencyCode}`;
|
|
2594
2610
|
}
|
|
2595
2611
|
}
|
|
2596
2612
|
//#endregion
|
|
@@ -2616,7 +2632,7 @@ function isPublicEventPricingOptionDisplayable(option) {
|
|
|
2616
2632
|
case "not_on_sale_yet":
|
|
2617
2633
|
case "sale_ended":
|
|
2618
2634
|
case "attendance_mode_unavailable": return false;
|
|
2619
|
-
default: return assertNever$
|
|
2635
|
+
default: return assertNever$4(reason);
|
|
2620
2636
|
}
|
|
2621
2637
|
}
|
|
2622
2638
|
function publicEventPricingDisplay(pricing) {
|
|
@@ -2737,7 +2753,7 @@ function canonicalEventPricingDisplay(pricing) {
|
|
|
2737
2753
|
currency: pricing.currency,
|
|
2738
2754
|
purpose: "configured"
|
|
2739
2755
|
});
|
|
2740
|
-
default: return assertNever$
|
|
2756
|
+
default: return assertNever$4(pricing);
|
|
2741
2757
|
}
|
|
2742
2758
|
}
|
|
2743
2759
|
//#endregion
|
|
@@ -2786,7 +2802,7 @@ function parseEventPageSurfaceDestinationMode(value) {
|
|
|
2786
2802
|
return value === "cms-managed" || value === "system-managed" ? value : void 0;
|
|
2787
2803
|
}
|
|
2788
2804
|
function parseEventPageSurfaceSubject(value) {
|
|
2789
|
-
if (!isRecord$
|
|
2805
|
+
if (!isRecord$9(value)) return err$1({ kind: "notObject" });
|
|
2790
2806
|
switch (value.kind) {
|
|
2791
2807
|
case "eventSeries": {
|
|
2792
2808
|
const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
|
|
@@ -2841,7 +2857,7 @@ function parseEventSeriesIdList(values) {
|
|
|
2841
2857
|
}
|
|
2842
2858
|
return ok$1(parsed);
|
|
2843
2859
|
}
|
|
2844
|
-
function isRecord$
|
|
2860
|
+
function isRecord$9(value) {
|
|
2845
2861
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2846
2862
|
}
|
|
2847
2863
|
//#endregion
|
|
@@ -2868,10 +2884,10 @@ function resolveFlexibleBalanceDueAt(input) {
|
|
|
2868
2884
|
switch (input.dueDateRule.kind) {
|
|
2869
2885
|
case "relative_to_start_date": return subtractDaysFromIso(input.bookingStartAt, input.dueDateRule.daysBeforeStart);
|
|
2870
2886
|
case "fixed_calendar_date": return input.dueDateRule.dueAt;
|
|
2871
|
-
default: return assertNever$
|
|
2887
|
+
default: return assertNever$3(input.dueDateRule);
|
|
2872
2888
|
}
|
|
2873
2889
|
}
|
|
2874
|
-
function assertNever$
|
|
2890
|
+
function assertNever$3(value) {
|
|
2875
2891
|
throw new Error(`Unexpected value: ${String(value)}`);
|
|
2876
2892
|
}
|
|
2877
2893
|
//#endregion
|
|
@@ -2881,7 +2897,7 @@ function isDepositBearingBookingInstalmentPlan(plan) {
|
|
|
2881
2897
|
case "deposit_plus_one_remainder":
|
|
2882
2898
|
case "deposit_plus_scheduled_instalments": return true;
|
|
2883
2899
|
case "equal_scheduled_instalments": return false;
|
|
2884
|
-
default: return assertNever$
|
|
2900
|
+
default: return assertNever$2(plan);
|
|
2885
2901
|
}
|
|
2886
2902
|
}
|
|
2887
2903
|
function getBookingInstalmentDepositRefundability(plan) {
|
|
@@ -2907,7 +2923,7 @@ function addIntervalPreservingMonthAnchor(isoString, intervalCount, intervalUnit
|
|
|
2907
2923
|
date.setUTCDate(date.getUTCDate() + intervalCount * 7);
|
|
2908
2924
|
return date.toISOString();
|
|
2909
2925
|
case "month": return addMonthsPreservingAnchorDay(date, intervalCount).toISOString();
|
|
2910
|
-
default: return assertNever$
|
|
2926
|
+
default: return assertNever$2(intervalUnit);
|
|
2911
2927
|
}
|
|
2912
2928
|
}
|
|
2913
2929
|
function getBookingInstalmentPlanIntervalCount(plan) {
|
|
@@ -2915,7 +2931,7 @@ function getBookingInstalmentPlanIntervalCount(plan) {
|
|
|
2915
2931
|
case "deposit_plus_one_remainder": return plan.remainderDueCount;
|
|
2916
2932
|
case "deposit_plus_scheduled_instalments":
|
|
2917
2933
|
case "equal_scheduled_instalments": return plan.intervalCount;
|
|
2918
|
-
default: return assertNever$
|
|
2934
|
+
default: return assertNever$2(plan);
|
|
2919
2935
|
}
|
|
2920
2936
|
}
|
|
2921
2937
|
function omitZeroAmountFutureRows(rows) {
|
|
@@ -2931,10 +2947,20 @@ function addMonthsPreservingAnchorDay(date, intervalCount) {
|
|
|
2931
2947
|
nextMonth.setUTCDate(Math.min(anchorDay, lastDayOfTargetMonth));
|
|
2932
2948
|
return nextMonth;
|
|
2933
2949
|
}
|
|
2934
|
-
function assertNever$
|
|
2950
|
+
function assertNever$2(value) {
|
|
2935
2951
|
throw new Error(`Unexpected value: ${String(value)}`);
|
|
2936
2952
|
}
|
|
2937
2953
|
//#endregion
|
|
2954
|
+
//#region ../core/src/booking-payment-options.ts
|
|
2955
|
+
/** Automatic instalments and a flexible balance cannot share one booking offer. */
|
|
2956
|
+
function validateBookingPaymentOptionKinds(kinds) {
|
|
2957
|
+
if (kinds.length === 0) return err$1("no_options");
|
|
2958
|
+
const uniqueKinds = new Set(kinds);
|
|
2959
|
+
if (uniqueKinds.size !== kinds.length) return err$1("duplicate_kind");
|
|
2960
|
+
if (uniqueKinds.has("instalment_plan") && uniqueKinds.has("flexible_balance")) return err$1("incompatible_collection_options");
|
|
2961
|
+
return ok$1(void 0);
|
|
2962
|
+
}
|
|
2963
|
+
//#endregion
|
|
2938
2964
|
//#region ../core/src/booking-time-zone.ts
|
|
2939
2965
|
const TIME_ZONE_VALIDITY_CACHE_LIMIT = 100;
|
|
2940
2966
|
const timeZoneValidityCache = /* @__PURE__ */ new Map();
|
|
@@ -3168,6 +3194,16 @@ function resolveBookingSignupOffer(context, siteName) {
|
|
|
3168
3194
|
const name = siteName?.trim() ?? "";
|
|
3169
3195
|
return context?.tag === "configured" && context.bookingSignup.tag === "offered" ? { siteName: name.length > 0 ? name : "this site" } : null;
|
|
3170
3196
|
}
|
|
3197
|
+
//#endregion
|
|
3198
|
+
//#region ../core/src/uuid.ts
|
|
3199
|
+
function generateUuidV4(cryptoSource = globalThis.crypto) {
|
|
3200
|
+
if (typeof cryptoSource.randomUUID === "function") return cryptoSource.randomUUID();
|
|
3201
|
+
const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
|
|
3202
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
3203
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
3204
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
|
|
3205
|
+
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
|
|
3206
|
+
}
|
|
3171
3207
|
function sessionStartMs(session) {
|
|
3172
3208
|
return Date.parse(session.startsAt);
|
|
3173
3209
|
}
|
|
@@ -7023,7 +7059,7 @@ const boxBackgroundSchema = z.discriminatedUnion("type", [
|
|
|
7023
7059
|
})
|
|
7024
7060
|
]);
|
|
7025
7061
|
function normalizeAuthoringOpacity(value) {
|
|
7026
|
-
if (!isRecord$
|
|
7062
|
+
if (!isRecord$8(value)) return value;
|
|
7027
7063
|
return {
|
|
7028
7064
|
...value,
|
|
7029
7065
|
opacity: normalizeOpacity(value.opacity)
|
|
@@ -7032,7 +7068,7 @@ function normalizeAuthoringOpacity(value) {
|
|
|
7032
7068
|
function normalizeOpacity(value) {
|
|
7033
7069
|
return typeof value === "number" && value > 1 && value <= 100 ? value / 100 : value;
|
|
7034
7070
|
}
|
|
7035
|
-
function isRecord$
|
|
7071
|
+
function isRecord$8(value) {
|
|
7036
7072
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7037
7073
|
}
|
|
7038
7074
|
//#endregion
|
|
@@ -7833,68 +7869,115 @@ const RichTextDocSchema = z.object({
|
|
|
7833
7869
|
content: z.array(TipTapNodeSchema)
|
|
7834
7870
|
}).strict();
|
|
7835
7871
|
//#endregion
|
|
7836
|
-
//#region ../
|
|
7837
|
-
const
|
|
7838
|
-
const
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
intervalUnit: z.enum([
|
|
7845
|
-
"day",
|
|
7846
|
-
"week",
|
|
7847
|
-
"month"
|
|
7848
|
-
])
|
|
7849
|
-
}),
|
|
7850
|
-
z.object({
|
|
7851
|
-
kind: z.literal("deposit_plus_scheduled_instalments"),
|
|
7852
|
-
depositAmountCents: z.number().int().min(0),
|
|
7853
|
-
depositRefundability: bookingDepositRefundPolicySchema,
|
|
7854
|
-
instalmentCount: z.number().int().positive(),
|
|
7855
|
-
intervalCount: z.number().int().positive(),
|
|
7856
|
-
intervalUnit: z.enum([
|
|
7857
|
-
"day",
|
|
7858
|
-
"week",
|
|
7859
|
-
"month"
|
|
7860
|
-
])
|
|
7861
|
-
}),
|
|
7862
|
-
z.object({
|
|
7863
|
-
kind: z.literal("equal_scheduled_instalments"),
|
|
7864
|
-
instalmentCount: z.number().int().positive(),
|
|
7865
|
-
intervalCount: z.number().int().positive(),
|
|
7866
|
-
intervalUnit: z.enum([
|
|
7867
|
-
"day",
|
|
7868
|
-
"week",
|
|
7869
|
-
"month"
|
|
7870
|
-
])
|
|
7871
|
-
})
|
|
7872
|
-
]);
|
|
7873
|
-
const bookingFlexibleBalanceDueDateRuleSchema = z.union([z.object({
|
|
7874
|
-
kind: z.literal("relative_to_start_date"),
|
|
7875
|
-
daysBeforeStart: z.number().int().positive()
|
|
7876
|
-
}), z.object({
|
|
7877
|
-
kind: z.literal("fixed_calendar_date"),
|
|
7878
|
-
dueAt: z.string().datetime()
|
|
7879
|
-
})]);
|
|
7880
|
-
const bookingFlexibleBalanceConfigSchema = z.object({
|
|
7881
|
-
upfrontAmountCents: z.number().int().min(0),
|
|
7882
|
-
dueDateRule: bookingFlexibleBalanceDueDateRuleSchema,
|
|
7883
|
-
depositRefundability: bookingDepositRefundPolicySchema
|
|
7884
|
-
});
|
|
7885
|
-
const blockBookingPaymentCollectionOptionSchema = z.union([
|
|
7886
|
-
z.object({ kind: z.literal("upfront") }),
|
|
7887
|
-
z.object({ kind: z.literal("deferred_manual") }),
|
|
7888
|
-
z.object({
|
|
7889
|
-
kind: z.literal("instalment_plan"),
|
|
7890
|
-
plan: bookingInstalmentPlanSchema
|
|
7891
|
-
}),
|
|
7892
|
-
z.object({
|
|
7893
|
-
kind: z.literal("flexible_balance"),
|
|
7894
|
-
config: bookingFlexibleBalanceConfigSchema
|
|
7895
|
-
})
|
|
7872
|
+
//#region ../core/src/booking-payment-schemas.ts
|
|
7873
|
+
const stripObject = (shape) => z.object(shape);
|
|
7874
|
+
const strictObject = (shape) => z.strictObject(shape);
|
|
7875
|
+
const depositRefundPolicySchema = z.enum(["refundable", "non_refundable"]);
|
|
7876
|
+
const intervalUnitSchema = z.enum([
|
|
7877
|
+
"day",
|
|
7878
|
+
"week",
|
|
7879
|
+
"month"
|
|
7896
7880
|
]);
|
|
7897
|
-
const
|
|
7881
|
+
const nonNegativeIntegerSchema = z.number().int().nonnegative();
|
|
7882
|
+
const positiveIntegerSchema = z.number().int().positive();
|
|
7883
|
+
function createInstalmentPlanSchema(object) {
|
|
7884
|
+
return z.discriminatedUnion("kind", [
|
|
7885
|
+
object({
|
|
7886
|
+
kind: z.literal("deposit_plus_one_remainder"),
|
|
7887
|
+
depositAmountCents: nonNegativeIntegerSchema,
|
|
7888
|
+
depositRefundability: depositRefundPolicySchema,
|
|
7889
|
+
remainderDueCount: positiveIntegerSchema,
|
|
7890
|
+
intervalUnit: intervalUnitSchema
|
|
7891
|
+
}),
|
|
7892
|
+
object({
|
|
7893
|
+
kind: z.literal("deposit_plus_scheduled_instalments"),
|
|
7894
|
+
depositAmountCents: nonNegativeIntegerSchema,
|
|
7895
|
+
depositRefundability: depositRefundPolicySchema,
|
|
7896
|
+
instalmentCount: positiveIntegerSchema,
|
|
7897
|
+
intervalCount: positiveIntegerSchema,
|
|
7898
|
+
intervalUnit: intervalUnitSchema
|
|
7899
|
+
}),
|
|
7900
|
+
object({
|
|
7901
|
+
kind: z.literal("equal_scheduled_instalments"),
|
|
7902
|
+
instalmentCount: positiveIntegerSchema,
|
|
7903
|
+
intervalCount: positiveIntegerSchema,
|
|
7904
|
+
intervalUnit: intervalUnitSchema
|
|
7905
|
+
})
|
|
7906
|
+
]);
|
|
7907
|
+
}
|
|
7908
|
+
function createFlexibleBalanceSchemas(object) {
|
|
7909
|
+
const dueDateRule = z.discriminatedUnion("kind", [object({
|
|
7910
|
+
kind: z.literal("relative_to_start_date"),
|
|
7911
|
+
daysBeforeStart: positiveIntegerSchema
|
|
7912
|
+
}), object({
|
|
7913
|
+
kind: z.literal("fixed_calendar_date"),
|
|
7914
|
+
dueAt: z.string().datetime()
|
|
7915
|
+
})]);
|
|
7916
|
+
return {
|
|
7917
|
+
dueDateRule,
|
|
7918
|
+
config: object({
|
|
7919
|
+
upfrontAmountCents: nonNegativeIntegerSchema,
|
|
7920
|
+
dueDateRule,
|
|
7921
|
+
depositRefundability: depositRefundPolicySchema
|
|
7922
|
+
})
|
|
7923
|
+
};
|
|
7924
|
+
}
|
|
7925
|
+
const paymentOptionKindsMessages = {
|
|
7926
|
+
no_options: "Choose at least one way for customers to pay.",
|
|
7927
|
+
duplicate_kind: "Choose each payment option only once.",
|
|
7928
|
+
incompatible_collection_options: "Offer instalments or a deposit with the rest paid later, but not both."
|
|
7929
|
+
};
|
|
7930
|
+
function buildBookingPaymentOptionSchemas(object) {
|
|
7931
|
+
const instalmentPlan = createInstalmentPlanSchema(object);
|
|
7932
|
+
const flexibleBalance = createFlexibleBalanceSchemas(object);
|
|
7933
|
+
const paymentCollectionOption = z.discriminatedUnion("kind", [
|
|
7934
|
+
object({ kind: z.literal("upfront") }),
|
|
7935
|
+
object({ kind: z.literal("deferred_manual") }),
|
|
7936
|
+
object({
|
|
7937
|
+
kind: z.literal("instalment_plan"),
|
|
7938
|
+
plan: instalmentPlan
|
|
7939
|
+
}),
|
|
7940
|
+
object({
|
|
7941
|
+
kind: z.literal("flexible_balance"),
|
|
7942
|
+
config: flexibleBalance.config
|
|
7943
|
+
})
|
|
7944
|
+
]);
|
|
7945
|
+
const paymentTerms = object({ allowedOptions: z.array(paymentCollectionOption) }).superRefine(({ allowedOptions }, ctx) => {
|
|
7946
|
+
const result = validateBookingPaymentOptionKinds(allowedOptions.map(({ kind }) => kind));
|
|
7947
|
+
if (!result.ok) ctx.addIssue({
|
|
7948
|
+
code: "custom",
|
|
7949
|
+
path: ["allowedOptions"],
|
|
7950
|
+
message: paymentOptionKindsMessages[result.error]
|
|
7951
|
+
});
|
|
7952
|
+
});
|
|
7953
|
+
const paymentOptionsChoice = z.discriminatedUnion("source", [z.strictObject({ source: z.literal("default") }), z.strictObject({
|
|
7954
|
+
source: z.literal("custom"),
|
|
7955
|
+
paymentTerms
|
|
7956
|
+
})]);
|
|
7957
|
+
return {
|
|
7958
|
+
depositRefundPolicy: depositRefundPolicySchema,
|
|
7959
|
+
instalmentPlan,
|
|
7960
|
+
flexibleBalanceDueDateRule: flexibleBalance.dueDateRule,
|
|
7961
|
+
flexibleBalanceConfig: flexibleBalance.config,
|
|
7962
|
+
paymentCollectionOption,
|
|
7963
|
+
paymentTerms,
|
|
7964
|
+
paymentOptionsChoice
|
|
7965
|
+
};
|
|
7966
|
+
}
|
|
7967
|
+
function createBookingPaymentOptionSchemas(mode) {
|
|
7968
|
+
return mode === "strict" ? buildBookingPaymentOptionSchemas(strictObject) : buildBookingPaymentOptionSchemas(stripObject);
|
|
7969
|
+
}
|
|
7970
|
+
const bookingPaymentOptionSchemas = createBookingPaymentOptionSchemas("strip");
|
|
7971
|
+
bookingPaymentOptionSchemas.depositRefundPolicy;
|
|
7972
|
+
bookingPaymentOptionSchemas.instalmentPlan;
|
|
7973
|
+
bookingPaymentOptionSchemas.flexibleBalanceDueDateRule;
|
|
7974
|
+
bookingPaymentOptionSchemas.flexibleBalanceConfig;
|
|
7975
|
+
bookingPaymentOptionSchemas.paymentCollectionOption;
|
|
7976
|
+
const bookingPaymentTermsSchema = bookingPaymentOptionSchemas.paymentTerms;
|
|
7977
|
+
bookingPaymentOptionSchemas.paymentOptionsChoice;
|
|
7978
|
+
//#endregion
|
|
7979
|
+
//#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
|
|
7980
|
+
const blockBookingPaymentTermsSchema = bookingPaymentTermsSchema;
|
|
7898
7981
|
//#endregion
|
|
7899
7982
|
//#region ../blocks/src/system/blocks/shared/bookingConsent.ts
|
|
7900
7983
|
const BOOKING_REQUIREMENT_CONSENT_FIELD_PREFIX = "booking_requirement_consent_";
|
|
@@ -8156,7 +8239,6 @@ const publicEventBaseSchema = z.object({
|
|
|
8156
8239
|
description: z.string().nullable(),
|
|
8157
8240
|
content: z.object({ body: RichTextDocSchema.nullable().optional() }).optional(),
|
|
8158
8241
|
presentation: z.object({
|
|
8159
|
-
cardTitleOverride: z.string().nullable().optional(),
|
|
8160
8242
|
summary: z.string().nullable().optional(),
|
|
8161
8243
|
image: mediaSchema.nullable().optional()
|
|
8162
8244
|
}).optional(),
|
|
@@ -8189,6 +8271,7 @@ const publicEventBaseSchema = z.object({
|
|
|
8189
8271
|
"archived"
|
|
8190
8272
|
]).optional(),
|
|
8191
8273
|
timeZone: z.string(),
|
|
8274
|
+
siteTimeZone: z.string().optional(),
|
|
8192
8275
|
pricing: publicEventPricingSchema,
|
|
8193
8276
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
8194
8277
|
cancellationPolicy: z.object({ refunds: z.object({
|
|
@@ -8716,7 +8799,7 @@ var BlockApiError = class extends Error {
|
|
|
8716
8799
|
this.name = "BlockApiError";
|
|
8717
8800
|
}
|
|
8718
8801
|
};
|
|
8719
|
-
function isRecord$
|
|
8802
|
+
function isRecord$7(value) {
|
|
8720
8803
|
return typeof value === "object" && value !== null;
|
|
8721
8804
|
}
|
|
8722
8805
|
function isJsonResponseContentType(contentType) {
|
|
@@ -8740,15 +8823,15 @@ async function parseJsonBody(response) {
|
|
|
8740
8823
|
}
|
|
8741
8824
|
}
|
|
8742
8825
|
function isFieldError(value) {
|
|
8743
|
-
return isRecord$
|
|
8826
|
+
return isRecord$7(value) && !Array.isArray(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
|
|
8744
8827
|
}
|
|
8745
8828
|
function fieldErrorsFromUnknown(value) {
|
|
8746
8829
|
if (!Array.isArray(value)) return void 0;
|
|
8747
8830
|
return value.every(isFieldError) ? value : void 0;
|
|
8748
8831
|
}
|
|
8749
8832
|
function getBlockApiErrorDetails(data) {
|
|
8750
|
-
if (!isRecord$
|
|
8751
|
-
const nestedError = isRecord$
|
|
8833
|
+
if (!isRecord$7(data)) return {};
|
|
8834
|
+
const nestedError = isRecord$7(data.error) ? data.error : void 0;
|
|
8752
8835
|
const message = typeof nestedError?.message === "string" ? nestedError.message : typeof data.message === "string" ? data.message : void 0;
|
|
8753
8836
|
const code = typeof nestedError?.code === "string" ? nestedError.code : typeof data.code === "string" ? data.code : void 0;
|
|
8754
8837
|
const fieldErrors = fieldErrorsFromUnknown(nestedError?.fieldErrors) ?? fieldErrorsFromUnknown(data.fieldErrors);
|
|
@@ -9317,10 +9400,11 @@ function createBlockApi(config) {
|
|
|
9317
9400
|
},
|
|
9318
9401
|
async sendMagicLink(data) {
|
|
9319
9402
|
const sid = requireSiteId();
|
|
9320
|
-
|
|
9403
|
+
return request(PORTAL.sendMagicLink, { body: {
|
|
9321
9404
|
siteId: sid,
|
|
9322
9405
|
email: data.email,
|
|
9323
|
-
redirectUrl: data.redirectUrl
|
|
9406
|
+
redirectUrl: data.redirectUrl,
|
|
9407
|
+
demoBookingPass: data.demoBookingPass
|
|
9324
9408
|
} });
|
|
9325
9409
|
},
|
|
9326
9410
|
async logout() {
|
|
@@ -9465,7 +9549,7 @@ function err(error) {
|
|
|
9465
9549
|
error
|
|
9466
9550
|
};
|
|
9467
9551
|
}
|
|
9468
|
-
function assertNever(value, message) {
|
|
9552
|
+
function assertNever$1(value, message) {
|
|
9469
9553
|
throw new Error(message ?? `Unexpected value: ${String(value)}`);
|
|
9470
9554
|
}
|
|
9471
9555
|
//#endregion
|
|
@@ -9543,7 +9627,7 @@ function resolveAppointmentCheckoutVerificationState(input) {
|
|
|
9543
9627
|
tag: "timeout",
|
|
9544
9628
|
sessionId: input.config.sessionId,
|
|
9545
9629
|
appointmentId,
|
|
9546
|
-
message: "
|
|
9630
|
+
message: "We’re still confirming your payment. This can take a minute – you can check again, and you won’t be charged twice."
|
|
9547
9631
|
};
|
|
9548
9632
|
if (input.pollingStatus === "failed") {
|
|
9549
9633
|
if (paymentStatus === "refunded") return {
|
|
@@ -9607,26 +9691,26 @@ function deriveBookingFormViewState(input) {
|
|
|
9607
9691
|
message: input.verificationState.message
|
|
9608
9692
|
};
|
|
9609
9693
|
case "timeout": return {
|
|
9610
|
-
kind: "
|
|
9694
|
+
kind: "timeout",
|
|
9611
9695
|
message: input.verificationState.message
|
|
9612
9696
|
};
|
|
9613
9697
|
case "confirmed": return {
|
|
9614
9698
|
kind: "success",
|
|
9615
9699
|
resourceName: input.verificationState.resourceName
|
|
9616
9700
|
};
|
|
9617
|
-
default: return assertNever(input.verificationState);
|
|
9701
|
+
default: return assertNever$1(input.verificationState);
|
|
9618
9702
|
}
|
|
9619
9703
|
}
|
|
9620
9704
|
function resolveBookingSiteId(siteId, form) {
|
|
9621
9705
|
return siteId || form?.siteId || "";
|
|
9622
9706
|
}
|
|
9623
9707
|
function normalizeBookingFormConfig(form) {
|
|
9624
|
-
if (!isRecord$
|
|
9708
|
+
if (!isRecord$6(form)) return null;
|
|
9625
9709
|
const id = readNonEmptyString(form.id);
|
|
9626
9710
|
const name = readNonEmptyString(form.name);
|
|
9627
9711
|
if (!id || !name) return null;
|
|
9628
|
-
const schemaSource = isRecord$
|
|
9629
|
-
const settingsSource = isRecord$
|
|
9712
|
+
const schemaSource = isRecord$6(form.schema) ? form.schema : isRecord$6(form.schemaJson) ? form.schemaJson : null;
|
|
9713
|
+
const settingsSource = isRecord$6(form.settings) ? form.settings : isRecord$6(form.settingsJson) ? form.settingsJson : null;
|
|
9630
9714
|
return {
|
|
9631
9715
|
id,
|
|
9632
9716
|
name,
|
|
@@ -9646,8 +9730,8 @@ function normalizeBookingServices(services) {
|
|
|
9646
9730
|
};
|
|
9647
9731
|
if (!services) return [];
|
|
9648
9732
|
if (Array.isArray(services)) return services.filter(isBookingFormService).map(normalizeService);
|
|
9649
|
-
if (isRecord$
|
|
9650
|
-
return isRecord$
|
|
9733
|
+
if (isRecord$6(services) && "services" in services) return Array.isArray(services.services) ? services.services.filter(isBookingFormService).map(normalizeService) : [];
|
|
9734
|
+
return isRecord$6(services) ? Object.values(services).filter(isBookingFormService).map(normalizeService) : [];
|
|
9651
9735
|
}
|
|
9652
9736
|
function normalizeBookingSchema(value) {
|
|
9653
9737
|
if (!value) return void 0;
|
|
@@ -9658,7 +9742,7 @@ function normalizeBookingSchema(value) {
|
|
|
9658
9742
|
};
|
|
9659
9743
|
}
|
|
9660
9744
|
function readBookingFormField(value) {
|
|
9661
|
-
if (!isRecord$
|
|
9745
|
+
if (!isRecord$6(value)) return null;
|
|
9662
9746
|
const id = readNonEmptyString(value.id);
|
|
9663
9747
|
const label = readNonEmptyString(value.label);
|
|
9664
9748
|
const type = readBookingFieldType(value.type);
|
|
@@ -9701,7 +9785,7 @@ function readBookingFieldOptions(value) {
|
|
|
9701
9785
|
return options.length > 0 ? options : void 0;
|
|
9702
9786
|
}
|
|
9703
9787
|
function readBookingFieldOption(value) {
|
|
9704
|
-
if (!isRecord$
|
|
9788
|
+
if (!isRecord$6(value)) return null;
|
|
9705
9789
|
const optionValue = readNonEmptyString(value.value);
|
|
9706
9790
|
const label = readNonEmptyString(value.label);
|
|
9707
9791
|
return optionValue && label ? {
|
|
@@ -9721,7 +9805,7 @@ function normalizeBookingSettings(value) {
|
|
|
9721
9805
|
};
|
|
9722
9806
|
}
|
|
9723
9807
|
function isBookingFormService(value) {
|
|
9724
|
-
return isRecord$
|
|
9808
|
+
return isRecord$6(value) && typeof value.id === "string" && typeof value.siteId === "string" && typeof value.title === "string" && (value.consent === void 0 || blockBookingConsentSchema.safeParse(value.consent).success);
|
|
9725
9809
|
}
|
|
9726
9810
|
function collectBookingCustomFields(data) {
|
|
9727
9811
|
const customFields = {};
|
|
@@ -9771,26 +9855,24 @@ function readStringArray(value) {
|
|
|
9771
9855
|
const strings = value.filter((item) => typeof item === "string");
|
|
9772
9856
|
return strings.length > 0 ? strings : void 0;
|
|
9773
9857
|
}
|
|
9774
|
-
function isRecord$
|
|
9858
|
+
function isRecord$6(value) {
|
|
9775
9859
|
return typeof value === "object" && value !== null;
|
|
9776
9860
|
}
|
|
9777
9861
|
function getBookingServicePaymentSelectionMode(service) {
|
|
9778
9862
|
if (service?.paymentTermsAvailability?.kind === "pending_stripe_setup") return "pending_stripe_setup";
|
|
9779
9863
|
const allowedKinds = service?.paymentTerms?.allowedOptions.map((option) => option.kind) ?? [];
|
|
9780
9864
|
if (allowedKinds.length === 0) return "implicit_upfront";
|
|
9781
|
-
if (allowedKinds.
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9865
|
+
if (!validateBookingPaymentOptionKinds(allowedKinds).ok) return "unsupported";
|
|
9866
|
+
if (allowedKinds.length > 1) return "choice_required";
|
|
9867
|
+
const onlyKind = allowedKinds[0];
|
|
9868
|
+
switch (onlyKind) {
|
|
9869
|
+
case "upfront": return "implicit_upfront";
|
|
9870
|
+
case "deferred_manual": return "implicit_deferred_manual";
|
|
9871
|
+
case "instalment_plan": return "implicit_instalment_plan";
|
|
9872
|
+
case "flexible_balance": return "implicit_flexible_balance";
|
|
9873
|
+
case void 0: return "unsupported";
|
|
9874
|
+
default: return assertNever$1(onlyKind);
|
|
9791
9875
|
}
|
|
9792
|
-
if (allowedKinds.length === 2 && allowedKinds.includes("upfront") && (allowedKinds.includes("deferred_manual") || allowedKinds.includes("instalment_plan") || allowedKinds.includes("flexible_balance"))) return "choice_required";
|
|
9793
|
-
return "unsupported";
|
|
9794
9876
|
}
|
|
9795
9877
|
function resolveDefaultBookingServiceId(formConfig, services) {
|
|
9796
9878
|
const configuredServiceId = toTrimmedString(formConfig?.settings?.serviceId);
|
|
@@ -9962,11 +10044,43 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
9962
10044
|
case "sliding-amount-out-of-range": return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
9963
10045
|
case "payment-option-unsupported": return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
9964
10046
|
case "service-missing-duration": return `Service "${error.serviceTitle}" is missing duration. Please update the service in the dashboard to include a duration (e.g., 30 minutes).`;
|
|
9965
|
-
default: return assertNever(error);
|
|
10047
|
+
default: return assertNever$1(error);
|
|
10048
|
+
}
|
|
10049
|
+
}
|
|
10050
|
+
const DEFAULT_BOOKING_SUCCESS_COPY = {
|
|
10051
|
+
message: "Your booking has been confirmed.",
|
|
10052
|
+
defaultEmailSentence: "Check your email for details."
|
|
10053
|
+
};
|
|
10054
|
+
const DEFAULT_BOOKING_SUCCESS_MESSAGE = "Your booking has been confirmed. Check your email for details.";
|
|
10055
|
+
function getBookingSuccessCopy(successMessage) {
|
|
10056
|
+
const customMessage = successMessage?.trim();
|
|
10057
|
+
return customMessage && customMessage !== DEFAULT_BOOKING_SUCCESS_MESSAGE ? { message: customMessage } : DEFAULT_BOOKING_SUCCESS_COPY;
|
|
10058
|
+
}
|
|
10059
|
+
//#endregion
|
|
10060
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.payment-confirmation.ts
|
|
10061
|
+
function bookingServiceRequiresPaymentBeforeBooking(input) {
|
|
10062
|
+
switch (getBookingServicePaymentSelectionMode(input.service)) {
|
|
10063
|
+
case "implicit_upfront":
|
|
10064
|
+
case "implicit_instalment_plan":
|
|
10065
|
+
case "implicit_flexible_balance": return true;
|
|
10066
|
+
case "choice_required": return input.selectedCollectionOptionKind !== void 0 && input.selectedCollectionOptionKind !== "deferred_manual";
|
|
10067
|
+
case "implicit_deferred_manual":
|
|
10068
|
+
case "pending_stripe_setup":
|
|
10069
|
+
case "unsupported": return false;
|
|
9966
10070
|
}
|
|
9967
10071
|
}
|
|
9968
|
-
function
|
|
9969
|
-
|
|
10072
|
+
function resolveBookingPaymentConfirmationSummary(input) {
|
|
10073
|
+
const service = input.service;
|
|
10074
|
+
if (!service || input.hasSelectedAppointmentPackage || !Number.isFinite(input.priceAmount) || input.priceAmount <= 0 || !service.durationMinutes || !bookingServiceRequiresPaymentBeforeBooking({
|
|
10075
|
+
service,
|
|
10076
|
+
selectedCollectionOptionKind: input.selectedCollectionOptionKind
|
|
10077
|
+
})) return null;
|
|
10078
|
+
return {
|
|
10079
|
+
serviceTitle: service.title,
|
|
10080
|
+
durationMinutes: service.durationMinutes,
|
|
10081
|
+
priceAmount: input.priceAmount,
|
|
10082
|
+
priceCurrency: service.priceCurrency ?? service.pricing?.currency ?? "USD"
|
|
10083
|
+
};
|
|
9970
10084
|
}
|
|
9971
10085
|
//#endregion
|
|
9972
10086
|
//#region ../blocks/src/system/runtime/hooks/useSelectedAppointmentConsentForm.ts
|
|
@@ -10183,7 +10297,7 @@ function availableDatesReducer(state, action) {
|
|
|
10183
10297
|
data: state.data,
|
|
10184
10298
|
message: action.message
|
|
10185
10299
|
};
|
|
10186
|
-
default: return assertNever(action);
|
|
10300
|
+
default: return assertNever$1(action);
|
|
10187
10301
|
}
|
|
10188
10302
|
}
|
|
10189
10303
|
//#endregion
|
|
@@ -10320,7 +10434,7 @@ function getAvailableSlots(state) {
|
|
|
10320
10434
|
case "loaded":
|
|
10321
10435
|
case "refreshing":
|
|
10322
10436
|
case "error": return state.slots;
|
|
10323
|
-
default: return assertNever(state);
|
|
10437
|
+
default: return assertNever$1(state);
|
|
10324
10438
|
}
|
|
10325
10439
|
}
|
|
10326
10440
|
function hasLoadedAvailableSlots(state) {
|
|
@@ -10330,7 +10444,7 @@ function hasLoadedAvailableSlots(state) {
|
|
|
10330
10444
|
case "refreshing":
|
|
10331
10445
|
case "error": return state.hasLoaded;
|
|
10332
10446
|
case "loaded": return true;
|
|
10333
|
-
default: return assertNever(state);
|
|
10447
|
+
default: return assertNever$1(state);
|
|
10334
10448
|
}
|
|
10335
10449
|
}
|
|
10336
10450
|
function isLoadingAvailableSlots(state) {
|
|
@@ -10364,7 +10478,7 @@ function availableSlotsReducer(state, action) {
|
|
|
10364
10478
|
hasLoaded: hasLoadedAvailableSlots(state),
|
|
10365
10479
|
message: action.message
|
|
10366
10480
|
};
|
|
10367
|
-
default: return assertNever(action);
|
|
10481
|
+
default: return assertNever$1(action);
|
|
10368
10482
|
}
|
|
10369
10483
|
}
|
|
10370
10484
|
//#endregion
|
|
@@ -10459,6 +10573,19 @@ function useAvailableSlots({ siteId: _siteId, serviceId, resourceId, selectedDat
|
|
|
10459
10573
|
};
|
|
10460
10574
|
}
|
|
10461
10575
|
//#endregion
|
|
10576
|
+
//#region ../blocks/src/system/runtime/hooks/useBookingNowIso.ts
|
|
10577
|
+
/**
|
|
10578
|
+
* The moment a booking or registration flow opened, as an ISO timestamp.
|
|
10579
|
+
*
|
|
10580
|
+
* Payment previews take this as their "now" so the pure view-model builders
|
|
10581
|
+
* never read the clock themselves. It's captured once per mount, which keeps
|
|
10582
|
+
* memoised previews stable across renders.
|
|
10583
|
+
*/
|
|
10584
|
+
function useBookingNowIso() {
|
|
10585
|
+
const [nowIso] = useState(() => (/* @__PURE__ */ new Date()).toISOString());
|
|
10586
|
+
return nowIso;
|
|
10587
|
+
}
|
|
10588
|
+
//#endregion
|
|
10462
10589
|
//#region ../blocks/src/system/runtime/hooks/useBookingSubmission.state.ts
|
|
10463
10590
|
const initialBookingSubmissionState = {
|
|
10464
10591
|
status: { tag: "idle" },
|
|
@@ -10480,13 +10607,61 @@ function bookingSubmissionReducer(state, action) {
|
|
|
10480
10607
|
feedback: reportWorkflowError(state, action.message).feedback
|
|
10481
10608
|
};
|
|
10482
10609
|
case "feedback-cleared": return clearWorkflowFeedback(state);
|
|
10483
|
-
default: return assertNever(action);
|
|
10610
|
+
default: return assertNever$1(action);
|
|
10484
10611
|
}
|
|
10485
10612
|
}
|
|
10486
10613
|
function selectIsSubmitting(state) {
|
|
10487
10614
|
return state.status.tag === "submitting";
|
|
10488
10615
|
}
|
|
10489
10616
|
//#endregion
|
|
10617
|
+
//#region ../blocks/src/system/runtime/shared/utils/demoBookingPassStorage.ts
|
|
10618
|
+
const STORAGE_KEY = "riverbank:demo-booking-passes:v1";
|
|
10619
|
+
const MAX_STORED_PASSES = 10;
|
|
10620
|
+
function normalizeDemoBookingEmail(email) {
|
|
10621
|
+
return email.trim().toLowerCase();
|
|
10622
|
+
}
|
|
10623
|
+
function storeDemoBookingPass(email, pass) {
|
|
10624
|
+
try {
|
|
10625
|
+
const normalizedEmail = normalizeDemoBookingEmail(email);
|
|
10626
|
+
if (!normalizedEmail || !pass) return;
|
|
10627
|
+
const current = readStoredDemoBookingPasses();
|
|
10628
|
+
const updated = [{
|
|
10629
|
+
email: normalizedEmail,
|
|
10630
|
+
pass
|
|
10631
|
+
}, ...current.filter((entry) => entry.email !== normalizedEmail)].slice(0, MAX_STORED_PASSES);
|
|
10632
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
|
|
10633
|
+
} catch {}
|
|
10634
|
+
}
|
|
10635
|
+
function storeDemoBookingPassIfAvailable(email, pass) {
|
|
10636
|
+
if (email && pass) storeDemoBookingPass(email, pass);
|
|
10637
|
+
}
|
|
10638
|
+
function getDemoBookingPass(email) {
|
|
10639
|
+
try {
|
|
10640
|
+
const normalizedEmail = normalizeDemoBookingEmail(email);
|
|
10641
|
+
return readStoredDemoBookingPasses().find((entry) => entry.email === normalizedEmail)?.pass ?? null;
|
|
10642
|
+
} catch {
|
|
10643
|
+
return null;
|
|
10644
|
+
}
|
|
10645
|
+
}
|
|
10646
|
+
function readStoredDemoBookingPasses() {
|
|
10647
|
+
try {
|
|
10648
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
10649
|
+
if (!raw) return [];
|
|
10650
|
+
const parsed = JSON.parse(raw);
|
|
10651
|
+
return Array.isArray(parsed) ? parsed.filter(isStoredDemoBookingPass) : [];
|
|
10652
|
+
} catch {
|
|
10653
|
+
return [];
|
|
10654
|
+
}
|
|
10655
|
+
}
|
|
10656
|
+
function isStoredDemoBookingPass(value) {
|
|
10657
|
+
if (!isRecord$5(value)) return false;
|
|
10658
|
+
const record = value;
|
|
10659
|
+
return typeof record.email === "string" && record.email.length > 0 && typeof record.pass === "string" && record.pass.length > 0;
|
|
10660
|
+
}
|
|
10661
|
+
function isRecord$5(value) {
|
|
10662
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10663
|
+
}
|
|
10664
|
+
//#endregion
|
|
10490
10665
|
//#region ../blocks/src/system/runtime/hooks/useBookingSubmission.ts
|
|
10491
10666
|
/**
|
|
10492
10667
|
* Custom hook for submitting appointment bookings
|
|
@@ -10552,6 +10727,7 @@ function useBookingSubmission(_siteId) {
|
|
|
10552
10727
|
successUrl: data.successUrl,
|
|
10553
10728
|
cancelUrl: data.cancelUrl
|
|
10554
10729
|
});
|
|
10730
|
+
storeDemoBookingPassIfAvailable(response.customer.email, response.demoBookingPass);
|
|
10555
10731
|
dispatch({
|
|
10556
10732
|
type: "submission-succeeded",
|
|
10557
10733
|
message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
|
|
@@ -10590,15 +10766,18 @@ function completeBookingSubmission(input) {
|
|
|
10590
10766
|
kind: "checkout_redirect",
|
|
10591
10767
|
checkoutUrl: data.checkoutUrl,
|
|
10592
10768
|
sessionId: data.sessionId,
|
|
10769
|
+
customerEmail: data.customer.email,
|
|
10770
|
+
...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
|
|
10593
10771
|
...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
|
|
10594
10772
|
}
|
|
10595
10773
|
};
|
|
10596
10774
|
}
|
|
10775
|
+
const successCopy = getBookingSuccessCopy(input.successMessage);
|
|
10597
10776
|
input.dispatch({
|
|
10598
10777
|
type: "feedback-set",
|
|
10599
10778
|
feedback: {
|
|
10600
10779
|
kind: "success",
|
|
10601
|
-
message:
|
|
10780
|
+
message: successCopy.defaultEmailSentence ? `${successCopy.message} ${successCopy.defaultEmailSentence}`.trim() : successCopy.message,
|
|
10602
10781
|
resourceName: data.appointment.resourceName
|
|
10603
10782
|
}
|
|
10604
10783
|
});
|
|
@@ -10608,6 +10787,8 @@ function completeBookingSubmission(input) {
|
|
|
10608
10787
|
kind: "booked",
|
|
10609
10788
|
appointmentId: data.appointment.id,
|
|
10610
10789
|
resourceName: data.appointment.resourceName,
|
|
10790
|
+
customerEmail: data.customer.email,
|
|
10791
|
+
...data.demoBookingPass ? { demoBookingPass: data.demoBookingPass } : {},
|
|
10611
10792
|
...data.mailingListSignupNote ? { mailingListSignupNote: data.mailingListSignupNote } : {}
|
|
10612
10793
|
}
|
|
10613
10794
|
};
|
|
@@ -10788,168 +10969,390 @@ function useDiscountCodeUi(options) {
|
|
|
10788
10969
|
};
|
|
10789
10970
|
}
|
|
10790
10971
|
//#endregion
|
|
10791
|
-
//#region ../
|
|
10792
|
-
function
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
description: "Pay everything today and your booking is confirmed.",
|
|
10796
|
-
ctaLabel: `Pay ${formattedTotal} now`
|
|
10797
|
-
};
|
|
10798
|
-
}
|
|
10799
|
-
function buildDeferredManualBookingPaymentOptionCopy() {
|
|
10800
|
-
return {
|
|
10801
|
-
title: "Pay offline",
|
|
10802
|
-
description: "Book now and pay the business later, outside the platform.",
|
|
10803
|
-
helperText: "Nothing is due today.",
|
|
10804
|
-
ctaLabel: "Book now"
|
|
10805
|
-
};
|
|
10806
|
-
}
|
|
10807
|
-
function buildInstalmentBookingPaymentOptionCopy(input) {
|
|
10808
|
-
return {
|
|
10809
|
-
title: "Payment plan",
|
|
10810
|
-
description: describeInstalmentPlanCopy(input),
|
|
10811
|
-
helperText: "You can pay the rest early any time in your customer portal.",
|
|
10812
|
-
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
10813
|
-
};
|
|
10814
|
-
}
|
|
10815
|
-
function describeInstalmentPlanCopy(input) {
|
|
10816
|
-
if (input.depositRefundability) return `Pay ${input.formattedDueToday} today, then continue with scheduled payments. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`;
|
|
10817
|
-
if (input.futurePaymentCount === 0) return `Pay ${input.formattedDueToday} today.`;
|
|
10818
|
-
if (input.futurePaymentCount === 1) return `Pay ${input.formattedDueToday} today, then one more payment later.`;
|
|
10819
|
-
const formattedFirstFuture = input.formattedFirstFuture ?? input.formattedDueToday;
|
|
10820
|
-
return `Pay ${input.formattedDueToday} today, then ${input.futurePaymentCount} more ${input.cadenceLabel} payments from ${formattedFirstFuture}.`;
|
|
10821
|
-
}
|
|
10822
|
-
function buildFlexibleBalanceBookingPaymentOptionCopy(input) {
|
|
10823
|
-
return {
|
|
10824
|
-
title: "Deposit now, pay the rest later",
|
|
10825
|
-
description: `Pay ${input.formattedDueToday} today, then pay the remaining balance any time before ${input.dueDateLabel}. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`,
|
|
10826
|
-
helperText: "You can return in your customer portal to pay the rest before the due date.",
|
|
10827
|
-
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
10828
|
-
};
|
|
10829
|
-
}
|
|
10830
|
-
function formatDepositRefundabilityLabel(depositRefundability) {
|
|
10831
|
-
return depositRefundability === "non_refundable" ? "non-refundable" : "refundable";
|
|
10972
|
+
//#region ../commerce/src/utils/assertNever.ts
|
|
10973
|
+
function assertNever(value, message) {
|
|
10974
|
+
if (message) throw new Error(message);
|
|
10975
|
+
throw new Error(`Unexpected value: ${String(value)}`);
|
|
10832
10976
|
}
|
|
10833
10977
|
//#endregion
|
|
10834
|
-
//#region ../
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
* @param cents - Price in cents
|
|
10844
|
-
* @param currency - ISO 4217 currency code (e.g., 'USD', 'GBP')
|
|
10845
|
-
* @param locale - Optional locale override (defaults to the currency's locale)
|
|
10846
|
-
* @returns Formatted price string (e.g., "£100.00")
|
|
10847
|
-
*/
|
|
10848
|
-
function formatPrice(cents, currency = "GBP", locale) {
|
|
10849
|
-
return formatCurrencyAmount(cents, currency, { locale });
|
|
10978
|
+
//#region ../commerce/src/purchase/bookingInstalmentSchedule.ts
|
|
10979
|
+
function resolveBookingInitialInstalmentAmountCents(input) {
|
|
10980
|
+
const totalAmountCents = Math.max(0, input.totalAmountCents);
|
|
10981
|
+
switch (input.plan.kind) {
|
|
10982
|
+
case "deposit_plus_one_remainder":
|
|
10983
|
+
case "deposit_plus_scheduled_instalments": return clampConfiguredAmount(input.plan.depositAmountCents, totalAmountCents);
|
|
10984
|
+
case "equal_scheduled_instalments": return splitAmountWithRemainderInFirst(totalAmountCents, input.plan.instalmentCount)[0] ?? 0;
|
|
10985
|
+
default: return assertNever(input.plan);
|
|
10986
|
+
}
|
|
10850
10987
|
}
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10988
|
+
function buildBookingInstalmentSchedule(input) {
|
|
10989
|
+
const totalAmountCents = Math.max(0, input.totalAmountCents);
|
|
10990
|
+
switch (input.plan.kind) {
|
|
10991
|
+
case "deposit_plus_one_remainder": {
|
|
10992
|
+
const depositAmountCents = resolveBookingInitialInstalmentAmountCents(input);
|
|
10993
|
+
const remainderAmountCents = Math.max(0, totalAmountCents - depositAmountCents);
|
|
10994
|
+
return omitZeroAmountFutureRows([createScheduleRow({
|
|
10995
|
+
sequence: 1,
|
|
10996
|
+
stateAtBooking: "paid_today",
|
|
10997
|
+
dueAt: input.anchorAt,
|
|
10998
|
+
amountCents: depositAmountCents
|
|
10999
|
+
}), createScheduleRow({
|
|
11000
|
+
sequence: 2,
|
|
11001
|
+
stateAtBooking: "scheduled",
|
|
11002
|
+
dueAt: addIntervalPreservingMonthAnchor(input.anchorAt, input.plan.remainderDueCount, input.plan.intervalUnit),
|
|
11003
|
+
amountCents: remainderAmountCents
|
|
11004
|
+
})]);
|
|
11005
|
+
}
|
|
11006
|
+
case "deposit_plus_scheduled_instalments": {
|
|
11007
|
+
const plan = input.plan;
|
|
11008
|
+
const depositAmountCents = resolveBookingInitialInstalmentAmountCents(input);
|
|
11009
|
+
const instalmentAmounts = splitAmountWithRemainderInFirst(Math.max(0, totalAmountCents - depositAmountCents), plan.instalmentCount);
|
|
11010
|
+
return omitZeroAmountFutureRows([createScheduleRow({
|
|
11011
|
+
sequence: 1,
|
|
11012
|
+
stateAtBooking: "paid_today",
|
|
11013
|
+
dueAt: input.anchorAt,
|
|
11014
|
+
amountCents: depositAmountCents
|
|
11015
|
+
}), ...instalmentAmounts.map((amountCents, index) => createScheduleRow({
|
|
11016
|
+
sequence: index + 2,
|
|
11017
|
+
stateAtBooking: "scheduled",
|
|
11018
|
+
dueAt: addIntervalPreservingMonthAnchor(input.anchorAt, plan.intervalCount * (index + 1), plan.intervalUnit),
|
|
11019
|
+
amountCents
|
|
11020
|
+
}))]);
|
|
11021
|
+
}
|
|
11022
|
+
case "equal_scheduled_instalments": {
|
|
11023
|
+
const plan = input.plan;
|
|
11024
|
+
return omitZeroAmountFutureRows(splitAmountWithRemainderInFirst(totalAmountCents, plan.instalmentCount).map((amountCents, index) => createScheduleRow({
|
|
11025
|
+
sequence: index + 1,
|
|
11026
|
+
stateAtBooking: index === 0 ? "paid_today" : "scheduled",
|
|
11027
|
+
dueAt: index === 0 ? input.anchorAt : addIntervalPreservingMonthAnchor(input.anchorAt, plan.intervalCount * index, plan.intervalUnit),
|
|
11028
|
+
amountCents
|
|
11029
|
+
})));
|
|
11030
|
+
}
|
|
11031
|
+
default: return assertNever(input.plan);
|
|
10867
11032
|
}
|
|
10868
11033
|
}
|
|
10869
|
-
function
|
|
10870
|
-
const currency = input.priceCurrency ?? "USD";
|
|
10871
|
-
const totalCents = Math.max(0, input.priceAmount ?? 0);
|
|
10872
|
-
const allowedOptions = input.paymentTerms?.allowedOptions ?? [{ kind: "upfront" }];
|
|
10873
|
-
const mode = allowedOptions.length > 1 ? "choice_required" : "single_option";
|
|
11034
|
+
function createScheduleRow(input) {
|
|
10874
11035
|
return {
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
totalCents,
|
|
10881
|
-
currency,
|
|
10882
|
-
bookingStartAt: input.bookingStartAt,
|
|
10883
|
-
locale: input.locale
|
|
10884
|
-
}))
|
|
11036
|
+
id: `payment-${input.sequence}`,
|
|
11037
|
+
sequence: input.sequence,
|
|
11038
|
+
stateAtBooking: input.stateAtBooking,
|
|
11039
|
+
dueAt: input.dueAt,
|
|
11040
|
+
amountCents: input.amountCents
|
|
10885
11041
|
};
|
|
10886
11042
|
}
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
11043
|
+
//#endregion
|
|
11044
|
+
//#region ../commerce/src/purchase/checkoutSessionMetadata.ts
|
|
11045
|
+
const datedOfferingSharedEngineMetadataShape = {
|
|
11046
|
+
datedOfferingEngineContractVersion: z.literal("shared_v1"),
|
|
11047
|
+
datedOfferingEngineRouteKind: z.literal("shared_whole_series_registration"),
|
|
11048
|
+
datedOfferingCapacityHoldId: z.string().uuid(),
|
|
11049
|
+
datedOfferingCapacityHoldAuditRef: z.string().uuid(),
|
|
11050
|
+
customerId: z.string().uuid(),
|
|
11051
|
+
eventSeriesId: z.string().uuid()
|
|
11052
|
+
};
|
|
11053
|
+
z.object(datedOfferingSharedEngineMetadataShape);
|
|
11054
|
+
const orderCheckoutSessionMetadataBaseShape = {
|
|
11055
|
+
type: z.literal("order"),
|
|
11056
|
+
site_id: z.string().uuid(),
|
|
11057
|
+
order_id: z.string().uuid().optional(),
|
|
11058
|
+
customer_email: z.string().email().optional(),
|
|
11059
|
+
customer_name: z.string().optional(),
|
|
11060
|
+
product_id: z.string().uuid().optional(),
|
|
11061
|
+
attendee_id: z.string().uuid().optional(),
|
|
11062
|
+
occurrence_id: z.string().uuid().optional(),
|
|
11063
|
+
tickets_count: z.string().optional(),
|
|
11064
|
+
notes: z.string().optional(),
|
|
11065
|
+
discount_redemption_id: z.string().uuid().optional(),
|
|
11066
|
+
discount_code_id: z.string().uuid().optional(),
|
|
11067
|
+
discount_code: z.string().optional(),
|
|
11068
|
+
discount_public_label: z.string().optional(),
|
|
11069
|
+
credit_reservation_id: z.string().uuid().optional(),
|
|
11070
|
+
credit_reserved_cents: z.string().optional(),
|
|
11071
|
+
discount_code_amount_cents: z.string().optional(),
|
|
11072
|
+
order_payment_reason: z.enum([
|
|
11073
|
+
"instalment_payoff",
|
|
11074
|
+
"flexible_balance_initial",
|
|
11075
|
+
"flexible_balance_paydown"
|
|
11076
|
+
]).optional(),
|
|
11077
|
+
order_payment_plan_id: z.string().uuid().optional(),
|
|
11078
|
+
order_flexible_balance_contract_id: z.string().uuid().optional()
|
|
11079
|
+
};
|
|
11080
|
+
const absentDatedOfferingSharedEngineMetadataShape = {
|
|
11081
|
+
datedOfferingEngineContractVersion: z.never().optional(),
|
|
11082
|
+
datedOfferingEngineRouteKind: z.never().optional(),
|
|
11083
|
+
datedOfferingCapacityHoldId: z.never().optional(),
|
|
11084
|
+
datedOfferingCapacityHoldAuditRef: z.never().optional(),
|
|
11085
|
+
customerId: z.never().optional(),
|
|
11086
|
+
eventSeriesId: z.never().optional()
|
|
11087
|
+
};
|
|
11088
|
+
const LegacyOrderCheckoutSessionMetadataSchema = z.object({
|
|
11089
|
+
...orderCheckoutSessionMetadataBaseShape,
|
|
11090
|
+
...absentDatedOfferingSharedEngineMetadataShape
|
|
11091
|
+
});
|
|
11092
|
+
const SharedDatedOfferingOrderCheckoutSessionMetadataSchema = z.object({
|
|
11093
|
+
...orderCheckoutSessionMetadataBaseShape,
|
|
11094
|
+
...datedOfferingSharedEngineMetadataShape
|
|
11095
|
+
});
|
|
11096
|
+
z.union([SharedDatedOfferingOrderCheckoutSessionMetadataSchema, LegacyOrderCheckoutSessionMetadataSchema]);
|
|
11097
|
+
//#endregion
|
|
11098
|
+
//#region ../commerce/src/purchase/stripeCommissionMetadata.ts
|
|
11099
|
+
/** Reasons are payment evidence, not an independent pricing policy. */
|
|
11100
|
+
const STRIPE_COMMISSION_FREE_REASONS = [
|
|
11101
|
+
"managed_billing",
|
|
11102
|
+
"no_commission_plan",
|
|
11103
|
+
"billing_evidence_invalid",
|
|
11104
|
+
"fee_rounds_to_zero",
|
|
11105
|
+
"payment_not_stripe"
|
|
11106
|
+
];
|
|
11107
|
+
const historicalContext = {
|
|
11108
|
+
currency: z.string().refine((value) => parseCurrencyCode(value) !== null).optional(),
|
|
11109
|
+
sourcePlanId: z.string().trim().min(1).optional()
|
|
11110
|
+
};
|
|
11111
|
+
const percentSchema = z.number().finite().min(0).max(100);
|
|
11112
|
+
z.discriminatedUnion("kind", [
|
|
11113
|
+
z.object({
|
|
11114
|
+
kind: z.literal("commission_free"),
|
|
11115
|
+
reason: z.enum(STRIPE_COMMISSION_FREE_REASONS),
|
|
11116
|
+
...historicalContext
|
|
11117
|
+
}),
|
|
11118
|
+
z.object({
|
|
11119
|
+
kind: z.literal("application_fee_amount"),
|
|
11120
|
+
amountCents: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
11121
|
+
percent: percentSchema,
|
|
11122
|
+
...historicalContext
|
|
11123
|
+
}),
|
|
11124
|
+
z.object({
|
|
11125
|
+
kind: z.literal("application_fee_percent"),
|
|
11126
|
+
percent: percentSchema,
|
|
11127
|
+
...historicalContext
|
|
11128
|
+
})
|
|
11129
|
+
]);
|
|
11130
|
+
toNonNegativeCents(0);
|
|
11131
|
+
//#endregion
|
|
11132
|
+
//#region ../commerce/src/purchase/event-registration-errors.ts
|
|
11133
|
+
const eventRegistrationErrors = {
|
|
11134
|
+
registrationClosed: {
|
|
11135
|
+
message: "Booking is currently closed for this event. Please contact the organiser if you’d like to find out more.",
|
|
11136
|
+
action: "none"
|
|
11137
|
+
},
|
|
11138
|
+
paymentInvestigationRequired: {
|
|
11139
|
+
message: "We still can’t confirm your payment. Please don’t make another payment. Contact the organiser so they can check your booking.",
|
|
11140
|
+
action: "none"
|
|
11141
|
+
},
|
|
11142
|
+
paymentProviderUnavailable: {
|
|
11143
|
+
message: "We couldn’t reach the payment provider. Please try again in a minute.",
|
|
11144
|
+
action: "retry"
|
|
11145
|
+
},
|
|
11146
|
+
paymentPageUnavailable: {
|
|
11147
|
+
message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
|
|
11148
|
+
action: "retry"
|
|
11149
|
+
},
|
|
11150
|
+
paymentUnavailable: {
|
|
11151
|
+
message: "Online payment is not available for this event right now. Please contact the organiser for help with booking.",
|
|
11152
|
+
action: "none"
|
|
11153
|
+
},
|
|
11154
|
+
capacityChanged: {
|
|
11155
|
+
message: "Sorry, there aren’t enough places left for your selection. Please check the available places and choose again.",
|
|
11156
|
+
action: "places"
|
|
11157
|
+
},
|
|
11158
|
+
selectionChanged: {
|
|
11159
|
+
message: "The booking options for this event have changed. Please check the latest options and choose your places again.",
|
|
11160
|
+
action: "places"
|
|
11161
|
+
},
|
|
11162
|
+
registrationPreparationChanged: {
|
|
11163
|
+
message: "The booking options for this event have changed. Please check the latest options and choose your places again.",
|
|
11164
|
+
action: "places"
|
|
11165
|
+
},
|
|
11166
|
+
registrationAlreadyExists: {
|
|
11167
|
+
message: "You already have a booking for this event. Please check your bookings to see its status. If you need help, contact the organiser.",
|
|
11168
|
+
action: "portal"
|
|
11169
|
+
},
|
|
11170
|
+
holdExpired: {
|
|
11171
|
+
message: "Your reservation has timed out. Please check availability and choose your places again.",
|
|
11172
|
+
action: "start"
|
|
11173
|
+
},
|
|
11174
|
+
waitlistUnavailable: {
|
|
11175
|
+
message: "Sorry, the waiting list place offered in this invitation is no longer available. Please check the event for available places or contact the organiser for help.",
|
|
11176
|
+
action: "event"
|
|
11177
|
+
},
|
|
11178
|
+
paymentContextMismatch: {
|
|
11179
|
+
message: "The payment options for this event have changed. Please check the latest options before continuing.",
|
|
11180
|
+
action: "payment-options"
|
|
11181
|
+
},
|
|
11182
|
+
verificationFailed: {
|
|
11183
|
+
message: "We couldn’t confirm this request came from a person. Please refresh the page and try again.",
|
|
11184
|
+
action: "none"
|
|
11185
|
+
},
|
|
11186
|
+
idempotencyConflict: {
|
|
11187
|
+
message: "You’ve already started booking this event. Please finish in the other tab if it’s still open, or check your booking status before starting again.",
|
|
11188
|
+
action: "portal"
|
|
11189
|
+
},
|
|
11190
|
+
invalidCommitInput: {
|
|
11191
|
+
message: "We couldn’t accept your booking details. Please check the information you entered and try again. If this keeps happening, contact the organiser for help.",
|
|
11192
|
+
action: "details"
|
|
11193
|
+
}
|
|
11194
|
+
};
|
|
11195
|
+
function parseEventRegistrationErrorReason(value) {
|
|
11196
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(eventRegistrationErrors, value) ? value : null;
|
|
11197
|
+
}
|
|
11198
|
+
//#endregion
|
|
11199
|
+
//#region ../blocks/src/system/runtime/shared/bookingPaymentOptionCopy.ts
|
|
11200
|
+
function buildUpfrontBookingPaymentOptionCopy(formattedTotal) {
|
|
11201
|
+
return {
|
|
11202
|
+
title: "Pay in full",
|
|
11203
|
+
description: "Pay everything today and your booking is confirmed.",
|
|
11204
|
+
ctaLabel: `Pay ${formattedTotal} now`
|
|
11205
|
+
};
|
|
11206
|
+
}
|
|
11207
|
+
function buildDeferredManualBookingPaymentOptionCopy() {
|
|
11208
|
+
return {
|
|
11209
|
+
title: "Pay offline",
|
|
11210
|
+
description: "Book now and pay the business later, outside the platform.",
|
|
11211
|
+
helperText: "Nothing is due today.",
|
|
11212
|
+
ctaLabel: "Book now"
|
|
11213
|
+
};
|
|
11214
|
+
}
|
|
11215
|
+
function buildInstalmentBookingPaymentOptionCopy(input) {
|
|
11216
|
+
return {
|
|
11217
|
+
title: "Payment plan",
|
|
11218
|
+
description: describeInstalmentPlanCopy(input),
|
|
11219
|
+
helperText: "You can pay the rest early any time in your customer portal.",
|
|
11220
|
+
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
11221
|
+
};
|
|
11222
|
+
}
|
|
11223
|
+
function describeInstalmentPlanCopy(input) {
|
|
11224
|
+
if (input.depositRefundability) return `Pay ${input.formattedDueToday} today, then continue with scheduled payments. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`;
|
|
11225
|
+
if (input.futurePaymentCount === 0) return `Pay ${input.formattedDueToday} today.`;
|
|
11226
|
+
if (input.futurePaymentCount === 1) return `Pay ${input.formattedDueToday} today, then one more payment later.`;
|
|
11227
|
+
const formattedFirstFuture = input.formattedFirstFuture ?? input.formattedDueToday;
|
|
11228
|
+
return `Pay ${input.formattedDueToday} today, then ${input.futurePaymentCount} more ${input.cadenceLabel} payments from ${formattedFirstFuture}.`;
|
|
11229
|
+
}
|
|
11230
|
+
function buildFlexibleBalanceBookingPaymentOptionCopy(input) {
|
|
11231
|
+
return {
|
|
11232
|
+
title: "Deposit now, pay the rest later",
|
|
11233
|
+
description: `Pay ${input.formattedDueToday} today, then pay the remaining balance any time before ${input.dueDateLabel}. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`,
|
|
11234
|
+
helperText: "You can return in your customer portal to pay the rest before the due date.",
|
|
11235
|
+
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
11236
|
+
};
|
|
11237
|
+
}
|
|
11238
|
+
function formatDepositRefundabilityLabel(depositRefundability) {
|
|
11239
|
+
return depositRefundability === "non_refundable" ? "non-refundable" : "refundable";
|
|
11240
|
+
}
|
|
11241
|
+
//#endregion
|
|
11242
|
+
//#region ../blocks/src/system/runtime/shared/utils/formatting.ts
|
|
11243
|
+
/**
|
|
11244
|
+
* Shared Formatting Utilities
|
|
11245
|
+
*
|
|
11246
|
+
* Currency and date formatting helpers for registration blocks.
|
|
11247
|
+
*/
|
|
11248
|
+
/**
|
|
11249
|
+
* Format a price in cents to a localized currency string.
|
|
11250
|
+
*
|
|
11251
|
+
* @param cents - Price in cents
|
|
11252
|
+
* @param currency - ISO 4217 currency code (e.g., 'USD', 'GBP')
|
|
11253
|
+
* @param locale - Optional locale override (defaults to the currency's locale)
|
|
11254
|
+
* @returns Formatted price string (e.g., "£100.00")
|
|
11255
|
+
*/
|
|
11256
|
+
function formatPrice(cents, currency = "GBP", locale) {
|
|
11257
|
+
return formatCurrencyAmount(cents, currency, { locale });
|
|
11258
|
+
}
|
|
11259
|
+
//#endregion
|
|
11260
|
+
//#region ../blocks/src/system/runtime/shared/bookingPaymentOptions.ts
|
|
11261
|
+
function resolveBookingPaymentDueNowCents(input) {
|
|
11262
|
+
switch (input.option.kind) {
|
|
11263
|
+
case "upfront": return input.totalCents;
|
|
11264
|
+
case "deferred_manual": return 0;
|
|
11265
|
+
case "instalment_plan": return resolveBookingInitialInstalmentAmountCents({
|
|
11266
|
+
totalAmountCents: input.totalCents,
|
|
11267
|
+
plan: input.option.plan
|
|
11268
|
+
});
|
|
11269
|
+
case "flexible_balance": return resolveFlexibleBalanceInitialPaymentCents({
|
|
11270
|
+
totalAmountCents: input.totalCents,
|
|
11271
|
+
config: input.option.config
|
|
11272
|
+
});
|
|
11273
|
+
default: return assertNever$1(input.option);
|
|
11274
|
+
}
|
|
11275
|
+
}
|
|
11276
|
+
function buildBookingPaymentSelectionViewModel(input) {
|
|
11277
|
+
const currency = input.priceCurrency ?? "USD";
|
|
11278
|
+
const totalCents = Math.max(0, input.priceAmount ?? 0);
|
|
11279
|
+
const allowedOptions = input.paymentTerms?.allowedOptions ?? [{ kind: "upfront" }];
|
|
11280
|
+
const mode = allowedOptions.length > 1 ? "choice_required" : "single_option";
|
|
11281
|
+
return {
|
|
11282
|
+
mode,
|
|
11283
|
+
sectionTitle: mode === "choice_required" ? "Choose how you'd like to pay" : "Payment",
|
|
11284
|
+
serviceTitle: input.serviceTitle,
|
|
11285
|
+
options: allowedOptions.map((option) => buildBookingPaymentOptionViewModel({
|
|
11286
|
+
option,
|
|
11287
|
+
totalCents,
|
|
11288
|
+
currency,
|
|
11289
|
+
bookingStartAt: input.bookingStartAt,
|
|
11290
|
+
nowIso: input.nowIso,
|
|
11291
|
+
locale: input.locale
|
|
11292
|
+
}))
|
|
11293
|
+
};
|
|
11294
|
+
}
|
|
11295
|
+
function buildBookingPaymentOptionViewModel(input) {
|
|
11296
|
+
switch (input.option.kind) {
|
|
11297
|
+
case "upfront": {
|
|
11298
|
+
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
11299
|
+
const copy = buildUpfrontBookingPaymentOptionCopy(formattedTotal);
|
|
11300
|
+
return {
|
|
11301
|
+
kind: "upfront",
|
|
11302
|
+
title: copy.title,
|
|
11303
|
+
description: copy.description,
|
|
11304
|
+
summaryRows: [{
|
|
11305
|
+
label: "Total",
|
|
11306
|
+
value: formattedTotal
|
|
11307
|
+
}, {
|
|
11308
|
+
label: "Due today",
|
|
11309
|
+
value: formattedTotal
|
|
11310
|
+
}],
|
|
11311
|
+
ctaLabel: copy.ctaLabel
|
|
11312
|
+
};
|
|
11313
|
+
}
|
|
11314
|
+
case "deferred_manual": {
|
|
11315
|
+
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
11316
|
+
const copy = buildDeferredManualBookingPaymentOptionCopy();
|
|
11317
|
+
return {
|
|
11318
|
+
kind: "deferred_manual",
|
|
11319
|
+
title: copy.title,
|
|
11320
|
+
description: copy.description,
|
|
11321
|
+
summaryRows: [{
|
|
11322
|
+
label: "Total",
|
|
11323
|
+
value: formattedTotal
|
|
11324
|
+
}, {
|
|
11325
|
+
label: "Due today",
|
|
11326
|
+
value: formatPrice(0, input.currency, input.locale)
|
|
11327
|
+
}],
|
|
11328
|
+
helperText: copy.helperText,
|
|
11329
|
+
ctaLabel: copy.ctaLabel
|
|
11330
|
+
};
|
|
11331
|
+
}
|
|
11332
|
+
case "instalment_plan": {
|
|
11333
|
+
const [firstRow, ...futureRows] = buildBookingInstalmentSchedule({
|
|
11334
|
+
anchorAt: input.nowIso,
|
|
11335
|
+
totalAmountCents: input.totalCents,
|
|
11336
|
+
plan: input.option.plan
|
|
11337
|
+
});
|
|
11338
|
+
const dueToday = firstRow?.amountCents ?? 0;
|
|
11339
|
+
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
11340
|
+
const formattedDueToday = formatPrice(dueToday, input.currency, input.locale);
|
|
11341
|
+
const depositRefundability = getBookingInstalmentDepositRefundability(input.option.plan);
|
|
11342
|
+
const copy = buildInstalmentBookingPaymentOptionCopy({
|
|
11343
|
+
formattedDueToday,
|
|
11344
|
+
futurePaymentCount: futureRows.length,
|
|
11345
|
+
formattedFirstFuture: futureRows[0] ? formatPrice(futureRows[0].amountCents, input.currency, input.locale) : null,
|
|
11346
|
+
cadenceLabel: getPaymentCadenceLabel(input.option.plan),
|
|
11347
|
+
depositRefundability
|
|
11348
|
+
});
|
|
11349
|
+
return {
|
|
11350
|
+
kind: "instalment_plan",
|
|
11351
|
+
title: copy.title,
|
|
11352
|
+
description: copy.description,
|
|
11353
|
+
summaryRows: [
|
|
11354
|
+
{
|
|
11355
|
+
label: "Total",
|
|
10953
11356
|
value: formattedTotal
|
|
10954
11357
|
},
|
|
10955
11358
|
{
|
|
@@ -10979,7 +11382,7 @@ function buildBookingPaymentOptionViewModel(input) {
|
|
|
10979
11382
|
const formattedDueToday = formatPrice(dueToday, input.currency, input.locale);
|
|
10980
11383
|
const formattedRemainingBalance = formatPrice(remainingBalance, input.currency, input.locale);
|
|
10981
11384
|
const dueAt = resolveFlexibleBalanceDueAt({
|
|
10982
|
-
bookingStartAt: input.bookingStartAt ??
|
|
11385
|
+
bookingStartAt: input.bookingStartAt ?? input.nowIso,
|
|
10983
11386
|
dueDateRule: input.option.config.dueDateRule
|
|
10984
11387
|
});
|
|
10985
11388
|
const copy = buildFlexibleBalanceBookingPaymentOptionCopy({
|
|
@@ -11017,43 +11420,7 @@ function buildBookingPaymentOptionViewModel(input) {
|
|
|
11017
11420
|
ctaLabel: copy.ctaLabel
|
|
11018
11421
|
};
|
|
11019
11422
|
}
|
|
11020
|
-
default: return assertNever(input.option);
|
|
11021
|
-
}
|
|
11022
|
-
}
|
|
11023
|
-
function buildInstalmentSchedulePreview(input) {
|
|
11024
|
-
const startAt = input.bookingStartAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
11025
|
-
switch (input.option.plan.kind) {
|
|
11026
|
-
case "deposit_plus_one_remainder": {
|
|
11027
|
-
const deposit = clampConfiguredAmount(input.option.plan.depositAmountCents, input.totalCents);
|
|
11028
|
-
const remainder = Math.max(0, input.totalCents - deposit);
|
|
11029
|
-
return compactSchedulePreview([{
|
|
11030
|
-
dueAt: startAt,
|
|
11031
|
-
amountCents: deposit
|
|
11032
|
-
}, {
|
|
11033
|
-
dueAt: addIntervalPreservingMonthAnchor(startAt, input.option.plan.remainderDueCount, input.option.plan.intervalUnit),
|
|
11034
|
-
amountCents: remainder
|
|
11035
|
-
}]);
|
|
11036
|
-
}
|
|
11037
|
-
case "deposit_plus_scheduled_instalments": {
|
|
11038
|
-
const plan = input.option.plan;
|
|
11039
|
-
const deposit = clampConfiguredAmount(plan.depositAmountCents, input.totalCents);
|
|
11040
|
-
const instalments = splitAmountWithRemainderInFirst(Math.max(0, input.totalCents - deposit), plan.instalmentCount);
|
|
11041
|
-
return compactSchedulePreview([{
|
|
11042
|
-
dueAt: startAt,
|
|
11043
|
-
amountCents: deposit
|
|
11044
|
-
}, ...instalments.map((amountCents, index) => ({
|
|
11045
|
-
dueAt: addIntervalPreservingMonthAnchor(startAt, plan.intervalCount * (index + 1), plan.intervalUnit),
|
|
11046
|
-
amountCents
|
|
11047
|
-
}))]);
|
|
11048
|
-
}
|
|
11049
|
-
case "equal_scheduled_instalments": {
|
|
11050
|
-
const plan = input.option.plan;
|
|
11051
|
-
return compactSchedulePreview(splitAmountWithRemainderInFirst(input.totalCents, plan.instalmentCount).map((amountCents, index) => ({
|
|
11052
|
-
dueAt: index === 0 ? startAt : addIntervalPreservingMonthAnchor(startAt, plan.intervalCount * index, plan.intervalUnit),
|
|
11053
|
-
amountCents
|
|
11054
|
-
})));
|
|
11055
|
-
}
|
|
11056
|
-
default: return assertNever(input.option.plan);
|
|
11423
|
+
default: return assertNever$1(input.option);
|
|
11057
11424
|
}
|
|
11058
11425
|
}
|
|
11059
11426
|
function getPaymentCadenceLabel(plan) {
|
|
@@ -11061,9 +11428,6 @@ function getPaymentCadenceLabel(plan) {
|
|
|
11061
11428
|
const unitLabel = intervalCount === 1 ? plan.intervalUnit : `${plan.intervalUnit}s`;
|
|
11062
11429
|
return intervalCount === 1 ? unitLabel : `every ${intervalCount} ${unitLabel}`;
|
|
11063
11430
|
}
|
|
11064
|
-
function compactSchedulePreview(schedule) {
|
|
11065
|
-
return omitZeroAmountFutureRows(schedule);
|
|
11066
|
-
}
|
|
11067
11431
|
function formatScheduleDate(isoString, locale) {
|
|
11068
11432
|
const date = new Date(isoString);
|
|
11069
11433
|
if (!Number.isFinite(date.getTime())) return isoString;
|
|
@@ -11071,11 +11435,11 @@ function formatScheduleDate(isoString, locale) {
|
|
|
11071
11435
|
}
|
|
11072
11436
|
//#endregion
|
|
11073
11437
|
//#region ../blocks/src/system/runtime/nodes/booking-form.service-categories.ts
|
|
11074
|
-
function isRecord$
|
|
11438
|
+
function isRecord$4(value) {
|
|
11075
11439
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11076
11440
|
}
|
|
11077
11441
|
function readCategory(value) {
|
|
11078
|
-
if (!isRecord$
|
|
11442
|
+
if (!isRecord$4(value)) return [];
|
|
11079
11443
|
const { id, name, description } = value;
|
|
11080
11444
|
if (typeof id !== "string" || id.trim() === "" || typeof name !== "string") return [];
|
|
11081
11445
|
return [{
|
|
@@ -11091,7 +11455,7 @@ function readCategory(value) {
|
|
|
11091
11455
|
* it.
|
|
11092
11456
|
*/
|
|
11093
11457
|
function normalizeBookingServiceCategories(services) {
|
|
11094
|
-
if (!isRecord$
|
|
11458
|
+
if (!isRecord$4(services) || !Array.isArray(services.categories)) return [];
|
|
11095
11459
|
return services.categories.flatMap(readCategory);
|
|
11096
11460
|
}
|
|
11097
11461
|
/**
|
|
@@ -11099,7 +11463,7 @@ function normalizeBookingServiceCategories(services) {
|
|
|
11099
11463
|
* its loader data (`data.services`).
|
|
11100
11464
|
*/
|
|
11101
11465
|
function readOverrideServiceCategories(data) {
|
|
11102
|
-
return isRecord$
|
|
11466
|
+
return isRecord$4(data) ? normalizeBookingServiceCategories(data.services) : [];
|
|
11103
11467
|
}
|
|
11104
11468
|
//#endregion
|
|
11105
11469
|
//#region ../blocks/src/system/runtime/nodes/booking-form.validationErrors.ts
|
|
@@ -11346,7 +11710,7 @@ function bookingFlowReducer(state, event) {
|
|
|
11346
11710
|
phase: "editing"
|
|
11347
11711
|
} : state;
|
|
11348
11712
|
case "reset": return event.initial;
|
|
11349
|
-
default: return assertNever(event);
|
|
11713
|
+
default: return assertNever$1(event);
|
|
11350
11714
|
}
|
|
11351
11715
|
}
|
|
11352
11716
|
function applyBookingServiceSelection(state, serviceId) {
|
|
@@ -11516,7 +11880,7 @@ function validateBookingStep(input) {
|
|
|
11516
11880
|
errors: createFieldBookingValidationErrors(errors)
|
|
11517
11881
|
} : { ok: true };
|
|
11518
11882
|
}
|
|
11519
|
-
default: return assertNever(input.stepId);
|
|
11883
|
+
default: return assertNever$1(input.stepId);
|
|
11520
11884
|
}
|
|
11521
11885
|
}
|
|
11522
11886
|
function validateBookingFields(input) {
|
|
@@ -11816,7 +12180,7 @@ function resolveAppointmentPackagesModel(input) {
|
|
|
11816
12180
|
selected
|
|
11817
12181
|
};
|
|
11818
12182
|
}
|
|
11819
|
-
default: return assertNever(input.state);
|
|
12183
|
+
default: return assertNever$1(input.state);
|
|
11820
12184
|
}
|
|
11821
12185
|
}
|
|
11822
12186
|
function toHeadlessEligibleAppointmentPackage(appointmentPackage) {
|
|
@@ -11865,7 +12229,7 @@ function isBlankFieldValue(value) {
|
|
|
11865
12229
|
return false;
|
|
11866
12230
|
}
|
|
11867
12231
|
function readAppointmentBookingOverrideData(value) {
|
|
11868
|
-
if (!isRecord$
|
|
12232
|
+
if (!isRecord$3(value)) return null;
|
|
11869
12233
|
const services = normalizeBookingServices(value.services);
|
|
11870
12234
|
return {
|
|
11871
12235
|
form: normalizeBookingFormConfig(value.form),
|
|
@@ -11880,7 +12244,7 @@ function createOverrideInputError(reason, message, warnInDev = false) {
|
|
|
11880
12244
|
message
|
|
11881
12245
|
};
|
|
11882
12246
|
}
|
|
11883
|
-
function isRecord$
|
|
12247
|
+
function isRecord$3(value) {
|
|
11884
12248
|
return typeof value === "object" && value !== null;
|
|
11885
12249
|
}
|
|
11886
12250
|
//#endregion
|
|
@@ -12371,18 +12735,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
12371
12735
|
defaultServiceId,
|
|
12372
12736
|
options.services
|
|
12373
12737
|
]);
|
|
12738
|
+
const bookingNowIso = useBookingNowIso();
|
|
12374
12739
|
const paymentSelection = useMemo(() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
12375
12740
|
serviceTitle: selectedService.title,
|
|
12376
12741
|
paymentTerms: selectedService.paymentTerms,
|
|
12377
12742
|
priceAmount: selectedAppointmentPriceAmount,
|
|
12378
12743
|
priceCurrency: selectedService.priceCurrency,
|
|
12379
|
-
bookingStartAt: state.selectedSlot?.startAt
|
|
12744
|
+
bookingStartAt: state.selectedSlot?.startAt,
|
|
12745
|
+
nowIso: bookingNowIso
|
|
12380
12746
|
}) : null, [
|
|
12747
|
+
bookingNowIso,
|
|
12381
12748
|
paymentResolution.mode,
|
|
12382
12749
|
selectedAppointmentPriceAmount,
|
|
12383
12750
|
selectedService,
|
|
12384
12751
|
state.selectedSlot?.startAt
|
|
12385
12752
|
]);
|
|
12753
|
+
const paymentConfirmationSummary = resolveBookingPaymentConfirmationSummary({
|
|
12754
|
+
service: selectedService,
|
|
12755
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
12756
|
+
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
12757
|
+
hasSelectedAppointmentPackage: Boolean(state.selectedAppointmentPackageId)
|
|
12758
|
+
});
|
|
12386
12759
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
12387
12760
|
const selectedAppointmentPackage = appointmentPackageItems.find((appointmentPackage) => appointmentPackage.customerPassId === state.selectedAppointmentPackageId) ?? null;
|
|
12388
12761
|
const spamProtectionEnabled = options.spamProtectionEnabled ?? isSpamProtectionEnabled();
|
|
@@ -12412,7 +12785,8 @@ function useHeadlessBookingFlow(options) {
|
|
|
12412
12785
|
selectedSlidingAmount,
|
|
12413
12786
|
slidingScale: selectedServiceSlidingScale,
|
|
12414
12787
|
appointmentPackages: appointmentPackagesModel,
|
|
12415
|
-
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
12788
|
+
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now.",
|
|
12789
|
+
confirmationSummary: null
|
|
12416
12790
|
} : {
|
|
12417
12791
|
kind: "ok",
|
|
12418
12792
|
mode: paymentResolution.mode,
|
|
@@ -12422,7 +12796,8 @@ function useHeadlessBookingFlow(options) {
|
|
|
12422
12796
|
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
12423
12797
|
selectedSlidingAmount,
|
|
12424
12798
|
slidingScale: selectedServiceSlidingScale,
|
|
12425
|
-
appointmentPackages: appointmentPackagesModel
|
|
12799
|
+
appointmentPackages: appointmentPackagesModel,
|
|
12800
|
+
confirmationSummary: paymentConfirmationSummary
|
|
12426
12801
|
};
|
|
12427
12802
|
return {
|
|
12428
12803
|
mailingList,
|
|
@@ -12562,14 +12937,14 @@ function pollingReducer(state, action) {
|
|
|
12562
12937
|
case "completed":
|
|
12563
12938
|
case "failed":
|
|
12564
12939
|
case "timeout": return state;
|
|
12565
|
-
default: return assertNever(state);
|
|
12940
|
+
default: return assertNever$1(state);
|
|
12566
12941
|
}
|
|
12567
12942
|
case "polling-timed-out": return {
|
|
12568
12943
|
tag: "timeout",
|
|
12569
12944
|
result: state.result,
|
|
12570
12945
|
error: /* @__PURE__ */ new Error("Polling timed out")
|
|
12571
12946
|
};
|
|
12572
|
-
default: return assertNever(action);
|
|
12947
|
+
default: return assertNever$1(action);
|
|
12573
12948
|
}
|
|
12574
12949
|
}
|
|
12575
12950
|
//#endregion
|
|
@@ -12580,67 +12955,24 @@ function pollingReducer(state, action) {
|
|
|
12580
12955
|
* Provides a reusable polling mechanism with configurable intervals,
|
|
12581
12956
|
* max attempts, and completion detection. Used by usePaymentVerification
|
|
12582
12957
|
* and other hooks that need to poll for status changes.
|
|
12583
|
-
*
|
|
12584
|
-
* @example
|
|
12585
|
-
* ```tsx
|
|
12586
|
-
* const polling = usePolling(shouldPoll ? {
|
|
12587
|
-
* pollFn: () => api.getStatus(id),
|
|
12588
|
-
* isComplete: (result) => result.status === 'done',
|
|
12589
|
-
* } : null);
|
|
12590
|
-
*
|
|
12591
|
-
* useEffect(() => {
|
|
12592
|
-
* if (polling.status === 'completed') {
|
|
12593
|
-
* handleSuccess(polling.result);
|
|
12594
|
-
* }
|
|
12595
|
-
* }, [polling.status]);
|
|
12596
|
-
* ```
|
|
12597
12958
|
*/
|
|
12598
12959
|
const DEFAULT_MAX_ATTEMPTS = 10;
|
|
12599
12960
|
const DEFAULT_POLL_INTERVAL = 1e3;
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
* ```tsx
|
|
12616
|
-
* // BAD - inline object creates new identity every render
|
|
12617
|
-
* usePolling({
|
|
12618
|
-
* pollFn: () => api.getStatus(id),
|
|
12619
|
-
* isComplete: (result) => result.status === 'done',
|
|
12620
|
-
* });
|
|
12621
|
-
*
|
|
12622
|
-
* // GOOD - memoized config, stable identity
|
|
12623
|
-
* const pollConfig = useMemo(() => shouldPoll ? {
|
|
12624
|
-
* pollFn: () => api.getStatus(id),
|
|
12625
|
-
* isComplete: (result) => result.status === 'done',
|
|
12626
|
-
* } : null, [shouldPoll, api, id]);
|
|
12627
|
-
*
|
|
12628
|
-
* usePolling(pollConfig);
|
|
12629
|
-
* ```
|
|
12630
|
-
*
|
|
12631
|
-
* @param config - Configuration for polling, or null to stop
|
|
12632
|
-
* @returns Polling result with status, data, and retry function
|
|
12633
|
-
*/
|
|
12634
|
-
function usePolling(config) {
|
|
12635
|
-
const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
|
|
12636
|
-
const attemptsRef = useRef(0);
|
|
12637
|
-
const timeoutRef = useRef(null);
|
|
12638
|
-
const isPollingRef = useRef(false);
|
|
12639
|
-
const isActiveRef = useRef(false);
|
|
12640
|
-
const generationRef = useRef(0);
|
|
12641
|
-
const configRef = useRef(config);
|
|
12642
|
-
configRef.current = config;
|
|
12643
|
-
const cleanup = useCallback(() => {
|
|
12961
|
+
function usePollingRuntime(config) {
|
|
12962
|
+
const runtime = {
|
|
12963
|
+
configRef: useRef(config),
|
|
12964
|
+
attemptsRef: useRef(0),
|
|
12965
|
+
timeoutRef: useRef(null),
|
|
12966
|
+
isPollingRef: useRef(false),
|
|
12967
|
+
isActiveRef: useRef(false),
|
|
12968
|
+
generationRef: useRef(0)
|
|
12969
|
+
};
|
|
12970
|
+
runtime.configRef.current = config;
|
|
12971
|
+
return runtime;
|
|
12972
|
+
}
|
|
12973
|
+
function usePollingCleanup(runtime) {
|
|
12974
|
+
const { isActiveRef, generationRef, timeoutRef, isPollingRef } = runtime;
|
|
12975
|
+
return useCallback(() => {
|
|
12644
12976
|
isActiveRef.current = false;
|
|
12645
12977
|
generationRef.current += 1;
|
|
12646
12978
|
if (timeoutRef.current) {
|
|
@@ -12648,16 +12980,27 @@ function usePolling(config) {
|
|
|
12648
12980
|
timeoutRef.current = null;
|
|
12649
12981
|
}
|
|
12650
12982
|
isPollingRef.current = false;
|
|
12651
|
-
}, [
|
|
12652
|
-
|
|
12983
|
+
}, [
|
|
12984
|
+
generationRef,
|
|
12985
|
+
isActiveRef,
|
|
12986
|
+
isPollingRef,
|
|
12987
|
+
timeoutRef
|
|
12988
|
+
]);
|
|
12989
|
+
}
|
|
12990
|
+
function usePollingReset(runtime, dispatch) {
|
|
12991
|
+
const { attemptsRef } = runtime;
|
|
12992
|
+
return useCallback(() => {
|
|
12653
12993
|
dispatch({ type: "polling-reset" });
|
|
12654
12994
|
attemptsRef.current = 0;
|
|
12655
|
-
}, []);
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12995
|
+
}, [attemptsRef, dispatch]);
|
|
12996
|
+
}
|
|
12997
|
+
function usePollingRequest(runtime, dispatch, cleanup) {
|
|
12998
|
+
const { configRef, attemptsRef, isPollingRef, isActiveRef, generationRef } = runtime;
|
|
12999
|
+
return useCallback(async () => {
|
|
13000
|
+
const config = configRef.current;
|
|
13001
|
+
if (!config) return true;
|
|
12659
13002
|
if (isPollingRef.current) return false;
|
|
12660
|
-
const maxAttempts =
|
|
13003
|
+
const maxAttempts = config.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
12661
13004
|
if (attemptsRef.current >= maxAttempts) {
|
|
12662
13005
|
dispatch({ type: "polling-timed-out" });
|
|
12663
13006
|
cleanup();
|
|
@@ -12667,81 +13010,115 @@ function usePolling(config) {
|
|
|
12667
13010
|
attemptsRef.current += 1;
|
|
12668
13011
|
const generation = generationRef.current;
|
|
12669
13012
|
try {
|
|
12670
|
-
const
|
|
12671
|
-
if (generation !== generationRef.current || !isActiveRef.current)
|
|
12672
|
-
|
|
12673
|
-
return true;
|
|
12674
|
-
}
|
|
12675
|
-
if (cfg.isFailed?.(data)) {
|
|
13013
|
+
const result = await config.pollFn();
|
|
13014
|
+
if (generation !== generationRef.current || !isActiveRef.current) return true;
|
|
13015
|
+
if (config.isFailed?.(result)) {
|
|
12676
13016
|
dispatch({
|
|
12677
13017
|
type: "polling-failed",
|
|
12678
|
-
result
|
|
13018
|
+
result
|
|
12679
13019
|
});
|
|
12680
13020
|
cleanup();
|
|
12681
13021
|
return true;
|
|
12682
13022
|
}
|
|
12683
|
-
if (
|
|
13023
|
+
if (config.isComplete(result)) {
|
|
12684
13024
|
dispatch({
|
|
12685
13025
|
type: "polling-completed",
|
|
12686
|
-
result
|
|
13026
|
+
result
|
|
12687
13027
|
});
|
|
12688
13028
|
cleanup();
|
|
12689
13029
|
return true;
|
|
12690
13030
|
}
|
|
12691
13031
|
dispatch({
|
|
12692
13032
|
type: "polling-progressed",
|
|
12693
|
-
result
|
|
13033
|
+
result
|
|
12694
13034
|
});
|
|
12695
13035
|
isPollingRef.current = false;
|
|
12696
13036
|
return false;
|
|
12697
|
-
} catch (
|
|
12698
|
-
if (generation !== generationRef.current || !isActiveRef.current)
|
|
12699
|
-
|
|
12700
|
-
return true;
|
|
12701
|
-
}
|
|
12702
|
-
if (err instanceof Error) dispatch({
|
|
13037
|
+
} catch (error) {
|
|
13038
|
+
if (generation !== generationRef.current || !isActiveRef.current) return true;
|
|
13039
|
+
if (error instanceof Error) dispatch({
|
|
12703
13040
|
type: "polling-request-failed",
|
|
12704
|
-
error
|
|
13041
|
+
error
|
|
12705
13042
|
});
|
|
12706
13043
|
isPollingRef.current = false;
|
|
12707
13044
|
return false;
|
|
12708
13045
|
}
|
|
12709
|
-
}, [
|
|
12710
|
-
|
|
13046
|
+
}, [
|
|
13047
|
+
attemptsRef,
|
|
13048
|
+
cleanup,
|
|
13049
|
+
configRef,
|
|
13050
|
+
dispatch,
|
|
13051
|
+
generationRef,
|
|
13052
|
+
isActiveRef,
|
|
13053
|
+
isPollingRef
|
|
13054
|
+
]);
|
|
13055
|
+
}
|
|
13056
|
+
function usePollingScheduler(runtime, poll) {
|
|
13057
|
+
const { attemptsRef, configRef, isActiveRef, timeoutRef } = runtime;
|
|
13058
|
+
return useCallback(() => {
|
|
12711
13059
|
if (!isActiveRef.current) return;
|
|
12712
|
-
const pollInterval = configRef.current?.interval ?? DEFAULT_POLL_INTERVAL;
|
|
12713
13060
|
const doPoll = async () => {
|
|
12714
|
-
if (!await poll() && isActiveRef.current)
|
|
13061
|
+
if (!await poll() && isActiveRef.current) {
|
|
13062
|
+
const configuredInterval = configRef.current?.interval;
|
|
13063
|
+
const interval = typeof configuredInterval === "function" ? configuredInterval(attemptsRef.current) : configuredInterval ?? DEFAULT_POLL_INTERVAL;
|
|
13064
|
+
timeoutRef.current = setTimeout(doPoll, interval);
|
|
13065
|
+
}
|
|
12715
13066
|
};
|
|
12716
13067
|
doPoll();
|
|
12717
|
-
}, [
|
|
13068
|
+
}, [
|
|
13069
|
+
attemptsRef,
|
|
13070
|
+
configRef,
|
|
13071
|
+
isActiveRef,
|
|
13072
|
+
poll,
|
|
13073
|
+
timeoutRef
|
|
13074
|
+
]);
|
|
13075
|
+
}
|
|
13076
|
+
function usePollingCycle(config, runtime, dispatch) {
|
|
13077
|
+
const cleanup = usePollingCleanup(runtime);
|
|
13078
|
+
const resetState = usePollingReset(runtime, dispatch);
|
|
13079
|
+
const schedulePoll = usePollingScheduler(runtime, usePollingRequest(runtime, dispatch, cleanup));
|
|
13080
|
+
const pollingEnabled = config !== null;
|
|
12718
13081
|
useEffect(() => {
|
|
12719
|
-
if (!
|
|
13082
|
+
if (!pollingEnabled) {
|
|
12720
13083
|
cleanup();
|
|
12721
13084
|
dispatch({ type: "polling-went-idle" });
|
|
12722
13085
|
return;
|
|
12723
13086
|
}
|
|
12724
13087
|
resetState();
|
|
12725
|
-
isActiveRef.current = true;
|
|
13088
|
+
runtime.isActiveRef.current = true;
|
|
12726
13089
|
schedulePoll();
|
|
12727
13090
|
return cleanup;
|
|
12728
13091
|
}, [
|
|
12729
|
-
config,
|
|
12730
13092
|
cleanup,
|
|
13093
|
+
dispatch,
|
|
13094
|
+
pollingEnabled,
|
|
12731
13095
|
resetState,
|
|
13096
|
+
config?.restartKey ?? null,
|
|
13097
|
+
runtime.isActiveRef,
|
|
12732
13098
|
schedulePoll
|
|
12733
13099
|
]);
|
|
12734
|
-
|
|
12735
|
-
if (!configRef.current) return;
|
|
13100
|
+
return useCallback(() => {
|
|
13101
|
+
if (!runtime.configRef.current) return;
|
|
12736
13102
|
cleanup();
|
|
12737
13103
|
resetState();
|
|
12738
|
-
isActiveRef.current = true;
|
|
13104
|
+
runtime.isActiveRef.current = true;
|
|
12739
13105
|
schedulePoll();
|
|
12740
13106
|
}, [
|
|
12741
13107
|
cleanup,
|
|
12742
13108
|
resetState,
|
|
13109
|
+
runtime.configRef,
|
|
13110
|
+
runtime.isActiveRef,
|
|
12743
13111
|
schedulePoll
|
|
12744
13112
|
]);
|
|
13113
|
+
}
|
|
13114
|
+
/**
|
|
13115
|
+
* Polls until the operation completes, fails, times out, or becomes disabled.
|
|
13116
|
+
* Config objects may be rebuilt across renders; change restartKey to begin a
|
|
13117
|
+
* new operation and reset its attempt budget.
|
|
13118
|
+
*/
|
|
13119
|
+
function usePolling(config) {
|
|
13120
|
+
const [state, dispatch] = useReducer(pollingReducer, void 0, createInitialPollingState);
|
|
13121
|
+
const retry = usePollingCycle(config, usePollingRuntime(config), dispatch);
|
|
12745
13122
|
return {
|
|
12746
13123
|
status: config ? state.tag : "idle",
|
|
12747
13124
|
result: config ? state.result : null,
|
|
@@ -12751,6 +13128,10 @@ function usePolling(config) {
|
|
|
12751
13128
|
}
|
|
12752
13129
|
//#endregion
|
|
12753
13130
|
//#region ../blocks/src/system/runtime/hooks/useAppointmentCheckoutVerification.ts
|
|
13131
|
+
const APPOINTMENT_CHECKOUT_MAX_ATTEMPTS = 12;
|
|
13132
|
+
function resolveAppointmentCheckoutPollInterval(attempt) {
|
|
13133
|
+
return Math.min(1e3 * 2 ** (attempt - 1), 4e3);
|
|
13134
|
+
}
|
|
12754
13135
|
const appointmentCheckoutVerificationDeps = {
|
|
12755
13136
|
useBlockApi,
|
|
12756
13137
|
usePolling
|
|
@@ -12760,16 +13141,25 @@ function useAppointmentCheckoutVerification(config) {
|
|
|
12760
13141
|
}
|
|
12761
13142
|
function useAppointmentCheckoutVerificationWithDeps(config, deps) {
|
|
12762
13143
|
const api = deps.useBlockApi();
|
|
13144
|
+
const sessionId = config?.sessionId ?? null;
|
|
13145
|
+
const maxAttempts = config?.maxAttempts;
|
|
13146
|
+
const pollInterval = config?.pollInterval;
|
|
12763
13147
|
const pollingConfig = useMemo(() => {
|
|
12764
|
-
if (
|
|
13148
|
+
if (sessionId === null) return null;
|
|
12765
13149
|
return {
|
|
12766
|
-
|
|
13150
|
+
restartKey: sessionId,
|
|
13151
|
+
pollFn: () => api.getAppointmentBookingStatus({ sessionId }),
|
|
12767
13152
|
isComplete: (result) => (result.paymentStatus === "completed" || result.paymentStatus === "not_required") && result.appointmentStatus === "confirmed",
|
|
12768
13153
|
isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "cancelled" || result.paymentStatus === "refunded" || result.appointmentStatus === "cancelled",
|
|
12769
|
-
maxAttempts:
|
|
12770
|
-
interval:
|
|
13154
|
+
maxAttempts: maxAttempts ?? APPOINTMENT_CHECKOUT_MAX_ATTEMPTS,
|
|
13155
|
+
interval: pollInterval ?? resolveAppointmentCheckoutPollInterval
|
|
12771
13156
|
};
|
|
12772
|
-
}, [
|
|
13157
|
+
}, [
|
|
13158
|
+
api,
|
|
13159
|
+
sessionId,
|
|
13160
|
+
maxAttempts,
|
|
13161
|
+
pollInterval
|
|
13162
|
+
]);
|
|
12773
13163
|
const polling = deps.usePolling(pollingConfig);
|
|
12774
13164
|
return {
|
|
12775
13165
|
state: resolveAppointmentCheckoutVerificationState({
|
|
@@ -13381,11 +13771,18 @@ function isReservedPathSegment(value) {
|
|
|
13381
13771
|
function isUnsafePathSegment(segment) {
|
|
13382
13772
|
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
13383
13773
|
}
|
|
13384
|
-
|
|
13774
|
+
//#endregion
|
|
13775
|
+
//#region ../media-core/src/fileStorage.ts
|
|
13776
|
+
const FILE_STORAGE_BUCKETS = {
|
|
13385
13777
|
publicSite: unsafeAsStorageBucketName("media"),
|
|
13386
13778
|
privateSite: unsafeAsStorageBucketName("site-files-private"),
|
|
13387
|
-
temporary: unsafeAsStorageBucketName("temp-uploads")
|
|
13388
|
-
|
|
13779
|
+
temporary: unsafeAsStorageBucketName("temp-uploads"),
|
|
13780
|
+
siteAssets: unsafeAsStorageBucketName("site-assets"),
|
|
13781
|
+
siteFonts: unsafeAsStorageBucketName("site-fonts"),
|
|
13782
|
+
bookingRequirementDocuments: unsafeAsStorageBucketName("booking-requirement-documents")
|
|
13783
|
+
};
|
|
13784
|
+
FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts;
|
|
13785
|
+
FILE_STORAGE_BUCKETS.publicSite, FILE_STORAGE_BUCKETS.privateSite, FILE_STORAGE_BUCKETS.temporary, FILE_STORAGE_BUCKETS.siteAssets, FILE_STORAGE_BUCKETS.siteFonts, FILE_STORAGE_BUCKETS.bookingRequirementDocuments;
|
|
13389
13786
|
function parseStoragePath(value) {
|
|
13390
13787
|
return joinStoragePathSegments(value.split("/"));
|
|
13391
13788
|
}
|
|
@@ -14175,7 +14572,7 @@ function DefaultServiceChoices({ booking }) {
|
|
|
14175
14572
|
})]
|
|
14176
14573
|
}, group.key))
|
|
14177
14574
|
});
|
|
14178
|
-
default: return assertNever(layout);
|
|
14575
|
+
default: return assertNever$1(layout);
|
|
14179
14576
|
}
|
|
14180
14577
|
}
|
|
14181
14578
|
function ServiceChoiceGrid({ booking, choices }) {
|
|
@@ -14211,6 +14608,72 @@ function ServiceChoiceGrid({ booking, choices }) {
|
|
|
14211
14608
|
});
|
|
14212
14609
|
}
|
|
14213
14610
|
//#endregion
|
|
14611
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.submit-actions.tsx
|
|
14612
|
+
function resolvePrimaryActionLabel(isLastStep, requiresPayment) {
|
|
14613
|
+
if (!isLastStep) return "Continue";
|
|
14614
|
+
return requiresPayment ? "Continue to payment" : "Complete";
|
|
14615
|
+
}
|
|
14616
|
+
function formatBookingConfirmationDateTime(booking) {
|
|
14617
|
+
const startAt = booking.currentStep?.id === "datetime-selection" ? booking.availability.selectedSlot?.startAt : void 0;
|
|
14618
|
+
return startAt ? new Intl.DateTimeFormat(void 0, {
|
|
14619
|
+
dateStyle: "medium",
|
|
14620
|
+
timeStyle: "short",
|
|
14621
|
+
timeZone: booking.availability.timezone
|
|
14622
|
+
}).format(new Date(startAt)) : null;
|
|
14623
|
+
}
|
|
14624
|
+
function BookingPaymentConfirmationText({ booking, summary }) {
|
|
14625
|
+
if (!summary) return null;
|
|
14626
|
+
const dateTime = formatBookingConfirmationDateTime(booking);
|
|
14627
|
+
return /* @__PURE__ */ jsxs("p", {
|
|
14628
|
+
className: "ab-text rb-on-surface--muted",
|
|
14629
|
+
children: [
|
|
14630
|
+
summary.serviceTitle,
|
|
14631
|
+
" · ",
|
|
14632
|
+
summary.durationMinutes,
|
|
14633
|
+
" min ·",
|
|
14634
|
+
" ",
|
|
14635
|
+
formatCurrencyAmount(summary.priceAmount, summary.priceCurrency, { decimals: "auto" }),
|
|
14636
|
+
dateTime ? ` · ${dateTime}` : ""
|
|
14637
|
+
]
|
|
14638
|
+
});
|
|
14639
|
+
}
|
|
14640
|
+
function BookingFormSubmitActions({ booking, onSubmit }) {
|
|
14641
|
+
const currentStepIndex = booking.currentStep?.visibleIndex ?? 0;
|
|
14642
|
+
const isFirstStep = currentStepIndex === 0;
|
|
14643
|
+
const isLastStep = currentStepIndex === booking.steps.length - 1;
|
|
14644
|
+
const isSubmitting = booking.status.tag === "submitting";
|
|
14645
|
+
const paymentSummary = isLastStep && booking.payment.kind === "ok" ? booking.payment.confirmationSummary : null;
|
|
14646
|
+
const handlePrimaryAction = async () => {
|
|
14647
|
+
if ((await booking.actions.next()).ok && isLastStep) await onSubmit();
|
|
14648
|
+
};
|
|
14649
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BookingPaymentConfirmationText, {
|
|
14650
|
+
booking,
|
|
14651
|
+
summary: paymentSummary
|
|
14652
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
14653
|
+
className: "rb-wizard-actions",
|
|
14654
|
+
children: [!isFirstStep ? /* @__PURE__ */ jsx(ThemedButton, {
|
|
14655
|
+
type: "button",
|
|
14656
|
+
onClick: booking.actions.back,
|
|
14657
|
+
variant: "outline",
|
|
14658
|
+
size: "md",
|
|
14659
|
+
label: "Back"
|
|
14660
|
+
}) : null, /* @__PURE__ */ jsx(ThemedButton, {
|
|
14661
|
+
type: "button",
|
|
14662
|
+
onClick: () => {
|
|
14663
|
+
handlePrimaryAction();
|
|
14664
|
+
},
|
|
14665
|
+
disabled: isSubmitting,
|
|
14666
|
+
variant: "primary",
|
|
14667
|
+
size: "md",
|
|
14668
|
+
label: resolvePrimaryActionLabel(isLastStep, Boolean(paymentSummary)),
|
|
14669
|
+
pending: isSubmitting ? {
|
|
14670
|
+
label: "Submitting...",
|
|
14671
|
+
srLabel: "Submitting"
|
|
14672
|
+
} : void 0
|
|
14673
|
+
})]
|
|
14674
|
+
})] });
|
|
14675
|
+
}
|
|
14676
|
+
//#endregion
|
|
14214
14677
|
//#region ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
14215
14678
|
function formatBookingAmount(amount, currency) {
|
|
14216
14679
|
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
@@ -14219,13 +14682,6 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
|
|
|
14219
14682
|
const currentStep = booking.currentStep;
|
|
14220
14683
|
const errorSummaryId = React.useId();
|
|
14221
14684
|
const currentStepIndex = currentStep?.visibleIndex ?? 0;
|
|
14222
|
-
const isFirstStep = currentStepIndex === 0;
|
|
14223
|
-
const isLastStep = currentStepIndex === booking.steps.length - 1;
|
|
14224
|
-
const isSubmitting = booking.status.tag === "submitting";
|
|
14225
|
-
const handlePrimaryAction = async () => {
|
|
14226
|
-
if (!(await booking.actions.next()).ok) return;
|
|
14227
|
-
if (isLastStep) await onSubmit();
|
|
14228
|
-
};
|
|
14229
14685
|
if (!currentStep) return /* @__PURE__ */ jsx("div", {
|
|
14230
14686
|
className: "rb-text-center rb-py-12",
|
|
14231
14687
|
children: /* @__PURE__ */ jsx("p", {
|
|
@@ -14253,28 +14709,9 @@ function HeadlessBookingDefaultForm({ booking, onSubmit }) {
|
|
|
14253
14709
|
errors: currentStep.errors,
|
|
14254
14710
|
id: errorSummaryId
|
|
14255
14711
|
}),
|
|
14256
|
-
/* @__PURE__ */
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
type: "button",
|
|
14260
|
-
onClick: booking.actions.back,
|
|
14261
|
-
variant: "outline",
|
|
14262
|
-
size: "md",
|
|
14263
|
-
label: "Back"
|
|
14264
|
-
}) : null, /* @__PURE__ */ jsx(ThemedButton, {
|
|
14265
|
-
type: "button",
|
|
14266
|
-
onClick: () => {
|
|
14267
|
-
handlePrimaryAction();
|
|
14268
|
-
},
|
|
14269
|
-
disabled: isSubmitting,
|
|
14270
|
-
variant: "primary",
|
|
14271
|
-
size: "md",
|
|
14272
|
-
label: isLastStep ? "Complete" : "Continue",
|
|
14273
|
-
pending: isSubmitting ? {
|
|
14274
|
-
label: "Submitting...",
|
|
14275
|
-
srLabel: "Submitting"
|
|
14276
|
-
} : void 0
|
|
14277
|
-
})]
|
|
14712
|
+
/* @__PURE__ */ jsx(BookingFormSubmitActions, {
|
|
14713
|
+
booking,
|
|
14714
|
+
onSubmit
|
|
14278
14715
|
}),
|
|
14279
14716
|
/* @__PURE__ */ jsx(DefaultBookingDiscount, { booking }),
|
|
14280
14717
|
/* @__PURE__ */ jsx(DefaultBookingFeedback, { booking }),
|
|
@@ -14296,7 +14733,7 @@ function DefaultBookingStepContent({ booking, errorSummaryId }) {
|
|
|
14296
14733
|
fields: booking.fields.items,
|
|
14297
14734
|
booking
|
|
14298
14735
|
});
|
|
14299
|
-
default: return assertNever(stepId);
|
|
14736
|
+
default: return assertNever$1(stepId);
|
|
14300
14737
|
}
|
|
14301
14738
|
}
|
|
14302
14739
|
function DefaultServiceSelectionStep({ booking }) {
|
|
@@ -14985,27 +15422,167 @@ function TerminalPanel({ tone, title, titleAs: Title = "h3", body, secondaryBody
|
|
|
14985
15422
|
"data-terminal-title": true,
|
|
14986
15423
|
children: title
|
|
14987
15424
|
}),
|
|
14988
|
-
body ? /* @__PURE__ */ jsx("div", {
|
|
14989
|
-
className: joinClasses(bodyClassName),
|
|
14990
|
-
"data-terminal-body": true,
|
|
14991
|
-
children: body
|
|
14992
|
-
}) : null,
|
|
14993
|
-
actions ? /* @__PURE__ */ jsx("div", {
|
|
14994
|
-
className: joinClasses(actionsClassName),
|
|
14995
|
-
"data-terminal-actions": true,
|
|
14996
|
-
children: actions
|
|
15425
|
+
body ? /* @__PURE__ */ jsx("div", {
|
|
15426
|
+
className: joinClasses(bodyClassName),
|
|
15427
|
+
"data-terminal-body": true,
|
|
15428
|
+
children: body
|
|
15429
|
+
}) : null,
|
|
15430
|
+
actions ? /* @__PURE__ */ jsx("div", {
|
|
15431
|
+
className: joinClasses(actionsClassName),
|
|
15432
|
+
"data-terminal-actions": true,
|
|
15433
|
+
children: actions
|
|
15434
|
+
}) : null,
|
|
15435
|
+
secondaryBody ? /* @__PURE__ */ jsx("div", {
|
|
15436
|
+
className: joinClasses(secondaryBodyClassName),
|
|
15437
|
+
"data-terminal-secondary-body": true,
|
|
15438
|
+
children: secondaryBody
|
|
15439
|
+
}) : null
|
|
15440
|
+
]
|
|
15441
|
+
});
|
|
15442
|
+
}
|
|
15443
|
+
//#endregion
|
|
15444
|
+
//#region ../blocks/src/system/runtime/shared/utils/demoPortalMagicLink.ts
|
|
15445
|
+
const CUSTOMER_PORTAL_PATH = "/portal";
|
|
15446
|
+
function buildPortalCallbackUrl(origin, redirectTo) {
|
|
15447
|
+
const url = new URL("/api/portal/callback", origin);
|
|
15448
|
+
url.searchParams.set("redirect_to", redirectTo);
|
|
15449
|
+
return url.toString();
|
|
15450
|
+
}
|
|
15451
|
+
async function requestDemoPortalMagicLink(input) {
|
|
15452
|
+
const email = normalizeDemoBookingEmail(input.email);
|
|
15453
|
+
const pass = getDemoBookingPass(email);
|
|
15454
|
+
const request = {
|
|
15455
|
+
email,
|
|
15456
|
+
redirectUrl: input.redirectUrl,
|
|
15457
|
+
...pass ? { demoBookingPass: pass } : {}
|
|
15458
|
+
};
|
|
15459
|
+
try {
|
|
15460
|
+
const response = await input.send(request);
|
|
15461
|
+
if ("kind" in response) return {
|
|
15462
|
+
kind: "refused",
|
|
15463
|
+
message: response.message
|
|
15464
|
+
};
|
|
15465
|
+
return "demoSignInUrl" in response ? {
|
|
15466
|
+
kind: "demo_sign_in",
|
|
15467
|
+
url: response.demoSignInUrl
|
|
15468
|
+
} : { kind: "email_sent" };
|
|
15469
|
+
} catch (error) {
|
|
15470
|
+
if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
|
|
15471
|
+
kind: "refused",
|
|
15472
|
+
message: error.message
|
|
15473
|
+
};
|
|
15474
|
+
throw error;
|
|
15475
|
+
}
|
|
15476
|
+
}
|
|
15477
|
+
//#endregion
|
|
15478
|
+
//#region ../blocks/src/system/runtime/shared/components/DemoBookingPortalAccess.tsx
|
|
15479
|
+
const SUPPRESSED_CONFIRMATION_NOTE = "This is a demo, so we haven’t sent a confirmation email. You can still see your booking in the customer portal.";
|
|
15480
|
+
function BookingConfirmation(props) {
|
|
15481
|
+
const content = renderConfirmationMessage((props.demoEmailSuppressed ? [props.copy.message] : [props.copy.message, props.copy.defaultEmailSentence ?? ""]).filter((part) => part.trim().length > 0).join(" "), props.messagePresentation);
|
|
15482
|
+
if (!props.demoEmailSuppressed) return content;
|
|
15483
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [content, /* @__PURE__ */ jsx(DemoBookingPortalAccess, {
|
|
15484
|
+
email: props.email,
|
|
15485
|
+
noteClassName: props.noteClassName,
|
|
15486
|
+
showConfirmationNote: props.showConfirmationNote
|
|
15487
|
+
})] });
|
|
15488
|
+
}
|
|
15489
|
+
function DemoBookingPortalAccess(props) {
|
|
15490
|
+
const { state, openPortal } = useDemoBookingPortalAccess(props.email);
|
|
15491
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
15492
|
+
className: "rb-mt-4 rb-flex rb-flex-col rb-items-start rb-gap-3",
|
|
15493
|
+
"data-testid": "demo-booking-portal-access",
|
|
15494
|
+
children: [
|
|
15495
|
+
props.showConfirmationNote === false ? null : /* @__PURE__ */ jsx("p", {
|
|
15496
|
+
className: props.noteClassName ?? "ab-text",
|
|
15497
|
+
children: SUPPRESSED_CONFIRMATION_NOTE
|
|
15498
|
+
}),
|
|
15499
|
+
/* @__PURE__ */ jsx(ThemedButton, {
|
|
15500
|
+
type: "button",
|
|
15501
|
+
variant: "default",
|
|
15502
|
+
size: "md",
|
|
15503
|
+
label: state.tag === "opening" ? "Opening…" : "Open the customer portal",
|
|
15504
|
+
disabled: state.tag === "opening",
|
|
15505
|
+
onClick: openPortal
|
|
15506
|
+
}),
|
|
15507
|
+
state.tag === "refused" ? /* @__PURE__ */ jsx("p", {
|
|
15508
|
+
role: "alert",
|
|
15509
|
+
children: state.message
|
|
14997
15510
|
}) : null,
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
children: secondaryBody
|
|
15511
|
+
state.tag === "error" ? /* @__PURE__ */ jsx("p", {
|
|
15512
|
+
role: "alert",
|
|
15513
|
+
children: state.message
|
|
15002
15514
|
}) : null
|
|
15003
15515
|
]
|
|
15004
15516
|
});
|
|
15005
15517
|
}
|
|
15518
|
+
function renderConfirmationMessage(message, presentation) {
|
|
15519
|
+
if (!message) return null;
|
|
15520
|
+
switch (presentation.kind) {
|
|
15521
|
+
case "paragraph": return /* @__PURE__ */ jsx("p", {
|
|
15522
|
+
className: presentation.className,
|
|
15523
|
+
children: message
|
|
15524
|
+
});
|
|
15525
|
+
case "plain": return message;
|
|
15526
|
+
}
|
|
15527
|
+
}
|
|
15528
|
+
function useDemoBookingPortalAccess(email) {
|
|
15529
|
+
const api = useBlockApi();
|
|
15530
|
+
const [state, setState] = React.useState({ tag: "idle" });
|
|
15531
|
+
const openPortal = async () => {
|
|
15532
|
+
if (state.tag === "opening") return;
|
|
15533
|
+
if (!email) {
|
|
15534
|
+
setState({
|
|
15535
|
+
tag: "error",
|
|
15536
|
+
message: "We couldn’t open the customer portal. Please try again."
|
|
15537
|
+
});
|
|
15538
|
+
return;
|
|
15539
|
+
}
|
|
15540
|
+
setState({ tag: "opening" });
|
|
15541
|
+
try {
|
|
15542
|
+
const result = await requestDemoPortalMagicLink({
|
|
15543
|
+
email,
|
|
15544
|
+
redirectUrl: buildPortalCallbackUrl(window.location.origin, CUSTOMER_PORTAL_PATH),
|
|
15545
|
+
send: (request) => api.sendMagicLink(request)
|
|
15546
|
+
});
|
|
15547
|
+
switch (result.kind) {
|
|
15548
|
+
case "demo_sign_in":
|
|
15549
|
+
window.location.assign(result.url);
|
|
15550
|
+
return;
|
|
15551
|
+
case "refused":
|
|
15552
|
+
setState({
|
|
15553
|
+
tag: "refused",
|
|
15554
|
+
message: result.message
|
|
15555
|
+
});
|
|
15556
|
+
return;
|
|
15557
|
+
case "email_sent":
|
|
15558
|
+
setState({ tag: "idle" });
|
|
15559
|
+
return;
|
|
15560
|
+
}
|
|
15561
|
+
} catch (error) {
|
|
15562
|
+
setState(handlePortalAccessError(error));
|
|
15563
|
+
}
|
|
15564
|
+
};
|
|
15565
|
+
return {
|
|
15566
|
+
state,
|
|
15567
|
+
openPortal
|
|
15568
|
+
};
|
|
15569
|
+
}
|
|
15570
|
+
function handlePortalAccessError(error) {
|
|
15571
|
+
if (error instanceof BlockApiError && error.tag === "demo_email_not_booked_here") return {
|
|
15572
|
+
tag: "refused",
|
|
15573
|
+
message: error.message
|
|
15574
|
+
};
|
|
15575
|
+
return error instanceof BlockApiError ? {
|
|
15576
|
+
tag: "error",
|
|
15577
|
+
message: error.message
|
|
15578
|
+
} : {
|
|
15579
|
+
tag: "error",
|
|
15580
|
+
message: "We couldn’t open the customer portal. Please try again."
|
|
15581
|
+
};
|
|
15582
|
+
}
|
|
15006
15583
|
//#endregion
|
|
15007
15584
|
//#region ../blocks/src/system/runtime/components/booking/SuccessMessage.tsx
|
|
15008
|
-
const SuccessMessage = ({
|
|
15585
|
+
const SuccessMessage = ({ copy, resourceName, className, demoEmailSuppressed = false, customerEmail = null }) => {
|
|
15009
15586
|
return /* @__PURE__ */ jsx(TerminalPanel, {
|
|
15010
15587
|
tone: "success",
|
|
15011
15588
|
title: "Booking confirmed",
|
|
@@ -15013,9 +15590,15 @@ const SuccessMessage = ({ message, resourceName, className }) => {
|
|
|
15013
15590
|
variant: "success",
|
|
15014
15591
|
children: /* @__PURE__ */ jsx(CheckIcon, { strokeWidth: 3 })
|
|
15015
15592
|
}),
|
|
15016
|
-
body: /* @__PURE__ */ jsx(
|
|
15017
|
-
|
|
15018
|
-
|
|
15593
|
+
body: /* @__PURE__ */ jsx(BookingConfirmation, {
|
|
15594
|
+
demoEmailSuppressed,
|
|
15595
|
+
email: customerEmail,
|
|
15596
|
+
copy,
|
|
15597
|
+
messagePresentation: {
|
|
15598
|
+
kind: "paragraph",
|
|
15599
|
+
className: "ab-text"
|
|
15600
|
+
},
|
|
15601
|
+
noteClassName: "ab-text"
|
|
15019
15602
|
}),
|
|
15020
15603
|
secondaryBody: resourceName ? /* @__PURE__ */ jsxs("p", {
|
|
15021
15604
|
className: "ab-text rb-on-surface--muted",
|
|
@@ -15051,31 +15634,54 @@ function BookingMailingListNote(props) {
|
|
|
15051
15634
|
});
|
|
15052
15635
|
}
|
|
15053
15636
|
//#endregion
|
|
15054
|
-
//#region ../blocks/src/system/runtime/nodes/booking-form.
|
|
15637
|
+
//#region ../blocks/src/system/runtime/nodes/booking-form.checkout-return-context.ts
|
|
15055
15638
|
function storageKey(sessionId) {
|
|
15056
15639
|
return `riverbank:booking:mailing-list:${sessionId}`;
|
|
15057
15640
|
}
|
|
15058
|
-
function
|
|
15059
|
-
if (!
|
|
15641
|
+
function saveAppointmentCheckoutReturnContext(sessionId, context) {
|
|
15642
|
+
if (!context.customerEmail && !context.mailingListNote) return;
|
|
15060
15643
|
try {
|
|
15061
|
-
window.sessionStorage.setItem(storageKey(sessionId),
|
|
15644
|
+
window.sessionStorage.setItem(storageKey(sessionId), JSON.stringify(context));
|
|
15062
15645
|
} catch {}
|
|
15063
15646
|
}
|
|
15064
|
-
function
|
|
15647
|
+
function readAppointmentCheckoutReturnContext(sessionId) {
|
|
15065
15648
|
try {
|
|
15066
15649
|
const stored = window.sessionStorage.getItem(storageKey(sessionId));
|
|
15067
|
-
|
|
15650
|
+
if (!stored) return null;
|
|
15651
|
+
return parseContext(stored);
|
|
15068
15652
|
} catch {
|
|
15069
15653
|
return null;
|
|
15070
15654
|
}
|
|
15071
15655
|
}
|
|
15656
|
+
function parseContext(value) {
|
|
15657
|
+
try {
|
|
15658
|
+
const parsed = JSON.parse(value);
|
|
15659
|
+
return isContext(parsed) ? parsed : null;
|
|
15660
|
+
} catch {
|
|
15661
|
+
return value === "confirmation_required" || value === "not_confirmed" ? {
|
|
15662
|
+
customerEmail: null,
|
|
15663
|
+
mailingListNote: value
|
|
15664
|
+
} : null;
|
|
15665
|
+
}
|
|
15666
|
+
}
|
|
15667
|
+
function isContext(value) {
|
|
15668
|
+
if (!isRecord$2(value)) return false;
|
|
15669
|
+
return (typeof value.customerEmail === "string" || value.customerEmail === null) && (value.mailingListNote === null || value.mailingListNote === "confirmation_required" || value.mailingListNote === "not_confirmed");
|
|
15670
|
+
}
|
|
15671
|
+
function isRecord$2(value) {
|
|
15672
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15673
|
+
}
|
|
15072
15674
|
//#endregion
|
|
15073
15675
|
//#region ../blocks/src/system/runtime/nodes/booking-form.completion.tsx
|
|
15074
|
-
function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote }) {
|
|
15075
|
-
const
|
|
15676
|
+
function BookingFormCompletion({ resourceName, successMessage, redirectState, localNote, customerEmail, demoEmailSuppressed = false }) {
|
|
15677
|
+
const returnContext = redirectState.kind === "success" ? readAppointmentCheckoutReturnContext(redirectState.sessionId) : null;
|
|
15678
|
+
const note = redirectState.kind === "success" ? returnContext?.mailingListNote ?? null : localNote;
|
|
15679
|
+
const confirmedEmail = returnContext?.customerEmail ?? customerEmail;
|
|
15076
15680
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SuccessMessage, {
|
|
15077
|
-
|
|
15078
|
-
resourceName
|
|
15681
|
+
copy: getBookingSuccessCopy(successMessage),
|
|
15682
|
+
resourceName,
|
|
15683
|
+
demoEmailSuppressed,
|
|
15684
|
+
customerEmail: confirmedEmail
|
|
15079
15685
|
}), note ? /* @__PURE__ */ jsx(BookingMailingListNote, {
|
|
15080
15686
|
note,
|
|
15081
15687
|
context: "booking",
|
|
@@ -15099,12 +15705,17 @@ function createBookingFormSubmitHandler(input) {
|
|
|
15099
15705
|
cancelUrl: appendRebookFlag(cancelUrl, input.isPortalRebook)
|
|
15100
15706
|
});
|
|
15101
15707
|
if (!result.ok) return;
|
|
15708
|
+
storeDemoBookingPassIfAvailable(result.outcome.customerEmail, result.outcome.demoBookingPass);
|
|
15102
15709
|
if (result.outcome.kind === "checkout_redirect") {
|
|
15103
|
-
|
|
15710
|
+
saveAppointmentCheckoutReturnContext(result.outcome.sessionId, {
|
|
15711
|
+
customerEmail: result.outcome.customerEmail,
|
|
15712
|
+
mailingListNote: result.outcome.mailingListSignupNote ?? null
|
|
15713
|
+
});
|
|
15104
15714
|
window.location.href = result.outcome.checkoutUrl;
|
|
15105
15715
|
return;
|
|
15106
15716
|
}
|
|
15107
15717
|
input.setLocalMailingListNote(result.outcome.mailingListSignupNote ?? null);
|
|
15718
|
+
input.setLocalCustomerEmail(result.outcome.customerEmail);
|
|
15108
15719
|
};
|
|
15109
15720
|
}
|
|
15110
15721
|
//#endregion
|
|
@@ -15144,6 +15755,7 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
15144
15755
|
const hasLoggedRebookCompletionRef = useRef(false);
|
|
15145
15756
|
const [redirectState] = useState(() => getBookingRedirectStateFromLocation(getBookingRedirectLocationSnapshot()));
|
|
15146
15757
|
const [localMailingListNote, setLocalMailingListNote] = useState(null);
|
|
15758
|
+
const [localCustomerEmail, setLocalCustomerEmail] = useState(null);
|
|
15147
15759
|
const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
|
|
15148
15760
|
const api = useBlockApi();
|
|
15149
15761
|
const hasPortalAuth = api.config.auth.type === "bearer" || api.config.authOverrides?.portal?.type === "bearer";
|
|
@@ -15226,7 +15838,8 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
15226
15838
|
booking,
|
|
15227
15839
|
bookingAnchorId,
|
|
15228
15840
|
isPortalRebook,
|
|
15229
|
-
setLocalMailingListNote
|
|
15841
|
+
setLocalMailingListNote,
|
|
15842
|
+
setLocalCustomerEmail
|
|
15230
15843
|
});
|
|
15231
15844
|
if (viewState.kind === "success") return /* @__PURE__ */ jsx(BookingSurface, {
|
|
15232
15845
|
id: bookingAnchorId,
|
|
@@ -15235,7 +15848,9 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
15235
15848
|
successMessage: render.display.successMessage,
|
|
15236
15849
|
resourceName: viewState.resourceName,
|
|
15237
15850
|
redirectState,
|
|
15238
|
-
localNote: localMailingListNote
|
|
15851
|
+
localNote: localMailingListNote,
|
|
15852
|
+
customerEmail: localCustomerEmail,
|
|
15853
|
+
demoEmailSuppressed: render.hydration.demoEmailSuppressed
|
|
15239
15854
|
})
|
|
15240
15855
|
});
|
|
15241
15856
|
if (viewState.kind === "verifying") return /* @__PURE__ */ jsx(BookingSurface, {
|
|
@@ -15251,6 +15866,25 @@ const BookingFormClient$1 = ({ siteId: siteIdProp, render }) => {
|
|
|
15251
15866
|
})
|
|
15252
15867
|
})
|
|
15253
15868
|
});
|
|
15869
|
+
if (viewState.kind === "timeout") return /* @__PURE__ */ jsxs(BookingSurface, {
|
|
15870
|
+
id: bookingAnchorId,
|
|
15871
|
+
className: render.display.className,
|
|
15872
|
+
children: [/* @__PURE__ */ jsx(FeedbackMessage, {
|
|
15873
|
+
tone: "info",
|
|
15874
|
+
className: "alert alert-info",
|
|
15875
|
+
role: "status",
|
|
15876
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
15877
|
+
className: "ab-text",
|
|
15878
|
+
children: viewState.message
|
|
15879
|
+
})
|
|
15880
|
+
}), /* @__PURE__ */ jsx(ThemedButton, {
|
|
15881
|
+
type: "button",
|
|
15882
|
+
variant: "primary",
|
|
15883
|
+
size: "md",
|
|
15884
|
+
label: "Check again",
|
|
15885
|
+
onClick: verification.retry
|
|
15886
|
+
})]
|
|
15887
|
+
});
|
|
15254
15888
|
return /* @__PURE__ */ jsxs(BookingSurface, {
|
|
15255
15889
|
id: bookingAnchorId,
|
|
15256
15890
|
className: render.display.className,
|
|
@@ -15311,7 +15945,7 @@ function recoverRegistrationError(action, handlers) {
|
|
|
15311
15945
|
switch (action) {
|
|
15312
15946
|
case "none": return;
|
|
15313
15947
|
case "portal":
|
|
15314
|
-
window.location.assign(
|
|
15948
|
+
window.location.assign(CUSTOMER_PORTAL_PATH);
|
|
15315
15949
|
return;
|
|
15316
15950
|
case "event":
|
|
15317
15951
|
window.location.assign(window.location.pathname);
|
|
@@ -15566,7 +16200,7 @@ function eligibilityLookupReducer(state, action) {
|
|
|
15566
16200
|
settledRequestKey: null,
|
|
15567
16201
|
error: action.message
|
|
15568
16202
|
};
|
|
15569
|
-
default: return assertNever(action);
|
|
16203
|
+
default: return assertNever$1(action);
|
|
15570
16204
|
}
|
|
15571
16205
|
}
|
|
15572
16206
|
const initialExistingRegistrationLookupState = {
|
|
@@ -15584,7 +16218,7 @@ function existingRegistrationLookupReducer(state, action) {
|
|
|
15584
16218
|
tag: "resolved",
|
|
15585
16219
|
registration: action.registration
|
|
15586
16220
|
};
|
|
15587
|
-
default: return assertNever(action);
|
|
16221
|
+
default: return assertNever$1(action);
|
|
15588
16222
|
}
|
|
15589
16223
|
}
|
|
15590
16224
|
//#endregion
|
|
@@ -15838,157 +16472,6 @@ function logoutPortal(anchorId) {
|
|
|
15838
16472
|
form.submit();
|
|
15839
16473
|
}
|
|
15840
16474
|
//#endregion
|
|
15841
|
-
//#region ../commerce/src/purchase/checkoutSessionMetadata.ts
|
|
15842
|
-
const datedOfferingSharedEngineMetadataShape = {
|
|
15843
|
-
datedOfferingEngineContractVersion: z.literal("shared_v1"),
|
|
15844
|
-
datedOfferingEngineRouteKind: z.literal("shared_whole_series_registration"),
|
|
15845
|
-
datedOfferingCapacityHoldId: z.string().uuid(),
|
|
15846
|
-
datedOfferingCapacityHoldAuditRef: z.string().uuid(),
|
|
15847
|
-
customerId: z.string().uuid(),
|
|
15848
|
-
eventSeriesId: z.string().uuid()
|
|
15849
|
-
};
|
|
15850
|
-
z.object(datedOfferingSharedEngineMetadataShape);
|
|
15851
|
-
const orderCheckoutSessionMetadataBaseShape = {
|
|
15852
|
-
type: z.literal("order"),
|
|
15853
|
-
site_id: z.string().uuid(),
|
|
15854
|
-
order_id: z.string().uuid().optional(),
|
|
15855
|
-
customer_email: z.string().email(),
|
|
15856
|
-
customer_name: z.string().optional(),
|
|
15857
|
-
product_id: z.string().uuid().optional(),
|
|
15858
|
-
attendee_id: z.string().uuid().optional(),
|
|
15859
|
-
occurrence_id: z.string().uuid().optional(),
|
|
15860
|
-
tickets_count: z.string().optional(),
|
|
15861
|
-
notes: z.string().optional(),
|
|
15862
|
-
discount_redemption_id: z.string().uuid().optional(),
|
|
15863
|
-
discount_code_id: z.string().uuid().optional(),
|
|
15864
|
-
discount_code: z.string().optional(),
|
|
15865
|
-
discount_public_label: z.string().optional(),
|
|
15866
|
-
credit_reservation_id: z.string().uuid().optional(),
|
|
15867
|
-
credit_reserved_cents: z.string().optional(),
|
|
15868
|
-
discount_code_amount_cents: z.string().optional(),
|
|
15869
|
-
order_payment_reason: z.enum([
|
|
15870
|
-
"instalment_payoff",
|
|
15871
|
-
"flexible_balance_initial",
|
|
15872
|
-
"flexible_balance_paydown"
|
|
15873
|
-
]).optional(),
|
|
15874
|
-
order_payment_plan_id: z.string().uuid().optional(),
|
|
15875
|
-
order_flexible_balance_contract_id: z.string().uuid().optional()
|
|
15876
|
-
};
|
|
15877
|
-
const absentDatedOfferingSharedEngineMetadataShape = {
|
|
15878
|
-
datedOfferingEngineContractVersion: z.never().optional(),
|
|
15879
|
-
datedOfferingEngineRouteKind: z.never().optional(),
|
|
15880
|
-
datedOfferingCapacityHoldId: z.never().optional(),
|
|
15881
|
-
datedOfferingCapacityHoldAuditRef: z.never().optional(),
|
|
15882
|
-
customerId: z.never().optional(),
|
|
15883
|
-
eventSeriesId: z.never().optional()
|
|
15884
|
-
};
|
|
15885
|
-
const LegacyOrderCheckoutSessionMetadataSchema = z.object({
|
|
15886
|
-
...orderCheckoutSessionMetadataBaseShape,
|
|
15887
|
-
...absentDatedOfferingSharedEngineMetadataShape
|
|
15888
|
-
});
|
|
15889
|
-
const SharedDatedOfferingOrderCheckoutSessionMetadataSchema = z.object({
|
|
15890
|
-
...orderCheckoutSessionMetadataBaseShape,
|
|
15891
|
-
...datedOfferingSharedEngineMetadataShape
|
|
15892
|
-
});
|
|
15893
|
-
z.union([SharedDatedOfferingOrderCheckoutSessionMetadataSchema, LegacyOrderCheckoutSessionMetadataSchema]);
|
|
15894
|
-
//#endregion
|
|
15895
|
-
//#region ../commerce/src/purchase/stripeCommissionMetadata.ts
|
|
15896
|
-
/** Reasons are payment evidence, not an independent pricing policy. */
|
|
15897
|
-
const STRIPE_COMMISSION_FREE_REASONS = [
|
|
15898
|
-
"managed_billing",
|
|
15899
|
-
"no_commission_plan",
|
|
15900
|
-
"billing_evidence_invalid",
|
|
15901
|
-
"fee_rounds_to_zero",
|
|
15902
|
-
"payment_not_stripe"
|
|
15903
|
-
];
|
|
15904
|
-
const historicalContext = {
|
|
15905
|
-
currency: z.string().refine((value) => parseCurrencyCode(value) !== null).optional(),
|
|
15906
|
-
sourcePlanId: z.string().trim().min(1).optional()
|
|
15907
|
-
};
|
|
15908
|
-
const percentSchema = z.number().finite().min(0).max(100);
|
|
15909
|
-
z.discriminatedUnion("kind", [
|
|
15910
|
-
z.object({
|
|
15911
|
-
kind: z.literal("commission_free"),
|
|
15912
|
-
reason: z.enum(STRIPE_COMMISSION_FREE_REASONS),
|
|
15913
|
-
...historicalContext
|
|
15914
|
-
}),
|
|
15915
|
-
z.object({
|
|
15916
|
-
kind: z.literal("application_fee_amount"),
|
|
15917
|
-
amountCents: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
15918
|
-
percent: percentSchema,
|
|
15919
|
-
...historicalContext
|
|
15920
|
-
}),
|
|
15921
|
-
z.object({
|
|
15922
|
-
kind: z.literal("application_fee_percent"),
|
|
15923
|
-
percent: percentSchema,
|
|
15924
|
-
...historicalContext
|
|
15925
|
-
})
|
|
15926
|
-
]);
|
|
15927
|
-
toNonNegativeCents(0);
|
|
15928
|
-
//#endregion
|
|
15929
|
-
//#region ../commerce/src/purchase/event-registration-errors.ts
|
|
15930
|
-
const eventRegistrationErrors = {
|
|
15931
|
-
registrationClosed: {
|
|
15932
|
-
message: "Booking is currently closed for this event. Please contact the organiser if you’d like to find out more.",
|
|
15933
|
-
action: "none"
|
|
15934
|
-
},
|
|
15935
|
-
paymentInvestigationRequired: {
|
|
15936
|
-
message: "We still can’t confirm your payment. Please don’t make another payment. Contact the organiser so they can check your booking.",
|
|
15937
|
-
action: "none"
|
|
15938
|
-
},
|
|
15939
|
-
paymentProviderUnavailable: {
|
|
15940
|
-
message: "We couldn’t reach the payment provider. Please try again in a minute.",
|
|
15941
|
-
action: "retry"
|
|
15942
|
-
},
|
|
15943
|
-
paymentPageUnavailable: {
|
|
15944
|
-
message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
|
|
15945
|
-
action: "retry"
|
|
15946
|
-
},
|
|
15947
|
-
paymentUnavailable: {
|
|
15948
|
-
message: "Online payment is not available for this event right now. Please contact the organiser for help with booking.",
|
|
15949
|
-
action: "none"
|
|
15950
|
-
},
|
|
15951
|
-
capacityChanged: {
|
|
15952
|
-
message: "Sorry, there aren’t enough places left for your selection. Please check the available places and choose again.",
|
|
15953
|
-
action: "places"
|
|
15954
|
-
},
|
|
15955
|
-
selectionChanged: {
|
|
15956
|
-
message: "The booking options for this event have changed. Please check the latest options and choose your places again.",
|
|
15957
|
-
action: "places"
|
|
15958
|
-
},
|
|
15959
|
-
registrationPreparationChanged: {
|
|
15960
|
-
message: "The booking options for this event have changed. Please check the latest options and choose your places again.",
|
|
15961
|
-
action: "places"
|
|
15962
|
-
},
|
|
15963
|
-
registrationAlreadyExists: {
|
|
15964
|
-
message: "You already have a booking for this event. Please check your bookings to see its status. If you need help, contact the organiser.",
|
|
15965
|
-
action: "portal"
|
|
15966
|
-
},
|
|
15967
|
-
holdExpired: {
|
|
15968
|
-
message: "Your reservation has timed out. Please check availability and choose your places again.",
|
|
15969
|
-
action: "start"
|
|
15970
|
-
},
|
|
15971
|
-
waitlistUnavailable: {
|
|
15972
|
-
message: "Sorry, the waiting list place offered in this invitation is no longer available. Please check the event for available places or contact the organiser for help.",
|
|
15973
|
-
action: "event"
|
|
15974
|
-
},
|
|
15975
|
-
paymentContextMismatch: {
|
|
15976
|
-
message: "The payment options for this event have changed. Please check the latest options before continuing.",
|
|
15977
|
-
action: "payment-options"
|
|
15978
|
-
},
|
|
15979
|
-
idempotencyConflict: {
|
|
15980
|
-
message: "You’ve already started booking this event. Please finish in the other tab if it’s still open, or check your booking status before starting again.",
|
|
15981
|
-
action: "portal"
|
|
15982
|
-
},
|
|
15983
|
-
invalidCommitInput: {
|
|
15984
|
-
message: "We couldn’t accept your booking details. Please check the information you entered and try again. If this keeps happening, contact the organiser for help.",
|
|
15985
|
-
action: "details"
|
|
15986
|
-
}
|
|
15987
|
-
};
|
|
15988
|
-
function parseEventRegistrationErrorReason(value) {
|
|
15989
|
-
return typeof value === "string" && Object.prototype.hasOwnProperty.call(eventRegistrationErrors, value) ? value : null;
|
|
15990
|
-
}
|
|
15991
|
-
//#endregion
|
|
15992
16475
|
//#region ../blocks/src/system/runtime/shared/useWaitlistClaim.state.ts
|
|
15993
16476
|
const DEFAULT_WAITLIST_CLAIM_ERROR = "Online booking is unavailable right now. Please contact the organiser for help with booking.";
|
|
15994
16477
|
function createInitialWaitlistClaimState(hasToken) {
|
|
@@ -16163,11 +16646,50 @@ function useResolvedWaitlistClaim(deps, credential) {
|
|
|
16163
16646
|
* ```
|
|
16164
16647
|
*/
|
|
16165
16648
|
const paymentVerificationDeps = { useBlockApi };
|
|
16649
|
+
function resolvePaymentPollingTarget(config) {
|
|
16650
|
+
const reference = config.reference;
|
|
16651
|
+
return reference.scope === "occurrence" ? {
|
|
16652
|
+
key: `occurrence:${reference.attendeeId}`,
|
|
16653
|
+
reference
|
|
16654
|
+
} : {
|
|
16655
|
+
key: `wholeSeries:${reference.registrationId}`,
|
|
16656
|
+
reference
|
|
16657
|
+
};
|
|
16658
|
+
}
|
|
16659
|
+
function createPaymentPollingConfig(api, settings) {
|
|
16660
|
+
if (settings === null) return null;
|
|
16661
|
+
const target = resolvePaymentPollingTarget(settings);
|
|
16662
|
+
return {
|
|
16663
|
+
restartKey: target.key,
|
|
16664
|
+
pollFn: () => api.getEventRegistrationStatus(target.reference),
|
|
16665
|
+
isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
|
|
16666
|
+
isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
|
|
16667
|
+
maxAttempts: settings.maxAttempts,
|
|
16668
|
+
interval: settings.pollInterval
|
|
16669
|
+
};
|
|
16670
|
+
}
|
|
16671
|
+
function getPaymentVerificationError(polling, paymentStatus) {
|
|
16672
|
+
if (polling.status === "timeout") return "Could not verify payment. If you were charged, please contact support.";
|
|
16673
|
+
if (polling.status === "failed" && paymentStatus !== null) return paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
|
|
16674
|
+
return polling.error?.message ?? null;
|
|
16675
|
+
}
|
|
16676
|
+
function mapPaymentVerificationResult(polling) {
|
|
16677
|
+
const paymentStatus = polling.result?.paymentStatus ?? null;
|
|
16678
|
+
return {
|
|
16679
|
+
status: polling.status,
|
|
16680
|
+
paymentStatus,
|
|
16681
|
+
attendeeStatus: polling.result?.attendeeStatus ?? null,
|
|
16682
|
+
waitlistPosition: polling.result?.waitlistPosition ?? null,
|
|
16683
|
+
error: getPaymentVerificationError(polling, paymentStatus),
|
|
16684
|
+
retry: polling.retry
|
|
16685
|
+
};
|
|
16686
|
+
}
|
|
16166
16687
|
/**
|
|
16167
16688
|
* Hook for polling payment status after Stripe redirects.
|
|
16168
16689
|
*
|
|
16169
16690
|
* Pass config to start polling, or null to stop/idle.
|
|
16170
|
-
* The hook handles cleanup on unmount and
|
|
16691
|
+
* The hook handles cleanup on unmount and starts a new cycle when the status
|
|
16692
|
+
* reference changes.
|
|
16171
16693
|
*
|
|
16172
16694
|
* @param config - Configuration for polling, or null to stop
|
|
16173
16695
|
* @returns Verification result with status, data, and retry function
|
|
@@ -16176,30 +16698,7 @@ function usePaymentVerification(config) {
|
|
|
16176
16698
|
return usePaymentVerificationWithDeps(config, paymentVerificationDeps);
|
|
16177
16699
|
}
|
|
16178
16700
|
function usePaymentVerificationWithDeps(config, deps) {
|
|
16179
|
-
|
|
16180
|
-
const polling = usePolling(useMemo(() => {
|
|
16181
|
-
if (!config) return null;
|
|
16182
|
-
return {
|
|
16183
|
-
pollFn: () => api.getEventRegistrationStatus(config.reference),
|
|
16184
|
-
isComplete: (result) => result.paymentStatus === "completed" || result.paymentStatus === "not_required",
|
|
16185
|
-
isFailed: (result) => result.paymentStatus === "failed" || result.paymentStatus === "refunded",
|
|
16186
|
-
maxAttempts: config.maxAttempts,
|
|
16187
|
-
interval: config.pollInterval
|
|
16188
|
-
};
|
|
16189
|
-
}, [api, config]));
|
|
16190
|
-
const paymentStatus = polling.result?.paymentStatus ?? null;
|
|
16191
|
-
let errorMessage = null;
|
|
16192
|
-
if (polling.status === "timeout") errorMessage = "Could not verify payment. If you were charged, please contact support.";
|
|
16193
|
-
else if (polling.status === "failed" && paymentStatus) errorMessage = paymentStatus === "refunded" ? "Payment was refunded. Please contact support." : "Payment was declined. Please try again.";
|
|
16194
|
-
else if (polling.error) errorMessage = polling.error.message;
|
|
16195
|
-
return {
|
|
16196
|
-
status: polling.status,
|
|
16197
|
-
paymentStatus,
|
|
16198
|
-
attendeeStatus: polling.result?.attendeeStatus ?? null,
|
|
16199
|
-
waitlistPosition: polling.result?.waitlistPosition ?? null,
|
|
16200
|
-
error: errorMessage,
|
|
16201
|
-
retry: polling.retry
|
|
16202
|
-
};
|
|
16701
|
+
return mapPaymentVerificationResult(usePolling(createPaymentPollingConfig(deps.useBlockApi(), config)));
|
|
16203
16702
|
}
|
|
16204
16703
|
//#endregion
|
|
16205
16704
|
//#region ../blocks/src/system/runtime/nodes/event-registration/constants.ts
|
|
@@ -16572,20 +17071,9 @@ function registrationErrorPresentation(error) {
|
|
|
16572
17071
|
function wantsMailingListSignup(options) {
|
|
16573
17072
|
return options.mailingListSignup !== null && options.formData.mailingListOptIn === true;
|
|
16574
17073
|
}
|
|
16575
|
-
function createClientCommandId(cryptoSource = {
|
|
16576
|
-
randomUUID: globalThis.crypto.randomUUID?.bind(globalThis.crypto),
|
|
16577
|
-
getRandomValues: (bytes) => globalThis.crypto.getRandomValues(bytes)
|
|
16578
|
-
}) {
|
|
16579
|
-
if (cryptoSource.randomUUID) return cryptoSource.randomUUID();
|
|
16580
|
-
const bytes = cryptoSource.getRandomValues(/* @__PURE__ */ new Uint8Array(16));
|
|
16581
|
-
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
16582
|
-
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
16583
|
-
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
|
|
16584
|
-
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
|
|
16585
|
-
}
|
|
16586
17074
|
const eventRegistrationSubmitDeps = {
|
|
16587
17075
|
savePendingRegistration,
|
|
16588
|
-
createClientCommandId
|
|
17076
|
+
createClientCommandId: generateUuidV4
|
|
16589
17077
|
};
|
|
16590
17078
|
function useEventRegistrationSubmit(options) {
|
|
16591
17079
|
return useEventRegistrationSubmitWithDeps(options, eventRegistrationSubmitDeps);
|
|
@@ -16665,6 +17153,7 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
|
|
|
16665
17153
|
};
|
|
16666
17154
|
}
|
|
16667
17155
|
async function completeRegistrationSubmission(options, deps, prepared, result, submitOptions) {
|
|
17156
|
+
if (result.demoBookingPass) storeDemoBookingPass(options.formData.email, result.demoBookingPass);
|
|
16668
17157
|
switch (result.kind) {
|
|
16669
17158
|
case "paymentStatusRequired":
|
|
16670
17159
|
options.setPaymentStatusRecovery({
|
|
@@ -16687,6 +17176,7 @@ async function completeRegistrationSubmission(options, deps, prepared, result, s
|
|
|
16687
17176
|
status: "waitlist",
|
|
16688
17177
|
title: "Added to waitlist",
|
|
16689
17178
|
message: result.waitlist.message,
|
|
17179
|
+
emailFollowupMessage: result.waitlist.emailFollowupMessage,
|
|
16690
17180
|
mailingListSignupNote: result.mailingListSignupNote
|
|
16691
17181
|
});
|
|
16692
17182
|
break;
|
|
@@ -16902,6 +17392,7 @@ function buildEventRegistrationPaymentOptionsViewModel(input) {
|
|
|
16902
17392
|
priceAmount: input.totalPriceCents,
|
|
16903
17393
|
priceCurrency: input.currency,
|
|
16904
17394
|
bookingStartAt: input.startsAt,
|
|
17395
|
+
nowIso: input.nowIso,
|
|
16905
17396
|
locale: input.locale
|
|
16906
17397
|
});
|
|
16907
17398
|
return {
|
|
@@ -16909,7 +17400,7 @@ function buildEventRegistrationPaymentOptionsViewModel(input) {
|
|
|
16909
17400
|
sectionTitle: selection.sectionTitle,
|
|
16910
17401
|
options: selection.options.flatMap((option, index) => {
|
|
16911
17402
|
const sourceOption = approvedOptions[index];
|
|
16912
|
-
return sourceOption ? [toEventDirectPaymentOption(option, sourceOption, selection.mode, input.totalPriceCents
|
|
17403
|
+
return sourceOption ? [toEventDirectPaymentOption(option, sourceOption, selection.mode, input.totalPriceCents)] : [];
|
|
16913
17404
|
})
|
|
16914
17405
|
};
|
|
16915
17406
|
}
|
|
@@ -16917,11 +17408,10 @@ function selectApprovedEventDirectPaymentOptions(approvedPaymentOptions, payment
|
|
|
16917
17408
|
const approvedKinds = new Set(getApprovedDirectPaymentCollectionOptionKinds(approvedPaymentOptions));
|
|
16918
17409
|
return paymentTerms.allowedOptions.filter((option) => approvedKinds.has(option.kind));
|
|
16919
17410
|
}
|
|
16920
|
-
function toEventDirectPaymentOption(option, sourceOption, mode, totalCents
|
|
17411
|
+
function toEventDirectPaymentOption(option, sourceOption, mode, totalCents) {
|
|
16921
17412
|
const configuredPaymentDueNowCents = resolveBookingPaymentDueNowCents({
|
|
16922
17413
|
option: sourceOption,
|
|
16923
|
-
totalCents
|
|
16924
|
-
bookingStartAt: startsAt
|
|
17414
|
+
totalCents
|
|
16925
17415
|
});
|
|
16926
17416
|
switch (option.kind) {
|
|
16927
17417
|
case "upfront": return {
|
|
@@ -17908,13 +18398,15 @@ const eventRegistrationWizardDeps = {
|
|
|
17908
18398
|
useWaitlistClaim,
|
|
17909
18399
|
useEventRegistrationStripeReturn,
|
|
17910
18400
|
useEventRegistrationSubmit,
|
|
17911
|
-
useDiscountCodeUi
|
|
18401
|
+
useDiscountCodeUi,
|
|
18402
|
+
useBookingNowIso
|
|
17912
18403
|
};
|
|
17913
18404
|
function useEventRegistrationWizard(options) {
|
|
17914
18405
|
return useEventRegistrationWizardWithDeps(options, eventRegistrationWizardDeps);
|
|
17915
18406
|
}
|
|
17916
18407
|
function useEventRegistrationWizardWithDeps(options, deps) {
|
|
17917
18408
|
const api = useBlockApi();
|
|
18409
|
+
const nowIso = deps.useBookingNowIso();
|
|
17918
18410
|
const registrationEvents = useMemo(() => [...toRegistrationEvents(options.events ?? []), ...toWholeSeriesRegistrationEvents(options.events ?? [])], [options.events]);
|
|
17919
18411
|
const scopedEvents = useMemo(() => {
|
|
17920
18412
|
return resolveEventRegistrationScopedEvents(registrationEvents, {
|
|
@@ -18445,6 +18937,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
|
|
|
18445
18937
|
});
|
|
18446
18938
|
return {
|
|
18447
18939
|
api,
|
|
18940
|
+
nowIso,
|
|
18448
18941
|
anchorId: options.anchorId,
|
|
18449
18942
|
occurrenceContext: options.occurrenceContext,
|
|
18450
18943
|
registrationTarget,
|
|
@@ -18573,6 +19066,7 @@ function useEventRegistrationControllerWithDeps(options, deps) {
|
|
|
18573
19066
|
const currentStep = steps.find((step) => step.state === "active") ?? null;
|
|
18574
19067
|
const directPaymentOptions = useMemo(() => resolveHeadlessDirectPaymentOptions(wizard), [
|
|
18575
19068
|
wizard.eligibility,
|
|
19069
|
+
wizard.nowIso,
|
|
18576
19070
|
wizard.occurrenceContext,
|
|
18577
19071
|
wizard.preSelectedEvent,
|
|
18578
19072
|
wizard.selectedEvent,
|
|
@@ -18850,7 +19344,8 @@ function resolveHeadlessDirectPaymentOptions(wizard) {
|
|
|
18850
19344
|
paymentTerms: eligibility.paymentTerms,
|
|
18851
19345
|
totalPriceCents: eligibility.price,
|
|
18852
19346
|
currency: eligibility.currency,
|
|
18853
|
-
startsAt: wizard.occurrenceContext?.startsAt ?? event?.startsAt
|
|
19347
|
+
startsAt: wizard.occurrenceContext?.startsAt ?? event?.startsAt,
|
|
19348
|
+
nowIso: wizard.nowIso
|
|
18854
19349
|
}).options;
|
|
18855
19350
|
}
|
|
18856
19351
|
//#endregion
|
|
@@ -18903,7 +19398,7 @@ function bookingFormConfigReducer(state, action) {
|
|
|
18903
19398
|
message: action.message,
|
|
18904
19399
|
previous: toBookingFormConfigSnapshot(state)
|
|
18905
19400
|
};
|
|
18906
|
-
default: return assertNever(action);
|
|
19401
|
+
default: return assertNever$1(action);
|
|
18907
19402
|
}
|
|
18908
19403
|
}
|
|
18909
19404
|
function selectBookingFormConfig(state) {
|
|
@@ -18926,7 +19421,7 @@ function toBookingFormConfigSnapshot(state) {
|
|
|
18926
19421
|
formConfig: state.formConfig,
|
|
18927
19422
|
services: state.services
|
|
18928
19423
|
};
|
|
18929
|
-
default: return assertNever(state);
|
|
19424
|
+
default: return assertNever$1(state);
|
|
18930
19425
|
}
|
|
18931
19426
|
}
|
|
18932
19427
|
//#endregion
|