@riverbankcms/sdk 0.88.0 → 0.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -4
- package/dist/{PreviewEditorSidebar-EVRS3C7T.mjs → PreviewEditorSidebar-KVXNF3VW.mjs} +3 -3
- package/dist/{PreviewEditorUI-54WD4IGE.mjs → PreviewEditorUI-J3JN5Z7T.mjs} +3 -3
- package/dist/SdkPreviewModeRuntime-UBL6MSNP.mjs +8 -0
- package/dist/_dts/ai/src/contracts/proposals.d.ts +216 -0
- package/dist/_dts/altcha/src/AltchaWidget.d.ts +1 -1
- package/dist/_dts/api/src/accessAdmin.d.ts +7 -0
- package/dist/_dts/api/src/bookingOperations.d.ts +2 -0
- package/dist/_dts/api/src/bookingRecords.d.ts +4 -2
- package/dist/_dts/api/src/bookings.d.ts +3 -1
- package/dist/_dts/api/src/endpoints.d.ts +8 -0
- package/dist/_dts/api/src/index.d.ts +7 -6
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +15 -5
- package/dist/_dts/api/src/request.d.ts +21 -0
- package/dist/_dts/api/src/sdk-event-upsert.d.ts +3 -1
- package/dist/_dts/api/src/sdkContracts.d.ts +2 -0
- package/dist/_dts/api/src/siteManagementEndpoints.d.ts +5 -1
- package/dist/_dts/api/src/siteMembers.d.ts +6 -1
- package/dist/_dts/api/src/types.d.ts +4 -2
- package/dist/_dts/api/src/url.d.ts +6 -3
- package/dist/_dts/block-form/src/utils/visibleWhen.d.ts +1 -0
- package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterThumbnailCard.d.ts +5 -1
- package/dist/_dts/block-form/src/widgets/RepeaterField/components/RepeaterThumbnailGrid.d.ts +9 -1
- package/dist/_dts/block-form/src/widgets/RepeaterField/components/index.d.ts +1 -0
- package/dist/_dts/blocks/src/contracts/non-block-islands.d.ts +7 -11
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +6 -0
- package/dist/_dts/blocks/src/index.d.ts +2 -1
- package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +14 -6
- package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -4
- package/dist/_dts/blocks/src/system/blocks/hero.d.ts +0 -2
- package/dist/_dts/blocks/src/system/blocks/shop.d.ts +3 -3
- package/dist/_dts/blocks/src/system/blocks/shop.shared.d.ts +8 -0
- package/dist/_dts/blocks/src/system/constants/events.d.ts +4 -1
- package/dist/_dts/blocks/src/system/icons/cta.d.ts +3 -3
- package/dist/_dts/blocks/src/system/icons/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/icons/registry.d.ts +2 -2
- package/dist/_dts/blocks/src/system/icons/semantic.d.ts +3 -3
- package/dist/_dts/blocks/src/system/icons/svg.d.ts +72 -0
- package/dist/_dts/blocks/src/system/manifest/schema.d.ts +3 -1
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +18 -5
- package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +51 -6
- package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/loadStateError.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useAvailableDates.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useAvailableDates.state.d.ts +55 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useAvailableSlots.state.d.ts +39 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useBookingFormConfig.d.ts +4 -27
- package/dist/_dts/blocks/src/system/runtime/hooks/useBookingFormConfig.state.d.ts +40 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useCalendarEvents.state.d.ts +20 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.state.d.ts +31 -0
- package/dist/_dts/blocks/src/system/runtime/hooks/useEventPagination.d.ts +3 -3
- package/dist/_dts/blocks/src/system/runtime/hooks/useEventPagination.state.d.ts +39 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +1 -17
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.client.d.ts +5 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-details.server.d.ts +5 -9
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventPaymentOptions.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +5 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +4 -4
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +50 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +21 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCalendar.interactive.d.ts +11 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +2 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +11 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventPaginatedListView.client.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/calendarViewOptions.d.ts +10 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventProductEligibility.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.client.state.d.ts +24 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/shared/MagicLinkForm.state.d.ts +24 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +5 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/shop-checkout-form.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.state.d.ts +35 -0
- package/dist/_dts/content-model/src/entry-slots/index.d.ts +1 -0
- package/dist/_dts/content-model/src/entry-slots/sdkBlocks.d.ts +21 -0
- package/dist/_dts/content-model/src/entry-slots/types.d.ts +61 -0
- package/dist/_dts/core/src/branded.d.ts +7 -0
- package/dist/_dts/core/src/index.d.ts +1 -0
- package/dist/_dts/core/src/money-input.d.ts +18 -0
- package/dist/_dts/core/src/site-route-target.d.ts +40 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +209 -2
- package/dist/_dts/media-core/src/fileDomain.d.ts +4 -0
- package/dist/_dts/media-editor/src/MediaEditor.d.ts +2 -1
- package/dist/_dts/media-editor/src/fieldUi.d.ts +6 -0
- package/dist/_dts/media-editor/src/index.d.ts +1 -1
- package/dist/_dts/preview-next/src/client/index.d.ts +1 -0
- package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/PreviewThemedSiteDocument.d.ts +3 -2
- package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +2 -2
- package/dist/_dts/preview-next/src/client/preview/themeRuntime.d.ts +6 -0
- package/dist/_dts/preview-next/src/client/sdk/SdkPreviewMode.d.ts +2 -1
- package/dist/_dts/sdk/src/cli/commands/pull-dated-offering-scope.d.ts +10 -0
- package/dist/_dts/sdk/src/cli/content/reader.d.ts +12 -5
- package/dist/_dts/sdk/src/client/management/types.d.ts +6 -55
- package/dist/_dts/sdk/src/client/runtimeCachePolicy.d.ts +160 -0
- package/dist/_dts/sdk/src/client/types.d.ts +26 -1
- package/dist/_dts/sdk/src/components.d.ts +1 -0
- package/dist/_dts/sdk/src/config/field-definitions.d.ts +3 -1
- package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +3 -1
- package/dist/_dts/sdk/src/index.d.ts +3 -1
- package/dist/_dts/sdk/src/next/types.d.ts +8 -11
- package/dist/_dts/sdk/src/preview-next/client/index.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/blocks-theme-scope.d.ts +2 -1
- package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +8 -7
- package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +5 -6
- package/dist/_dts/sdk/src/rendering/index.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/server.d.ts +1 -0
- package/dist/_dts/sdk/src/rendering/themeRuntime.d.ts +26 -0
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/site-commands/src/commands.d.ts +18 -0
- package/dist/_dts/theme-core/src/ResponsiveScope.d.ts +12 -0
- package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
- package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/buttons/types.d.ts +5 -5
- package/dist/_dts/theme-core/src/cards/types.d.ts +2 -2
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/_dts/theme-core/src/index.d.ts +2 -0
- package/dist/_dts/theme-core/src/mock-themes/all.d.ts +21 -21
- package/dist/_dts/theme-core/src/schema.d.ts +18 -18
- package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +2 -2
- package/dist/_dts/theme-core/src/site-styles/logoBranding.d.ts +4 -4
- package/dist/_dts/theme-core/src/themeRuntime.d.ts +11 -0
- package/dist/{chunk-ER4UIW4X.mjs → chunk-AEOYWPE4.mjs} +91 -55
- package/dist/{chunk-O4LVYUVH.mjs → chunk-BOQXMCSP.mjs} +147 -101
- package/dist/{chunk-HVOBXA3Y.mjs → chunk-GSPFFUVB.mjs} +2 -2
- package/dist/{chunk-7KOO7RPP.mjs → chunk-PMBB6MQ7.mjs} +2273 -1113
- package/dist/{chunk-K3JWH6HE.mjs → chunk-RQ3XZ4SJ.mjs} +9 -1
- package/dist/{chunk-YDMBIIS5.mjs → chunk-UG7I7S7W.mjs} +1 -1
- package/dist/cli/index.mjs +1564 -546
- package/dist/cli/init-docs/content/cli-reference.md +6 -1
- package/dist/cli/init-docs/content/content-management.md +27 -0
- package/dist/client/{accordion-PT5CGW5N.mjs → accordion-GXQNWQ6O.mjs} +2 -2
- package/dist/client/{bookingForm-2HLRTEYS.mjs → bookingForm-STLUJ36H.mjs} +206 -335
- package/dist/client/bookings.mjs +821 -413
- package/dist/client/{carousel-Z2LKYSWA.mjs → carousel-CVRN6EPP.mjs} +4 -3
- package/dist/client/{cart-ND5IK4A6.mjs → cart-IYIBA5CL.mjs} +8 -8
- package/dist/client/{checkout-EYUSGAY7.mjs → checkout-O3BGM4GS.mjs} +8 -8
- package/dist/client/chunk-4RTFGHZN.mjs +433 -0
- package/dist/client/{chunk-DIRW2LNG.mjs → chunk-6DPXDOIL.mjs} +336 -225
- package/dist/client/chunk-6N7YRNYU.mjs +183 -0
- package/dist/client/{chunk-O5JNI3E4.mjs → chunk-7DH35FGA.mjs} +2 -2
- package/dist/client/{chunk-S4G65LGR.mjs → chunk-D3ETC2SU.mjs} +1 -1
- package/dist/client/{chunk-BAWHZ5GM.mjs → chunk-DAS5CIER.mjs} +460 -157
- package/dist/client/{chunk-6DVPO44G.mjs → chunk-FHU6PFPM.mjs} +1 -1
- package/dist/client/{chunk-SDIYSQAY.mjs → chunk-HIHOQGIP.mjs} +2 -3
- package/dist/client/{chunk-BL66UWGD.mjs → chunk-MFPKS6QS.mjs} +13 -16
- package/dist/client/{chunk-X7GVFB7Y.mjs → chunk-NBFRJ5NB.mjs} +157 -5
- package/dist/client/{chunk-WCVK4MBJ.mjs → chunk-VFHZLZAC.mjs} +1 -1
- package/dist/client/{chunk-GOFO7HRH.mjs → chunk-WHZQDPBZ.mjs} +19 -1
- package/dist/client/{chunk-MHBEWDT7.mjs → chunk-Z62JYS5O.mjs} +122 -50
- package/dist/client/client.mjs +5979 -5198
- package/dist/client/{courseRegistration-H3AZBUEG.mjs → courseRegistration-2D3ACMJR.mjs} +20 -58
- package/dist/client/{eventCalendar-FPKJGLGS.mjs → eventCalendar-QY4UZUFF.mjs} +11 -11
- package/dist/client/{eventCombined-QCGIZBUY.mjs → eventCombined-RRCDKJC2.mjs} +11 -11
- package/dist/client/{eventDetails-HIT3BJWU.mjs → eventDetails-YO335BUT.mjs} +11 -11
- package/dist/client/{eventListing-R4HNWJDN.mjs → eventListing-PXA6GFQ3.mjs} +11 -11
- package/dist/client/{eventRegistration-Q7BYY5HF.mjs → eventRegistration-2ZHEDDXO.mjs} +11 -11
- package/dist/client/{form-NI6YOG6S.mjs → form-ZS6KX4U2.mjs} +7 -7
- package/dist/client/{headerSection-SDYGII36.mjs → headerSection-QK5SLIIB.mjs} +3 -3
- package/dist/client/hooks.mjs +1102 -1029
- package/dist/client/{locationMap-BDETEUQD.mjs → locationMap-GFNIUD2X.mjs} +3 -3
- package/dist/client/{newsletterForm-EKYIU67X.mjs → newsletterForm-PGLTTCUG.mjs} +61 -25
- package/dist/client/{productDetail-5UTGNN76.mjs → productDetail-OPBE5ZPI.mjs} +8 -8
- package/dist/client/{productList-7YA5KXZQ.mjs → productList-NI72Q62Z.mjs} +8 -8
- package/dist/client/rendering/client.mjs +4390 -4245
- package/dist/client/rendering/islands.mjs +19 -19
- package/dist/client/rendering.mjs +3327 -3181
- package/dist/client/{shop-AIMUMZYC.mjs → shop-3ZQPEWYI.mjs} +8 -8
- package/dist/client/spam-protection.mjs +4 -5
- package/dist/preview-next/before-render.mjs +20 -2
- package/dist/preview-next/client/runtime.mjs +5 -5
- package/dist/preview-next/middleware.mjs +18 -0
- package/dist/{sdk-runtime-NW472WNT.mjs → sdk-runtime-FSHXCWDS.mjs} +6 -6
- package/dist/server/components.mjs +2580 -2783
- package/dist/server/config-validation.mjs +1334 -1261
- package/dist/server/config.mjs +1334 -1261
- package/dist/server/data.mjs +1102 -1029
- package/dist/server/index.mjs +1097 -476
- package/dist/server/navigation.mjs +20 -30
- package/dist/server/next.mjs +3282 -2847
- package/dist/server/page-converter.mjs +1009 -946
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +2580 -2783
- package/dist/server/rendering.mjs +2586 -2789
- package/dist/server/routing.mjs +1440 -1053
- package/dist/server/server.mjs +1886 -1153
- package/dist/server/theme-bridge.mjs +34 -5
- package/dist/styles/index.css +26 -0
- package/package.json +3 -2
- package/dist/SdkPreviewModeRuntime-ZALZDJEK.mjs +0 -8
- package/dist/client/chunk-H4MHEXYS.mjs +0 -184
- package/dist/client/chunk-ZFHRN6W2.mjs +0 -66
- /package/dist/client/{chunk-LI2C6M5O.mjs → chunk-25W2EQUN.mjs} +0 -0
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { usePolling } from './chunk-
|
|
3
|
-
import { SpinnerNode } from './chunk-
|
|
4
|
-
import { useDiscountCodeUi } from './chunk-ZFHRN6W2.mjs';
|
|
2
|
+
import { buildBookingPaymentSelectionViewModel, usePolling } from './chunk-4RTFGHZN.mjs';
|
|
3
|
+
import { SpinnerNode } from './chunk-FHU6PFPM.mjs';
|
|
5
4
|
import { buildRouteIslandApiConfig } from './chunk-L4J5Y62O.mjs';
|
|
6
|
-
import { scrollToBlock, buildCheckoutReturnUrls, DiscountCodeDisclosure
|
|
5
|
+
import { scrollToBlock, useDiscountCodeUi, buildCheckoutReturnUrls, DiscountCodeDisclosure } from './chunk-NBFRJ5NB.mjs';
|
|
7
6
|
import { FieldValidationMessage, getFieldValidationControlProps } from './chunk-3DCJ45Z2.mjs';
|
|
8
7
|
import './chunk-WBQG7VJA.mjs';
|
|
9
|
-
import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-
|
|
10
|
-
import { BlockApiProvider, useBlockApi, FeedbackMessage } from './chunk-
|
|
8
|
+
import { isSpamProtectionEnabled, getChallengeUrl, AltchaWidget } from './chunk-HIHOQGIP.mjs';
|
|
9
|
+
import { BlockApiProvider, useBlockApi, FeedbackMessage } from './chunk-WHZQDPBZ.mjs';
|
|
11
10
|
import { mountReactIsland } from './chunk-N7PBWBWQ.mjs';
|
|
12
|
-
import { defineIslandPropsDecoder, resolveBookingSiteId, resolveDefaultBookingServiceId, getBookingRedirectStateFromLocation, deriveBookingFormViewState, logger, getBookingSuccessMessage, resolveAppointmentCheckoutVerificationState, themeButtonClassName, toSelectedCollectionOptionKind,
|
|
13
|
-
import { resolveBookingTimeZoneId, DEFAULT_BOOKING_TIME_ZONE, unsafeAsFormId, unsafeAsAppointmentResourceId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, formatLocalScheduleDate, addLocalScheduleDays, parseBookingLocalDate,
|
|
11
|
+
import { defineIslandPropsDecoder, resolveBookingSiteId, resolveDefaultBookingServiceId, getBookingRedirectStateFromLocation, deriveBookingFormViewState, logger, getBookingSuccessMessage, resolveAppointmentCheckoutVerificationState, themeButtonClassName, toSelectedCollectionOptionKind, assertNever, prepareBookingSubmission, formatBookingSubmissionPreparationError, resolveBookingPaymentStep, BOOKING_FORM_DATA_RESERVED_KEYS, clearWorkflowFeedback, reportWorkflowError, reportWorkflowSuccess, okWith, err } from './chunk-6DPXDOIL.mjs';
|
|
12
|
+
import { resolveBookingTimeZoneId, DEFAULT_BOOKING_TIME_ZONE, unsafeAsFormId, unsafeAsAppointmentResourceId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, formatLocalScheduleDate, addLocalScheduleDays, parseBookingLocalDate, unsafeAsPassId, formatBookingInstant } from './chunk-25W2EQUN.mjs';
|
|
14
13
|
import React2, { useRef, useState, useMemo, useReducer, useEffect, useCallback, useLayoutEffect } from 'react';
|
|
15
14
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
16
15
|
|
|
@@ -141,6 +140,74 @@ function useVisibleTabPolling({
|
|
|
141
140
|
}, [enabled, intervalMs, jitterMs, minVisibleRefreshIntervalMs]);
|
|
142
141
|
}
|
|
143
142
|
|
|
143
|
+
// ../blocks/src/system/runtime/hooks/useAvailableDates.state.ts
|
|
144
|
+
function createEmptyAvailableDatesData() {
|
|
145
|
+
return {
|
|
146
|
+
availableDates: /* @__PURE__ */ new Set(),
|
|
147
|
+
hasMore: false,
|
|
148
|
+
loadedRange: null,
|
|
149
|
+
nextStartDate: null
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function createInitialAvailableDatesState() {
|
|
153
|
+
return {
|
|
154
|
+
tag: "idle",
|
|
155
|
+
data: createEmptyAvailableDatesData()
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function getAvailableDates(state) {
|
|
159
|
+
return state.data.availableDates;
|
|
160
|
+
}
|
|
161
|
+
function getAvailableDatesLoadedRange(state) {
|
|
162
|
+
return state.data.loadedRange;
|
|
163
|
+
}
|
|
164
|
+
function getAvailableDatesNextStartDate(state) {
|
|
165
|
+
return state.data.nextStartDate;
|
|
166
|
+
}
|
|
167
|
+
function hasMoreAvailableDates(state) {
|
|
168
|
+
return state.data.hasMore;
|
|
169
|
+
}
|
|
170
|
+
function isLoadingAvailableDates(state) {
|
|
171
|
+
return state.tag === "loading";
|
|
172
|
+
}
|
|
173
|
+
function isRefreshingAvailableDates(state) {
|
|
174
|
+
return state.tag === "refreshing";
|
|
175
|
+
}
|
|
176
|
+
function getAvailableDatesError(state) {
|
|
177
|
+
return state.tag === "error" ? state.message : null;
|
|
178
|
+
}
|
|
179
|
+
function mergeAvailableDates(previous, action) {
|
|
180
|
+
const availableDates = action.append ? new Set(previous.availableDates) : /* @__PURE__ */ new Set();
|
|
181
|
+
for (const date of action.dates) {
|
|
182
|
+
availableDates.add(date);
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
availableDates,
|
|
186
|
+
hasMore: action.hasMore,
|
|
187
|
+
loadedRange: {
|
|
188
|
+
start: action.append && previous.loadedRange ? previous.loadedRange.start : action.startDate,
|
|
189
|
+
end: action.endDate
|
|
190
|
+
},
|
|
191
|
+
nextStartDate: action.nextStartDate
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function availableDatesReducer(state, action) {
|
|
195
|
+
switch (action.type) {
|
|
196
|
+
case "query-cleared":
|
|
197
|
+
return { tag: "idle", data: createEmptyAvailableDatesData() };
|
|
198
|
+
case "load-started":
|
|
199
|
+
return { tag: "loading", data: state.data };
|
|
200
|
+
case "refresh-started":
|
|
201
|
+
return { tag: "refreshing", data: state.data };
|
|
202
|
+
case "load-succeeded":
|
|
203
|
+
return { tag: "loaded", data: mergeAvailableDates(state.data, action) };
|
|
204
|
+
case "load-failed":
|
|
205
|
+
return { tag: "error", data: state.data, message: action.message };
|
|
206
|
+
default:
|
|
207
|
+
return assertNever(action);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
144
211
|
// ../blocks/src/system/runtime/hooks/useAvailableDates.ts
|
|
145
212
|
var AVAILABILITY_REFRESH_INTERVAL_MS = 3e4;
|
|
146
213
|
var AVAILABILITY_REFRESH_JITTER_MS = 5e3;
|
|
@@ -153,25 +220,23 @@ function useAvailableDates({
|
|
|
153
220
|
initialDays = 30
|
|
154
221
|
}) {
|
|
155
222
|
const api = useBlockApi();
|
|
156
|
-
const [
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const [hasMore, setHasMore] = useState(false);
|
|
161
|
-
const [loadedRange, setLoadedRange] = useState(null);
|
|
162
|
-
const nextStartDateRef = useRef(null);
|
|
223
|
+
const [state, dispatch] = useReducer(
|
|
224
|
+
availableDatesReducer,
|
|
225
|
+
createInitialAvailableDatesState()
|
|
226
|
+
);
|
|
163
227
|
const requestIdRef = useRef(0);
|
|
228
|
+
const loadedRange = getAvailableDatesLoadedRange(state);
|
|
229
|
+
const isLoading = isLoadingAvailableDates(state);
|
|
230
|
+
const nextStartDate = getAvailableDatesNextStartDate(state);
|
|
164
231
|
const fetchDates = useCallback(
|
|
165
232
|
async (startDate, endDate, append = false, mode = "load") => {
|
|
166
233
|
if (!serviceId) return;
|
|
167
234
|
const requestId = ++requestIdRef.current;
|
|
168
235
|
if (mode === "refresh") {
|
|
169
|
-
|
|
236
|
+
dispatch({ type: "refresh-started" });
|
|
170
237
|
} else {
|
|
171
|
-
|
|
172
|
-
setIsRefreshing(false);
|
|
238
|
+
dispatch({ type: "load-started" });
|
|
173
239
|
}
|
|
174
|
-
setError(null);
|
|
175
240
|
try {
|
|
176
241
|
const data = await api.getAvailableDates({
|
|
177
242
|
serviceId,
|
|
@@ -181,38 +246,29 @@ function useAvailableDates({
|
|
|
181
246
|
resourceId
|
|
182
247
|
});
|
|
183
248
|
if (requestId !== requestIdRef.current) return;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
data.dates
|
|
187
|
-
|
|
249
|
+
dispatch({
|
|
250
|
+
type: "load-succeeded",
|
|
251
|
+
dates: data.dates,
|
|
252
|
+
hasMore: data.hasMore,
|
|
253
|
+
nextStartDate: data.nextStartDate || null,
|
|
254
|
+
startDate: data.startDate,
|
|
255
|
+
endDate: data.endDate,
|
|
256
|
+
append
|
|
188
257
|
});
|
|
189
|
-
|
|
190
|
-
nextStartDateRef.current = data.nextStartDate || null;
|
|
191
|
-
setLoadedRange((prev) => ({
|
|
192
|
-
start: append && prev ? prev.start : data.startDate,
|
|
193
|
-
end: data.endDate
|
|
194
|
-
}));
|
|
195
|
-
} catch (err) {
|
|
258
|
+
} catch (err2) {
|
|
196
259
|
if (requestId !== requestIdRef.current) return;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (mode === "refresh" && requestId === requestIdRef.current) {
|
|
202
|
-
setIsRefreshing(false);
|
|
203
|
-
} else if (requestId === requestIdRef.current) {
|
|
204
|
-
setIsLoading(false);
|
|
205
|
-
}
|
|
260
|
+
dispatch({
|
|
261
|
+
type: "load-failed",
|
|
262
|
+
message: err2 instanceof Error ? err2.message : "Failed to load available dates"
|
|
263
|
+
});
|
|
206
264
|
}
|
|
207
265
|
},
|
|
208
266
|
[api, serviceId, resourceId, timezone]
|
|
209
267
|
);
|
|
210
268
|
useEffect(() => {
|
|
211
269
|
if (!serviceId) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
setHasMore(false);
|
|
215
|
-
setIsRefreshing(false);
|
|
270
|
+
requestIdRef.current += 1;
|
|
271
|
+
dispatch({ type: "query-cleared" });
|
|
216
272
|
return;
|
|
217
273
|
}
|
|
218
274
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -236,8 +292,8 @@ function useAvailableDates({
|
|
|
236
292
|
}
|
|
237
293
|
});
|
|
238
294
|
const loadMore = useCallback(() => {
|
|
239
|
-
if (!
|
|
240
|
-
const start =
|
|
295
|
+
if (!nextStartDate || isLoading) return;
|
|
296
|
+
const start = nextStartDate;
|
|
241
297
|
const end = formatLocalScheduleDate(
|
|
242
298
|
addLocalScheduleDays(
|
|
243
299
|
parseBookingLocalDate(start),
|
|
@@ -245,17 +301,83 @@ function useAvailableDates({
|
|
|
245
301
|
)
|
|
246
302
|
);
|
|
247
303
|
void fetchDates(start, end, true);
|
|
248
|
-
}, [fetchDates, isLoading]);
|
|
304
|
+
}, [fetchDates, isLoading, nextStartDate]);
|
|
249
305
|
return {
|
|
250
|
-
availableDates,
|
|
306
|
+
availableDates: getAvailableDates(state),
|
|
251
307
|
isLoading,
|
|
252
|
-
isRefreshing,
|
|
253
|
-
error,
|
|
254
|
-
hasMore,
|
|
308
|
+
isRefreshing: isRefreshingAvailableDates(state),
|
|
309
|
+
error: getAvailableDatesError(state),
|
|
310
|
+
hasMore: hasMoreAvailableDates(state),
|
|
255
311
|
loadMore,
|
|
256
312
|
loadedRange
|
|
257
313
|
};
|
|
258
314
|
}
|
|
315
|
+
|
|
316
|
+
// ../blocks/src/system/runtime/hooks/useAvailableSlots.state.ts
|
|
317
|
+
var initialAvailableSlotsState = { tag: "idle" };
|
|
318
|
+
function getAvailableSlots(state) {
|
|
319
|
+
switch (state.tag) {
|
|
320
|
+
case "idle":
|
|
321
|
+
case "loading":
|
|
322
|
+
return [];
|
|
323
|
+
case "loaded":
|
|
324
|
+
case "refreshing":
|
|
325
|
+
case "error":
|
|
326
|
+
return state.slots;
|
|
327
|
+
default:
|
|
328
|
+
return assertNever(state);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function hasLoadedAvailableSlots(state) {
|
|
332
|
+
switch (state.tag) {
|
|
333
|
+
case "idle":
|
|
334
|
+
return false;
|
|
335
|
+
case "loading":
|
|
336
|
+
case "refreshing":
|
|
337
|
+
case "error":
|
|
338
|
+
return state.hasLoaded;
|
|
339
|
+
case "loaded":
|
|
340
|
+
return true;
|
|
341
|
+
default:
|
|
342
|
+
return assertNever(state);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function isLoadingAvailableSlots(state) {
|
|
346
|
+
return state.tag === "loading";
|
|
347
|
+
}
|
|
348
|
+
function isRefreshingAvailableSlots(state) {
|
|
349
|
+
return state.tag === "refreshing";
|
|
350
|
+
}
|
|
351
|
+
function getAvailableSlotsError(state) {
|
|
352
|
+
return state.tag === "error" ? state.message : null;
|
|
353
|
+
}
|
|
354
|
+
function availableSlotsReducer(state, action) {
|
|
355
|
+
switch (action.type) {
|
|
356
|
+
case "query-cleared":
|
|
357
|
+
return { tag: "idle" };
|
|
358
|
+
case "load-started":
|
|
359
|
+
return { tag: "loading", hasLoaded: hasLoadedAvailableSlots(state) };
|
|
360
|
+
case "refresh-started":
|
|
361
|
+
return {
|
|
362
|
+
tag: "refreshing",
|
|
363
|
+
slots: getAvailableSlots(state),
|
|
364
|
+
hasLoaded: hasLoadedAvailableSlots(state)
|
|
365
|
+
};
|
|
366
|
+
case "load-succeeded":
|
|
367
|
+
return { tag: "loaded", slots: action.slots };
|
|
368
|
+
case "load-failed":
|
|
369
|
+
return {
|
|
370
|
+
tag: "error",
|
|
371
|
+
slots: getAvailableSlots(state),
|
|
372
|
+
hasLoaded: hasLoadedAvailableSlots(state),
|
|
373
|
+
message: action.message
|
|
374
|
+
};
|
|
375
|
+
default:
|
|
376
|
+
return assertNever(action);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ../blocks/src/system/runtime/hooks/useAvailableSlots.ts
|
|
259
381
|
var AVAILABILITY_REFRESH_INTERVAL_MS2 = 3e4;
|
|
260
382
|
var AVAILABILITY_REFRESH_JITTER_MS2 = 5e3;
|
|
261
383
|
function useAvailableSlots({
|
|
@@ -267,31 +389,23 @@ function useAvailableSlots({
|
|
|
267
389
|
timezone
|
|
268
390
|
}) {
|
|
269
391
|
const api = useBlockApi();
|
|
270
|
-
const [
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const [error, setError] = useState(null);
|
|
392
|
+
const [state, dispatch] = useReducer(
|
|
393
|
+
availableSlotsReducer,
|
|
394
|
+
initialAvailableSlotsState
|
|
395
|
+
);
|
|
275
396
|
const requestIdRef = useRef(0);
|
|
276
397
|
const fetchSlots = useCallback(
|
|
277
398
|
async (mode) => {
|
|
278
399
|
const requestId = ++requestIdRef.current;
|
|
279
400
|
if (!selectedDate || !serviceId) {
|
|
280
|
-
|
|
281
|
-
setIsLoading(false);
|
|
282
|
-
setIsRefreshing(false);
|
|
283
|
-
setHasLoaded(false);
|
|
284
|
-
setError(null);
|
|
401
|
+
dispatch({ type: "query-cleared" });
|
|
285
402
|
return;
|
|
286
403
|
}
|
|
287
404
|
if (mode === "refresh") {
|
|
288
|
-
|
|
405
|
+
dispatch({ type: "refresh-started" });
|
|
289
406
|
} else {
|
|
290
|
-
|
|
291
|
-
setIsRefreshing(false);
|
|
292
|
-
setSlots([]);
|
|
407
|
+
dispatch({ type: "load-started" });
|
|
293
408
|
}
|
|
294
|
-
setError(null);
|
|
295
409
|
try {
|
|
296
410
|
const result = await api.getAvailableSlots({
|
|
297
411
|
serviceId,
|
|
@@ -301,24 +415,19 @@ function useAvailableSlots({
|
|
|
301
415
|
resourceId
|
|
302
416
|
});
|
|
303
417
|
if (requestId !== requestIdRef.current) return;
|
|
304
|
-
|
|
305
|
-
|
|
418
|
+
dispatch({
|
|
419
|
+
type: "load-succeeded",
|
|
420
|
+
slots: result.slots.map((slot) => ({
|
|
306
421
|
...slot,
|
|
307
422
|
resourceId: unsafeAsAppointmentResourceId(slot.resourceId)
|
|
308
423
|
}))
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
} catch (err) {
|
|
424
|
+
});
|
|
425
|
+
} catch (err2) {
|
|
312
426
|
if (requestId !== requestIdRef.current) return;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (mode === "refresh" && requestId === requestIdRef.current) {
|
|
318
|
-
setIsRefreshing(false);
|
|
319
|
-
} else if (requestId === requestIdRef.current) {
|
|
320
|
-
setIsLoading(false);
|
|
321
|
-
}
|
|
427
|
+
dispatch({
|
|
428
|
+
type: "load-failed",
|
|
429
|
+
message: err2 instanceof Error ? err2.message : "Failed to load available times"
|
|
430
|
+
});
|
|
322
431
|
}
|
|
323
432
|
},
|
|
324
433
|
[selectedDate, serviceId, resourceId, timezone, api]
|
|
@@ -335,7 +444,13 @@ function useAvailableSlots({
|
|
|
335
444
|
jitterMs: AVAILABILITY_REFRESH_JITTER_MS2,
|
|
336
445
|
onPoll: () => fetchSlots("refresh")
|
|
337
446
|
});
|
|
338
|
-
return {
|
|
447
|
+
return {
|
|
448
|
+
slots: getAvailableSlots(state),
|
|
449
|
+
isLoading: isLoadingAvailableSlots(state),
|
|
450
|
+
isRefreshing: isRefreshingAvailableSlots(state),
|
|
451
|
+
hasLoaded: hasLoadedAvailableSlots(state),
|
|
452
|
+
error: getAvailableSlotsError(state)
|
|
453
|
+
};
|
|
339
454
|
}
|
|
340
455
|
|
|
341
456
|
// ../blocks/src/system/runtime/hooks/useBookingSubmission.state.ts
|
|
@@ -364,7 +479,7 @@ function bookingSubmissionReducer(state, action) {
|
|
|
364
479
|
case "feedback-cleared":
|
|
365
480
|
return clearWorkflowFeedback(state);
|
|
366
481
|
default:
|
|
367
|
-
return
|
|
482
|
+
return assertNever(action);
|
|
368
483
|
}
|
|
369
484
|
}
|
|
370
485
|
function selectIsSubmitting(state) {
|
|
@@ -408,7 +523,7 @@ function useBookingSubmission(_siteId) {
|
|
|
408
523
|
type: "submission-succeeded",
|
|
409
524
|
message: response.type === "checkout_redirect" ? "Redirecting to secure checkout..." : "Booking submitted successfully."
|
|
410
525
|
});
|
|
411
|
-
return
|
|
526
|
+
return okWith(response);
|
|
412
527
|
} catch (error) {
|
|
413
528
|
console.error("Booking submission error:", error);
|
|
414
529
|
const message = error instanceof Error ? error.message : "Failed to book appointment";
|
|
@@ -416,7 +531,7 @@ function useBookingSubmission(_siteId) {
|
|
|
416
531
|
type: "submission-failed",
|
|
417
532
|
message
|
|
418
533
|
});
|
|
419
|
-
return
|
|
534
|
+
return err(message);
|
|
420
535
|
}
|
|
421
536
|
};
|
|
422
537
|
return {
|
|
@@ -428,253 +543,6 @@ function useBookingSubmission(_siteId) {
|
|
|
428
543
|
};
|
|
429
544
|
}
|
|
430
545
|
|
|
431
|
-
// ../blocks/src/system/runtime/shared/bookingPaymentOptionCopy.ts
|
|
432
|
-
function buildUpfrontBookingPaymentOptionCopy(formattedTotal) {
|
|
433
|
-
return {
|
|
434
|
-
title: "Pay in full",
|
|
435
|
-
description: "Pay everything today and your booking is confirmed.",
|
|
436
|
-
ctaLabel: `Pay ${formattedTotal} now`
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
function buildDeferredManualBookingPaymentOptionCopy() {
|
|
440
|
-
return {
|
|
441
|
-
title: "Pay offline",
|
|
442
|
-
description: "Book now and pay the business later, outside the platform.",
|
|
443
|
-
helperText: "Nothing is due today.",
|
|
444
|
-
ctaLabel: "Book now"
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
function buildInstalmentBookingPaymentOptionCopy(input) {
|
|
448
|
-
return {
|
|
449
|
-
title: "Payment plan",
|
|
450
|
-
description: describeInstalmentPlanCopy(input),
|
|
451
|
-
helperText: "You can pay the rest early any time in your customer portal.",
|
|
452
|
-
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
function describeInstalmentPlanCopy(input) {
|
|
456
|
-
if (input.depositRefundability) {
|
|
457
|
-
return `Pay ${input.formattedDueToday} today, then continue with scheduled payments. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`;
|
|
458
|
-
}
|
|
459
|
-
if (input.futurePaymentCount === 0) {
|
|
460
|
-
return `Pay ${input.formattedDueToday} today.`;
|
|
461
|
-
}
|
|
462
|
-
if (input.futurePaymentCount === 1) {
|
|
463
|
-
return `Pay ${input.formattedDueToday} today, then one more payment later.`;
|
|
464
|
-
}
|
|
465
|
-
const formattedFirstFuture = input.formattedFirstFuture ?? input.formattedDueToday;
|
|
466
|
-
return `Pay ${input.formattedDueToday} today, then ${input.futurePaymentCount} more ${input.cadenceLabel} payments from ${formattedFirstFuture}.`;
|
|
467
|
-
}
|
|
468
|
-
function buildFlexibleBalanceBookingPaymentOptionCopy(input) {
|
|
469
|
-
return {
|
|
470
|
-
title: "Deposit now, pay the rest later",
|
|
471
|
-
description: `Pay ${input.formattedDueToday} today, then pay the remaining balance any time before ${input.dueDateLabel}. Your deposit is ${formatDepositRefundabilityLabel(input.depositRefundability)}.`,
|
|
472
|
-
helperText: "You can return in your customer portal to pay the rest before the due date.",
|
|
473
|
-
ctaLabel: `Pay ${input.formattedDueToday} now`
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
function formatDepositRefundabilityLabel(depositRefundability) {
|
|
477
|
-
return depositRefundability === "non_refundable" ? "non-refundable" : "refundable";
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// ../blocks/src/system/runtime/shared/bookingPaymentOptions.ts
|
|
481
|
-
function buildBookingPaymentSelectionViewModel(input) {
|
|
482
|
-
const currency = input.priceCurrency ?? "USD";
|
|
483
|
-
const totalCents = Math.max(0, input.priceAmount ?? 0);
|
|
484
|
-
const allowedOptions = input.paymentTerms?.allowedOptions ?? [{ kind: "upfront" }];
|
|
485
|
-
const mode = allowedOptions.length > 1 ? "choice_required" : "single_option";
|
|
486
|
-
return {
|
|
487
|
-
mode,
|
|
488
|
-
sectionTitle: mode === "choice_required" ? "Choose how you'd like to pay" : "Payment",
|
|
489
|
-
serviceTitle: input.serviceTitle,
|
|
490
|
-
options: allowedOptions.map((option) => buildBookingPaymentOptionViewModel({
|
|
491
|
-
option,
|
|
492
|
-
totalCents,
|
|
493
|
-
currency,
|
|
494
|
-
bookingStartAt: input.bookingStartAt,
|
|
495
|
-
locale: input.locale
|
|
496
|
-
}))
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
function buildBookingPaymentOptionViewModel(input) {
|
|
500
|
-
switch (input.option.kind) {
|
|
501
|
-
case "upfront": {
|
|
502
|
-
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
503
|
-
const copy = buildUpfrontBookingPaymentOptionCopy(formattedTotal);
|
|
504
|
-
return {
|
|
505
|
-
kind: "upfront",
|
|
506
|
-
title: copy.title,
|
|
507
|
-
description: copy.description,
|
|
508
|
-
summaryRows: [
|
|
509
|
-
{ label: "Total", value: formattedTotal },
|
|
510
|
-
{ label: "Due today", value: formattedTotal }
|
|
511
|
-
],
|
|
512
|
-
ctaLabel: copy.ctaLabel
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
case "deferred_manual": {
|
|
516
|
-
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
517
|
-
const copy = buildDeferredManualBookingPaymentOptionCopy();
|
|
518
|
-
return {
|
|
519
|
-
kind: "deferred_manual",
|
|
520
|
-
title: copy.title,
|
|
521
|
-
description: copy.description,
|
|
522
|
-
summaryRows: [
|
|
523
|
-
{ label: "Total", value: formattedTotal },
|
|
524
|
-
{ label: "Due today", value: formatPrice(0, input.currency, input.locale) }
|
|
525
|
-
],
|
|
526
|
-
helperText: copy.helperText,
|
|
527
|
-
ctaLabel: copy.ctaLabel
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
case "instalment_plan": {
|
|
531
|
-
const schedulePreview = buildInstalmentSchedulePreview({
|
|
532
|
-
totalCents: input.totalCents,
|
|
533
|
-
option: input.option,
|
|
534
|
-
bookingStartAt: input.bookingStartAt
|
|
535
|
-
});
|
|
536
|
-
const dueToday = schedulePreview[0]?.amountCents ?? input.totalCents;
|
|
537
|
-
const futureRows = schedulePreview.slice(1);
|
|
538
|
-
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
539
|
-
const formattedDueToday = formatPrice(dueToday, input.currency, input.locale);
|
|
540
|
-
const depositRefundability = getBookingInstalmentDepositRefundability(input.option.plan);
|
|
541
|
-
const copy = buildInstalmentBookingPaymentOptionCopy({
|
|
542
|
-
formattedDueToday,
|
|
543
|
-
futurePaymentCount: futureRows.length,
|
|
544
|
-
formattedFirstFuture: futureRows[0] ? formatPrice(futureRows[0].amountCents, input.currency, input.locale) : null,
|
|
545
|
-
cadenceLabel: getPaymentCadenceLabel(input.option.plan),
|
|
546
|
-
depositRefundability
|
|
547
|
-
});
|
|
548
|
-
return {
|
|
549
|
-
kind: "instalment_plan",
|
|
550
|
-
title: copy.title,
|
|
551
|
-
description: copy.description,
|
|
552
|
-
summaryRows: [
|
|
553
|
-
{ label: "Total", value: formattedTotal },
|
|
554
|
-
{ label: "Due today", value: formattedDueToday },
|
|
555
|
-
...depositRefundability ? [{
|
|
556
|
-
label: "Deposit policy",
|
|
557
|
-
value: depositRefundability === "non_refundable" ? "Non-refundable" : "Refundable"
|
|
558
|
-
}] : [],
|
|
559
|
-
...futureRows.map((row) => ({
|
|
560
|
-
label: formatScheduleDate(row.dueAt, input.locale),
|
|
561
|
-
value: formatPrice(row.amountCents, input.currency, input.locale)
|
|
562
|
-
}))
|
|
563
|
-
],
|
|
564
|
-
helperText: copy.helperText,
|
|
565
|
-
ctaLabel: copy.ctaLabel
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
case "flexible_balance": {
|
|
569
|
-
const dueToday = resolveFlexibleBalanceInitialPaymentCents({
|
|
570
|
-
totalAmountCents: input.totalCents,
|
|
571
|
-
config: input.option.config
|
|
572
|
-
});
|
|
573
|
-
const formattedTotal = formatPrice(input.totalCents, input.currency, input.locale);
|
|
574
|
-
const formattedDueToday = formatPrice(dueToday, input.currency, input.locale);
|
|
575
|
-
const dueAt = resolveFlexibleBalanceDueAt({
|
|
576
|
-
bookingStartAt: input.bookingStartAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
577
|
-
dueDateRule: input.option.config.dueDateRule
|
|
578
|
-
});
|
|
579
|
-
const copy = buildFlexibleBalanceBookingPaymentOptionCopy({
|
|
580
|
-
formattedDueToday,
|
|
581
|
-
dueDateLabel: formatScheduleDate(dueAt, input.locale),
|
|
582
|
-
depositRefundability: input.option.config.depositRefundability
|
|
583
|
-
});
|
|
584
|
-
return {
|
|
585
|
-
kind: "flexible_balance",
|
|
586
|
-
title: copy.title,
|
|
587
|
-
description: copy.description,
|
|
588
|
-
summaryRows: [
|
|
589
|
-
{ label: "Total", value: formattedTotal },
|
|
590
|
-
{ label: "Due today", value: formattedDueToday },
|
|
591
|
-
{ label: "Balance due by", value: formatScheduleDate(dueAt, input.locale) },
|
|
592
|
-
{
|
|
593
|
-
label: "Deposit policy",
|
|
594
|
-
value: input.option.config.depositRefundability === "non_refundable" ? "Non-refundable" : "Refundable"
|
|
595
|
-
}
|
|
596
|
-
],
|
|
597
|
-
helperText: copy.helperText,
|
|
598
|
-
ctaLabel: copy.ctaLabel
|
|
599
|
-
};
|
|
600
|
-
}
|
|
601
|
-
default:
|
|
602
|
-
return assertNever11(input.option);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
function buildInstalmentSchedulePreview(input) {
|
|
606
|
-
const startAt = input.bookingStartAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
607
|
-
switch (input.option.plan.kind) {
|
|
608
|
-
case "deposit_plus_one_remainder": {
|
|
609
|
-
const deposit = clampConfiguredAmount(input.option.plan.depositAmountCents, input.totalCents);
|
|
610
|
-
const remainder = Math.max(0, input.totalCents - deposit);
|
|
611
|
-
return compactSchedulePreview([
|
|
612
|
-
{ dueAt: startAt, amountCents: deposit },
|
|
613
|
-
{
|
|
614
|
-
dueAt: addIntervalPreservingMonthAnchor(
|
|
615
|
-
startAt,
|
|
616
|
-
input.option.plan.remainderDueCount,
|
|
617
|
-
input.option.plan.intervalUnit
|
|
618
|
-
),
|
|
619
|
-
amountCents: remainder
|
|
620
|
-
}
|
|
621
|
-
]);
|
|
622
|
-
}
|
|
623
|
-
case "deposit_plus_scheduled_instalments": {
|
|
624
|
-
const plan = input.option.plan;
|
|
625
|
-
const deposit = clampConfiguredAmount(plan.depositAmountCents, input.totalCents);
|
|
626
|
-
const remaining = Math.max(0, input.totalCents - deposit);
|
|
627
|
-
const instalments = splitAmountWithRemainderInFirst(
|
|
628
|
-
remaining,
|
|
629
|
-
plan.instalmentCount
|
|
630
|
-
);
|
|
631
|
-
return compactSchedulePreview([
|
|
632
|
-
{ dueAt: startAt, amountCents: deposit },
|
|
633
|
-
...instalments.map((amountCents, index) => ({
|
|
634
|
-
dueAt: addIntervalPreservingMonthAnchor(
|
|
635
|
-
startAt,
|
|
636
|
-
plan.intervalCount * (index + 1),
|
|
637
|
-
plan.intervalUnit
|
|
638
|
-
),
|
|
639
|
-
amountCents
|
|
640
|
-
}))
|
|
641
|
-
]);
|
|
642
|
-
}
|
|
643
|
-
case "equal_scheduled_instalments": {
|
|
644
|
-
const plan = input.option.plan;
|
|
645
|
-
const instalments = splitAmountWithRemainderInFirst(
|
|
646
|
-
input.totalCents,
|
|
647
|
-
plan.instalmentCount
|
|
648
|
-
);
|
|
649
|
-
return compactSchedulePreview(instalments.map((amountCents, index) => ({
|
|
650
|
-
dueAt: index === 0 ? startAt : addIntervalPreservingMonthAnchor(
|
|
651
|
-
startAt,
|
|
652
|
-
plan.intervalCount * index,
|
|
653
|
-
plan.intervalUnit
|
|
654
|
-
),
|
|
655
|
-
amountCents
|
|
656
|
-
})));
|
|
657
|
-
}
|
|
658
|
-
default:
|
|
659
|
-
return assertNever11(input.option.plan);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
function getPaymentCadenceLabel(plan) {
|
|
663
|
-
const intervalCount = getBookingInstalmentPlanIntervalCount(plan);
|
|
664
|
-
const unitLabel = intervalCount === 1 ? plan.intervalUnit : `${plan.intervalUnit}s`;
|
|
665
|
-
return intervalCount === 1 ? unitLabel : `every ${intervalCount} ${unitLabel}`;
|
|
666
|
-
}
|
|
667
|
-
function compactSchedulePreview(schedule) {
|
|
668
|
-
return omitZeroAmountFutureRows(schedule);
|
|
669
|
-
}
|
|
670
|
-
function formatScheduleDate(isoString, locale) {
|
|
671
|
-
const date = new Date(isoString);
|
|
672
|
-
if (!Number.isFinite(date.getTime())) {
|
|
673
|
-
return isoString;
|
|
674
|
-
}
|
|
675
|
-
return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(date);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
546
|
// ../blocks/src/system/runtime/nodes/booking-form.headless.state.ts
|
|
679
547
|
var unsafeAsBookingFieldId = (id) => id;
|
|
680
548
|
function createEmptyBookingValidationErrors() {
|
|
@@ -880,7 +748,7 @@ function bookingFlowReducer(state, event) {
|
|
|
880
748
|
case "reset":
|
|
881
749
|
return event.initial;
|
|
882
750
|
default:
|
|
883
|
-
return
|
|
751
|
+
return assertNever(event);
|
|
884
752
|
}
|
|
885
753
|
}
|
|
886
754
|
function clearAvailabilityFeedback(feedback) {
|
|
@@ -1009,7 +877,7 @@ function validateBookingStep(input) {
|
|
|
1009
877
|
return Object.keys(errors).length > 0 ? { ok: false, errors: createFieldBookingValidationErrors(errors) } : { ok: true };
|
|
1010
878
|
}
|
|
1011
879
|
default:
|
|
1012
|
-
return
|
|
880
|
+
return assertNever(input.stepId);
|
|
1013
881
|
}
|
|
1014
882
|
}
|
|
1015
883
|
function validateBookingFields(input) {
|
|
@@ -1301,7 +1169,7 @@ function resolveAppointmentPackagesModel(input) {
|
|
|
1301
1169
|
};
|
|
1302
1170
|
}
|
|
1303
1171
|
default:
|
|
1304
|
-
return
|
|
1172
|
+
return assertNever(input.state);
|
|
1305
1173
|
}
|
|
1306
1174
|
}
|
|
1307
1175
|
function toHeadlessEligibleAppointmentPackage(appointmentPackage) {
|
|
@@ -1625,7 +1493,10 @@ function useHeadlessBookingFlow(options) {
|
|
|
1625
1493
|
state.selectedDate,
|
|
1626
1494
|
state.selectedSlot
|
|
1627
1495
|
]);
|
|
1628
|
-
const appointmentDiscountContext =
|
|
1496
|
+
const appointmentDiscountContext = useMemo(
|
|
1497
|
+
() => selectedService && (selectedService.priceAmount ?? 0) > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
1498
|
+
[selectedService?.id, selectedService?.priceAmount]
|
|
1499
|
+
);
|
|
1629
1500
|
const discountUi = useDiscountCodeUi({
|
|
1630
1501
|
api,
|
|
1631
1502
|
discountContext: appointmentDiscountContext,
|
|
@@ -2211,7 +2082,7 @@ function DefaultBookingStepContent({
|
|
|
2211
2082
|
case "custom-fields":
|
|
2212
2083
|
return /* @__PURE__ */ jsx(DefaultDynamicFields, { fields: booking.fields.items, booking });
|
|
2213
2084
|
default:
|
|
2214
|
-
return
|
|
2085
|
+
return assertNever(stepId);
|
|
2215
2086
|
}
|
|
2216
2087
|
}
|
|
2217
2088
|
function DefaultServiceSelectionStep({
|