@riverbankcms/sdk 0.91.0 → 0.93.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/dist/{PreviewEditorSidebar-3TT47WCF.mjs → PreviewEditorSidebar-D3PAF7NW.mjs} +3 -3
- package/dist/{PreviewEditorUI-ORCLLUNZ.mjs → PreviewEditorUI-G5JVJEIJ.mjs} +3 -3
- package/dist/SdkPreviewModeRuntime-NHTLRNQD.mjs +8 -0
- package/dist/_dts/api/src/bookingConfig.d.ts +13 -1
- package/dist/_dts/api/src/bookingOperations.d.ts +1 -0
- package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
- package/dist/_dts/api/src/common/envelope.d.ts +10 -0
- package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
- package/dist/_dts/api/src/index.d.ts +2 -2
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +6 -0
- package/dist/_dts/api/src/request.d.ts +1 -1
- package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +32 -0
- package/dist/_dts/blocks/src/system/blocks/courses/shared/pricing.d.ts +12 -1
- package/dist/_dts/blocks/src/system/blocks/courses/shared/schemas.d.ts +12 -0
- package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +4 -1
- package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +44 -0
- package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +8 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.d.ts +8 -1
- package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.d.ts +1 -0
- 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 +40 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.reserved-fields.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.state.d.ts +29 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/components.d.ts +6 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +8 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +1 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +9 -0
- package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +14 -14
- package/dist/_dts/content-editor/src/controller/useEntrySyncHelpers.d.ts +1 -1
- package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +5 -15
- package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +46 -0
- package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +43 -36
- package/dist/_dts/content-model/src/entry-slots/types.d.ts +110 -2
- package/dist/_dts/core/src/branded.d.ts +3 -0
- package/dist/_dts/core/src/event-pricing.d.ts +18 -1
- package/dist/_dts/core/src/money-input.d.ts +34 -4
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +70 -0
- package/dist/_dts/media-core/src/fileAssetCompatibility.d.ts +1 -1
- package/dist/_dts/media-core/src/filePersistence.d.ts +5 -1
- package/dist/_dts/media-core/src/fileStorage.d.ts +1 -0
- package/dist/_dts/media-core/src/fileUploadFinalization.d.ts +29 -1
- package/dist/_dts/media-core/src/index.d.ts +1 -0
- package/dist/_dts/media-core/src/legacyMediaValue.d.ts +11 -0
- package/dist/_dts/media-core/src/videoPrep.d.ts +15 -6
- package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +5 -5
- package/dist/_dts/media-react/src/hooks/useApiMediaUploader.d.ts +2 -1
- package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +2 -0
- package/dist/_dts/sdk/src/cli/commands/push/execute/localMediaReporting.d.ts +23 -0
- package/dist/_dts/sdk/src/cli/commands/push/scopes/commandBackedDatedOfferingScope.d.ts +54 -0
- package/dist/_dts/sdk/src/cli/commands/push/scopes/mediaPrep.d.ts +7 -2
- package/dist/_dts/sdk/src/cli/commands/push/scopes/types.d.ts +6 -0
- package/dist/_dts/sdk/src/cli/media/local-sync.d.ts +35 -0
- package/dist/_dts/sdk/src/rendering/islands/types.d.ts +23 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/{chunk-GDT2QGIL.mjs → chunk-A63UXN3P.mjs} +21 -19
- package/dist/{chunk-U5YM4AWE.mjs → chunk-AJZGT6YG.mjs} +1 -1
- package/dist/{chunk-AFPMCLS7.mjs → chunk-AQ6RT6LZ.mjs} +2 -2
- package/dist/{chunk-ZA2S7H34.mjs → chunk-NT76QGIJ.mjs} +98 -1
- package/dist/{chunk-RQUZYSES.mjs → chunk-PCNCETBI.mjs} +1196 -426
- package/dist/{chunk-S3YHJWEU.mjs → chunk-XIK2HYI3.mjs} +7 -7
- package/dist/cli/index.mjs +749 -166
- package/dist/client/{accordion-AFX37652.mjs → accordion-RNQIPG55.mjs} +2 -2
- package/dist/client/{bookingForm-32V5QCOW.mjs → bookingForm-HYEEVRLP.mjs} +89 -14
- package/dist/client/bookings.mjs +243 -17
- package/dist/client/{carousel-TJGQJ7ER.mjs → carousel-W7DQ3YPU.mjs} +3 -3
- package/dist/client/{cart-JUU2JEW4.mjs → cart-PXJ3SXXO.mjs} +7 -7
- package/dist/client/{checkout-RD6BTFX4.mjs → checkout-X3JYSOXI.mjs} +7 -7
- package/dist/client/{chunk-MLBNVN4H.mjs → chunk-6SYGVVWA.mjs} +67 -4
- package/dist/client/{chunk-E6VIWZUG.mjs → chunk-DUOHLWLF.mjs} +3 -3
- package/dist/client/{chunk-6QZIBNGV.mjs → chunk-IXDSXF2D.mjs} +154 -16
- package/dist/client/{chunk-CKXEUWWA.mjs → chunk-J6TMMMXW.mjs} +3 -3
- package/dist/client/{chunk-PMNAV6LO.mjs → chunk-JNE6UI6U.mjs} +7 -6
- package/dist/client/{chunk-ISAUXU5R.mjs → chunk-OLAOAZEO.mjs} +1 -1
- package/dist/client/{chunk-RWYFG625.mjs → chunk-PCHACQEB.mjs} +30 -2
- package/dist/client/{chunk-FMZZHAIR.mjs → chunk-PICR3NTQ.mjs} +52 -5
- package/dist/client/{chunk-6RN62XBV.mjs → chunk-Q47XGAGS.mjs} +1 -1
- package/dist/client/{chunk-WHZQDPBZ.mjs → chunk-TNGL2WJF.mjs} +1 -0
- package/dist/client/{chunk-C4LP6BPG.mjs → chunk-WERRJXNJ.mjs} +1 -1
- package/dist/client/{chunk-RMOFBBNA.mjs → chunk-YYVGSYBO.mjs} +6 -6
- package/dist/client/client.mjs +641 -54
- package/dist/client/{courseRegistration-X63QAIVV.mjs → courseRegistration-QZ67PVHO.mjs} +111 -11
- package/dist/client/{eventCalendar-5T24GCZL.mjs → eventCalendar-V3BDHQNT.mjs} +9 -9
- package/dist/client/{eventCombined-AZVTF22X.mjs → eventCombined-XYFRN2RG.mjs} +9 -9
- package/dist/client/{eventDetails-7GPFNLGF.mjs → eventDetails-TFE5TWKV.mjs} +9 -9
- package/dist/client/{eventListing-QEUMTMUM.mjs → eventListing-IQ6AGWZ6.mjs} +9 -9
- package/dist/client/{eventRegistration-P2EDKCQZ.mjs → eventRegistration-WGJVFKQJ.mjs} +9 -9
- package/dist/client/{form-NUJ7H4IN.mjs → form-6UZY6RUA.mjs} +3 -3
- package/dist/client/{headerSection-JB7LECPL.mjs → headerSection-RSFXY6V3.mjs} +3 -3
- package/dist/client/hooks.mjs +57 -5
- package/dist/client/{locationMap-UEYWUCSW.mjs → locationMap-24FH67I4.mjs} +3 -3
- package/dist/client/{newsletterForm-S2YZQ2X7.mjs → newsletterForm-QVL3MLTN.mjs} +3 -3
- package/dist/client/{productDetail-H5MADGG7.mjs → productDetail-ZDYN3G4T.mjs} +7 -7
- package/dist/client/{productList-DK7YON7H.mjs → productList-4BMJLQHZ.mjs} +7 -7
- package/dist/client/rendering/client.mjs +503 -36
- package/dist/client/rendering/islands.mjs +19 -19
- package/dist/client/rendering.mjs +583 -39
- package/dist/client/{shop-6PA7RDRJ.mjs → shop-U5C634FF.mjs} +7 -7
- package/dist/preview-next/client/runtime.mjs +5 -5
- package/dist/{sdk-runtime-JP5347OB.mjs → sdk-runtime-VGV46WVB.mjs} +6 -6
- package/dist/server/components.mjs +287 -68
- package/dist/server/config-validation.mjs +58 -5
- package/dist/server/config.mjs +58 -5
- package/dist/server/data.mjs +57 -5
- package/dist/server/index.mjs +104 -29
- package/dist/server/next.mjs +347 -85
- package/dist/server/page-converter.mjs +22 -5
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +287 -68
- package/dist/server/rendering.mjs +287 -68
- package/dist/server/routing.mjs +131 -67
- package/dist/server/server.mjs +189 -94
- package/package.json +1 -1
- package/dist/SdkPreviewModeRuntime-GMCDQPZZ.mjs +0 -8
|
@@ -826,6 +826,7 @@ function createBlockApi(config) {
|
|
|
826
826
|
body: {
|
|
827
827
|
courseId: data.courseId,
|
|
828
828
|
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
829
|
+
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
829
830
|
email: data.email,
|
|
830
831
|
name: data.name,
|
|
831
832
|
phone: data.phone,
|
|
@@ -2986,12 +2987,13 @@ var init_result = __esm({
|
|
|
2986
2987
|
});
|
|
2987
2988
|
|
|
2988
2989
|
// ../core/src/branded.ts
|
|
2989
|
-
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
2990
|
+
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
2990
2991
|
var init_branded = __esm({
|
|
2991
2992
|
"../core/src/branded.ts"() {
|
|
2992
2993
|
"use strict";
|
|
2993
2994
|
unsafeAsMediaAssetId = (id) => id;
|
|
2994
2995
|
unsafeAsStorageBucketName = (value) => value;
|
|
2996
|
+
unsafeAsStoragePath = (value) => value;
|
|
2995
2997
|
unsafeAsPositiveByteCount = (value) => value;
|
|
2996
2998
|
unsafeAsPositiveSeconds = (value) => value;
|
|
2997
2999
|
unsafeAsFormId = (id) => id;
|
|
@@ -3137,6 +3139,7 @@ function publicEventPricingType(pricing) {
|
|
|
3137
3139
|
return "free";
|
|
3138
3140
|
case "single_paid":
|
|
3139
3141
|
case "ticket_types":
|
|
3142
|
+
case "sliding_scale":
|
|
3140
3143
|
case "course":
|
|
3141
3144
|
return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
|
|
3142
3145
|
case "external":
|
|
@@ -3149,6 +3152,7 @@ function publicEventPricingCurrency(pricing) {
|
|
|
3149
3152
|
case "free_registration":
|
|
3150
3153
|
case "single_paid":
|
|
3151
3154
|
case "ticket_types":
|
|
3155
|
+
case "sliding_scale":
|
|
3152
3156
|
return pricing.currency;
|
|
3153
3157
|
case "course":
|
|
3154
3158
|
return pricing.display.display.currency;
|
|
@@ -3166,6 +3170,8 @@ function publicEventPricingMode(pricing) {
|
|
|
3166
3170
|
return "single";
|
|
3167
3171
|
case "ticket_types":
|
|
3168
3172
|
return "ticket_types";
|
|
3173
|
+
case "sliding_scale":
|
|
3174
|
+
return "sliding_scale";
|
|
3169
3175
|
case "drop_in":
|
|
3170
3176
|
case "course":
|
|
3171
3177
|
case "external":
|
|
@@ -3199,6 +3205,8 @@ function formatCoursePriceDisplayLabel(display, options) {
|
|
|
3199
3205
|
return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
3200
3206
|
case "from":
|
|
3201
3207
|
return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
3208
|
+
case "range":
|
|
3209
|
+
return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
|
|
3202
3210
|
default:
|
|
3203
3211
|
return assertNever2(display);
|
|
3204
3212
|
}
|
|
@@ -3950,9 +3958,20 @@ var init_types5 = __esm({
|
|
|
3950
3958
|
});
|
|
3951
3959
|
|
|
3952
3960
|
// ../media-core/src/fileSafety.ts
|
|
3961
|
+
function containsUnsafePathSegmentCharacter(value) {
|
|
3962
|
+
return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
|
|
3963
|
+
}
|
|
3964
|
+
function isReservedPathSegment(value) {
|
|
3965
|
+
return value === "." || value === "..";
|
|
3966
|
+
}
|
|
3967
|
+
function isUnsafePathSegment(segment) {
|
|
3968
|
+
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
3969
|
+
}
|
|
3970
|
+
var CONTROL_CHARACTER_PATTERN;
|
|
3953
3971
|
var init_fileSafety = __esm({
|
|
3954
3972
|
"../media-core/src/fileSafety.ts"() {
|
|
3955
3973
|
"use strict";
|
|
3974
|
+
CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
3956
3975
|
}
|
|
3957
3976
|
});
|
|
3958
3977
|
|
|
@@ -3992,11 +4011,21 @@ var init_fileDomain = __esm({
|
|
|
3992
4011
|
});
|
|
3993
4012
|
|
|
3994
4013
|
// ../media-core/src/fileStorage.ts
|
|
4014
|
+
function parseStoragePath(value) {
|
|
4015
|
+
return joinStoragePathSegments(value.split("/"));
|
|
4016
|
+
}
|
|
4017
|
+
function joinStoragePathSegments(segments) {
|
|
4018
|
+
if (segments.some(isUnsafePathSegment)) {
|
|
4019
|
+
return err("unsafe-path-segment");
|
|
4020
|
+
}
|
|
4021
|
+
return ok(unsafeAsStoragePath(segments.join("/")));
|
|
4022
|
+
}
|
|
3995
4023
|
var FILE_STORAGE_BUCKETS, PUBLIC_SITE_FILE_STORAGE_BUCKETS, PRIVATE_SITE_FILE_BUCKET_MIME_TYPES, TEMP_UPLOAD_BUCKET_MIME_TYPES;
|
|
3996
4024
|
var init_fileStorage = __esm({
|
|
3997
4025
|
"../media-core/src/fileStorage.ts"() {
|
|
3998
4026
|
"use strict";
|
|
3999
4027
|
init_src();
|
|
4028
|
+
init_fileSafety();
|
|
4000
4029
|
FILE_STORAGE_BUCKETS = {
|
|
4001
4030
|
publicSite: unsafeAsStorageBucketName("media"),
|
|
4002
4031
|
privateSite: unsafeAsStorageBucketName("site-files-private"),
|
|
@@ -4182,14 +4211,18 @@ var init_uploadVerificationContract = __esm({
|
|
|
4182
4211
|
});
|
|
4183
4212
|
|
|
4184
4213
|
// ../media-core/src/videoPrep.ts
|
|
4214
|
+
function unsafeAsPositiveVideoDurationSeconds(value) {
|
|
4215
|
+
return value;
|
|
4216
|
+
}
|
|
4185
4217
|
var VIDEO_PREP_LIMITS;
|
|
4186
4218
|
var init_videoPrep = __esm({
|
|
4187
4219
|
"../media-core/src/videoPrep.ts"() {
|
|
4188
4220
|
"use strict";
|
|
4221
|
+
init_src();
|
|
4189
4222
|
VIDEO_PREP_LIMITS = {
|
|
4190
|
-
maxRawByteCount: 500 * 1024 * 1024,
|
|
4191
|
-
inlineContentMaxDurationSeconds: 60,
|
|
4192
|
-
backgroundVideoMaxDurationSeconds: 30,
|
|
4223
|
+
maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
|
|
4224
|
+
inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
|
|
4225
|
+
backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
|
|
4193
4226
|
targetMaxDimensionPixels: 1080
|
|
4194
4227
|
};
|
|
4195
4228
|
}
|
|
@@ -4260,10 +4293,10 @@ var init_identifiers = __esm({
|
|
|
4260
4293
|
|
|
4261
4294
|
// ../media-core/src/url.ts
|
|
4262
4295
|
function isRelativeDirectImageStoragePath(storagePath) {
|
|
4263
|
-
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
|
|
4296
|
+
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
|
|
4264
4297
|
}
|
|
4265
4298
|
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
4266
|
-
return storagePath.startsWith("sites/");
|
|
4299
|
+
return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
|
|
4267
4300
|
}
|
|
4268
4301
|
function encodeStoragePath(storagePath) {
|
|
4269
4302
|
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
@@ -4344,6 +4377,7 @@ var DEFAULT_BASE_PATH, RELATIVE_STORAGE_PATH_PREFIXES, formatNumber, ORDER, getI
|
|
|
4344
4377
|
var init_url = __esm({
|
|
4345
4378
|
"../media-core/src/url.ts"() {
|
|
4346
4379
|
"use strict";
|
|
4380
|
+
init_fileStorage();
|
|
4347
4381
|
DEFAULT_BASE_PATH = "/api/img";
|
|
4348
4382
|
RELATIVE_STORAGE_PATH_PREFIXES = [
|
|
4349
4383
|
"originals/",
|
|
@@ -4587,6 +4621,13 @@ var init_renderableMediaAsset = __esm({
|
|
|
4587
4621
|
}
|
|
4588
4622
|
});
|
|
4589
4623
|
|
|
4624
|
+
// ../media-core/src/legacyMediaValue.ts
|
|
4625
|
+
var init_legacyMediaValue = __esm({
|
|
4626
|
+
"../media-core/src/legacyMediaValue.ts"() {
|
|
4627
|
+
"use strict";
|
|
4628
|
+
}
|
|
4629
|
+
});
|
|
4630
|
+
|
|
4590
4631
|
// ../media-core/src/index.ts
|
|
4591
4632
|
var init_src2 = __esm({
|
|
4592
4633
|
"../media-core/src/index.ts"() {
|
|
@@ -4629,6 +4670,7 @@ var init_src2 = __esm({
|
|
|
4629
4670
|
init_mediaUsageProjection();
|
|
4630
4671
|
init_portableMediaReferences();
|
|
4631
4672
|
init_renderableMediaAsset();
|
|
4673
|
+
init_legacyMediaValue();
|
|
4632
4674
|
}
|
|
4633
4675
|
});
|
|
4634
4676
|
|
|
@@ -7098,6 +7140,7 @@ var init_booking_form_reserved_fields = __esm({
|
|
|
7098
7140
|
"selectedDate",
|
|
7099
7141
|
"selectedSlot",
|
|
7100
7142
|
"discountCode",
|
|
7143
|
+
"selectedSlidingAmountInput",
|
|
7101
7144
|
"selectedCollectionOptionKind",
|
|
7102
7145
|
"selectedAppointmentPackageId"
|
|
7103
7146
|
];
|
|
@@ -7383,6 +7426,32 @@ function readOptionalString(value) {
|
|
|
7383
7426
|
function readOptionalNumber(value) {
|
|
7384
7427
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7385
7428
|
}
|
|
7429
|
+
function getBookingServiceSlidingScale(service) {
|
|
7430
|
+
const pricing = service?.pricing;
|
|
7431
|
+
if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
|
|
7432
|
+
return null;
|
|
7433
|
+
}
|
|
7434
|
+
return {
|
|
7435
|
+
minAmount: pricing.slidingMinAmount,
|
|
7436
|
+
maxAmount: pricing.slidingMaxAmount,
|
|
7437
|
+
suggestedAmount: pricing.slidingSuggestedAmount ?? null,
|
|
7438
|
+
currency: pricing.currency
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
function parseBookingCurrencyInputToCents(value) {
|
|
7442
|
+
const trimmed = value?.trim() ?? "";
|
|
7443
|
+
if (!trimmed) return null;
|
|
7444
|
+
if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
|
|
7445
|
+
const parsed = Number(trimmed);
|
|
7446
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
7447
|
+
return Math.round(parsed * 100);
|
|
7448
|
+
}
|
|
7449
|
+
function formatBookingCentsAsCurrencyInput(amount) {
|
|
7450
|
+
return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
|
|
7451
|
+
}
|
|
7452
|
+
function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
|
|
7453
|
+
return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
|
|
7454
|
+
}
|
|
7386
7455
|
function readStringArray(value) {
|
|
7387
7456
|
if (!Array.isArray(value)) return void 0;
|
|
7388
7457
|
const strings = value.filter((item) => typeof item === "string");
|
|
@@ -7571,6 +7640,20 @@ function prepareBookingSubmission(input) {
|
|
|
7571
7640
|
};
|
|
7572
7641
|
}
|
|
7573
7642
|
const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
|
|
7643
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
7644
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
7645
|
+
input.data.selectedSlidingAmountInput
|
|
7646
|
+
);
|
|
7647
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
|
|
7648
|
+
return {
|
|
7649
|
+
ok: false,
|
|
7650
|
+
error: {
|
|
7651
|
+
tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
|
|
7652
|
+
serviceId,
|
|
7653
|
+
serviceTitle: selectedService.title || serviceId
|
|
7654
|
+
}
|
|
7655
|
+
};
|
|
7656
|
+
}
|
|
7574
7657
|
if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
|
|
7575
7658
|
return {
|
|
7576
7659
|
ok: false,
|
|
@@ -7598,6 +7681,7 @@ function prepareBookingSubmission(input) {
|
|
|
7598
7681
|
...common,
|
|
7599
7682
|
kind: "standard",
|
|
7600
7683
|
...discountCode ? { discountCode } : {},
|
|
7684
|
+
...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
|
|
7601
7685
|
...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
|
|
7602
7686
|
altchaSolution: input.altchaSolution ?? null
|
|
7603
7687
|
}
|
|
@@ -7611,6 +7695,10 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
7611
7695
|
return `Service not found: ${error.serviceId}`;
|
|
7612
7696
|
case "payment-option-required":
|
|
7613
7697
|
return `Please choose how you want to pay for "${error.serviceTitle}".`;
|
|
7698
|
+
case "sliding-amount-required":
|
|
7699
|
+
return `Please choose an amount for "${error.serviceTitle}".`;
|
|
7700
|
+
case "sliding-amount-out-of-range":
|
|
7701
|
+
return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
7614
7702
|
case "payment-option-unsupported":
|
|
7615
7703
|
return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
7616
7704
|
case "service-missing-duration":
|
|
@@ -7831,6 +7919,7 @@ var init_booking_form_interactive = __esm({
|
|
|
7831
7919
|
title: z10.string(),
|
|
7832
7920
|
description: z10.string().nullable().optional().transform((value) => value ?? void 0),
|
|
7833
7921
|
durationMinutes: z10.number().optional(),
|
|
7922
|
+
pricing: z10.custom().optional(),
|
|
7834
7923
|
priceAmount: z10.number().nullable().optional(),
|
|
7835
7924
|
priceCurrency: z10.string().nullable().optional(),
|
|
7836
7925
|
paymentTerms: blockBookingPaymentTermsSchema.optional(),
|
|
@@ -8117,9 +8206,12 @@ var init_schemas = __esm({
|
|
|
8117
8206
|
});
|
|
8118
8207
|
coursePricingSchema = z11.object({
|
|
8119
8208
|
bookingRequirement: z11.enum(["none", "required"]),
|
|
8120
|
-
pricingStrategy: z11.enum(["free", "single", "tiered"]),
|
|
8209
|
+
pricingStrategy: z11.enum(["free", "single", "tiered", "sliding_scale"]),
|
|
8121
8210
|
currency: z11.string(),
|
|
8122
8211
|
singlePriceAmount: z11.number().nullable(),
|
|
8212
|
+
slidingMinAmount: z11.number().nullable().optional(),
|
|
8213
|
+
slidingMaxAmount: z11.number().nullable().optional(),
|
|
8214
|
+
slidingSuggestedAmount: z11.number().nullable().optional(),
|
|
8123
8215
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
8124
8216
|
options: z11.array(coursePricingOptionSchema)
|
|
8125
8217
|
});
|
|
@@ -8181,7 +8273,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
8181
8273
|
return left.name.localeCompare(right.name);
|
|
8182
8274
|
});
|
|
8183
8275
|
}
|
|
8184
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
|
|
8276
|
+
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
8277
|
+
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
8278
|
+
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
8185
8279
|
const currency = course.pricing?.currency ?? course.currency;
|
|
8186
8280
|
if (!course.pricing) {
|
|
8187
8281
|
const legacyAmount = course.priceCents ?? 0;
|
|
@@ -8191,6 +8285,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8191
8285
|
selectableOptions: [],
|
|
8192
8286
|
requiresSelection: false,
|
|
8193
8287
|
selectedOption: null,
|
|
8288
|
+
slidingScale: null,
|
|
8289
|
+
selectedSlidingAmount: null,
|
|
8194
8290
|
selectedPriceAmount: legacyAmount,
|
|
8195
8291
|
selectedRequiresPayment: legacyAmount > 0,
|
|
8196
8292
|
hasPaidSelection: legacyAmount > 0,
|
|
@@ -8205,6 +8301,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8205
8301
|
selectableOptions: [],
|
|
8206
8302
|
requiresSelection: false,
|
|
8207
8303
|
selectedOption: null,
|
|
8304
|
+
slidingScale: null,
|
|
8305
|
+
selectedSlidingAmount: null,
|
|
8208
8306
|
selectedPriceAmount: 0,
|
|
8209
8307
|
selectedRequiresPayment: false,
|
|
8210
8308
|
hasPaidSelection: false,
|
|
@@ -8218,6 +8316,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8218
8316
|
selectableOptions: [],
|
|
8219
8317
|
requiresSelection: false,
|
|
8220
8318
|
selectedOption: null,
|
|
8319
|
+
slidingScale: null,
|
|
8320
|
+
selectedSlidingAmount: null,
|
|
8221
8321
|
selectedPriceAmount: amount,
|
|
8222
8322
|
selectedRequiresPayment: amount > 0,
|
|
8223
8323
|
hasPaidSelection: amount > 0,
|
|
@@ -8227,7 +8327,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8227
8327
|
case "tiered": {
|
|
8228
8328
|
const selectableOptions = getSelectableCoursePricingOptionsForNow(
|
|
8229
8329
|
course,
|
|
8230
|
-
resolvePlanningDateInput(
|
|
8330
|
+
resolvePlanningDateInput(effectiveNowInput)
|
|
8231
8331
|
);
|
|
8232
8332
|
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
8233
8333
|
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
@@ -8243,12 +8343,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8243
8343
|
selectableOptions,
|
|
8244
8344
|
requiresSelection: selectableOptions.length > 1,
|
|
8245
8345
|
selectedOption,
|
|
8346
|
+
slidingScale: null,
|
|
8347
|
+
selectedSlidingAmount: null,
|
|
8246
8348
|
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
8247
8349
|
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
8248
8350
|
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
8249
8351
|
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
8250
8352
|
};
|
|
8251
8353
|
}
|
|
8354
|
+
case "sliding_scale": {
|
|
8355
|
+
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
8356
|
+
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
8357
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
|
|
8358
|
+
return {
|
|
8359
|
+
currency,
|
|
8360
|
+
display: { kind: "unavailable", currency },
|
|
8361
|
+
selectableOptions: [],
|
|
8362
|
+
requiresSelection: true,
|
|
8363
|
+
selectedOption: null,
|
|
8364
|
+
slidingScale: null,
|
|
8365
|
+
selectedSlidingAmount: null,
|
|
8366
|
+
selectedPriceAmount: null,
|
|
8367
|
+
selectedRequiresPayment: false,
|
|
8368
|
+
hasPaidSelection: false,
|
|
8369
|
+
hasFreeSelection: false
|
|
8370
|
+
};
|
|
8371
|
+
}
|
|
8372
|
+
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
8373
|
+
return {
|
|
8374
|
+
currency,
|
|
8375
|
+
display: { kind: "range", minAmount, maxAmount, currency },
|
|
8376
|
+
selectableOptions: [],
|
|
8377
|
+
requiresSelection: normalizedSelectedAmount === null,
|
|
8378
|
+
selectedOption: null,
|
|
8379
|
+
slidingScale: {
|
|
8380
|
+
minAmount,
|
|
8381
|
+
maxAmount,
|
|
8382
|
+
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
8383
|
+
},
|
|
8384
|
+
selectedSlidingAmount: normalizedSelectedAmount,
|
|
8385
|
+
selectedPriceAmount: normalizedSelectedAmount,
|
|
8386
|
+
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
8387
|
+
hasPaidSelection: maxAmount > 0,
|
|
8388
|
+
hasFreeSelection: minAmount === 0
|
|
8389
|
+
};
|
|
8390
|
+
}
|
|
8252
8391
|
}
|
|
8253
8392
|
}
|
|
8254
8393
|
function formatCoursePriceDisplay(display, locale) {
|
|
@@ -8357,7 +8496,7 @@ function isRecord7(value) {
|
|
|
8357
8496
|
}
|
|
8358
8497
|
function isPublicEventPricing(value) {
|
|
8359
8498
|
if (!isRecord7(value) || typeof value.kind !== "string") return false;
|
|
8360
|
-
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
|
|
8499
|
+
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "sliding_scale" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
|
|
8361
8500
|
}
|
|
8362
8501
|
function isPublicEventTicketType(value) {
|
|
8363
8502
|
return isRecord7(value) && typeof value.id === "string";
|
|
@@ -10388,6 +10527,19 @@ var init_schemas2 = __esm({
|
|
|
10388
10527
|
ticketTypes: z14.array(publicEventTicketTypeSchema),
|
|
10389
10528
|
display: publicEventTicketTypePriceDisplaySchema
|
|
10390
10529
|
}),
|
|
10530
|
+
z14.object({
|
|
10531
|
+
kind: z14.literal("sliding_scale"),
|
|
10532
|
+
minAmount: z14.number(),
|
|
10533
|
+
maxAmount: z14.number(),
|
|
10534
|
+
suggestedAmount: z14.number().nullable(),
|
|
10535
|
+
currency: z14.string(),
|
|
10536
|
+
display: z14.object({
|
|
10537
|
+
kind: z14.literal("range"),
|
|
10538
|
+
minAmount: z14.number(),
|
|
10539
|
+
maxAmount: z14.number(),
|
|
10540
|
+
currency: z14.string()
|
|
10541
|
+
})
|
|
10542
|
+
}),
|
|
10391
10543
|
z14.object({
|
|
10392
10544
|
kind: z14.literal("course"),
|
|
10393
10545
|
display: z14.object({ kind: z14.literal("course"), display: publicCoursePriceDisplaySchema })
|
|
@@ -28331,6 +28483,7 @@ function useBookingSubmission(_siteId) {
|
|
|
28331
28483
|
customFields: data.customFields,
|
|
28332
28484
|
timezone: data.timezone,
|
|
28333
28485
|
discountCode: data.discountCode,
|
|
28486
|
+
selectedSlidingAmount: data.selectedSlidingAmount,
|
|
28334
28487
|
selectedCollectionOptionKind: data.selectedCollectionOptionKind,
|
|
28335
28488
|
altchaSolution: data.altchaSolution ?? null,
|
|
28336
28489
|
successUrl: data.successUrl,
|
|
@@ -28859,6 +29012,9 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
28859
29012
|
fieldValues: collectInitialFieldValues(initialData),
|
|
28860
29013
|
touchedFields: {},
|
|
28861
29014
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
29015
|
+
selectedSlidingAmountInput: toOptionalString(
|
|
29016
|
+
initialData.selectedSlidingAmountInput
|
|
29017
|
+
) ?? "",
|
|
28862
29018
|
selectedCollectionOptionKind: toSelectedCollectionOptionKind(
|
|
28863
29019
|
initialData.selectedCollectionOptionKind
|
|
28864
29020
|
),
|
|
@@ -28911,6 +29067,7 @@ function bookingFlowReducer(state, event) {
|
|
|
28911
29067
|
selectedDate: void 0,
|
|
28912
29068
|
selectedSlot: null,
|
|
28913
29069
|
selectedAppointmentPackageId: void 0,
|
|
29070
|
+
selectedSlidingAmountInput: "",
|
|
28914
29071
|
selectedCollectionOptionKind: void 0,
|
|
28915
29072
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
28916
29073
|
};
|
|
@@ -28964,6 +29121,13 @@ function bookingFlowReducer(state, event) {
|
|
|
28964
29121
|
selectedAppointmentPackageId: void 0,
|
|
28965
29122
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
28966
29123
|
};
|
|
29124
|
+
case "sliding-amount-changed":
|
|
29125
|
+
return {
|
|
29126
|
+
...state,
|
|
29127
|
+
selectedSlidingAmountInput: event.value,
|
|
29128
|
+
selectedAppointmentPackageId: void 0,
|
|
29129
|
+
validationErrors: clearBookingFormError(state.validationErrors)
|
|
29130
|
+
};
|
|
28967
29131
|
case "appointment-package-selected":
|
|
28968
29132
|
return {
|
|
28969
29133
|
...state,
|
|
@@ -29066,6 +29230,7 @@ function toBookingFormData(state) {
|
|
|
29066
29230
|
selectedDate: state.selectedDate,
|
|
29067
29231
|
selectedSlot: state.selectedSlot?.startAt,
|
|
29068
29232
|
discountCode: state.discountCode || void 0,
|
|
29233
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
|
|
29069
29234
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
29070
29235
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId
|
|
29071
29236
|
};
|
|
@@ -29083,7 +29248,8 @@ function buildBookingStepResolution(input) {
|
|
|
29083
29248
|
input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
|
|
29084
29249
|
);
|
|
29085
29250
|
const selectedService = paymentResolution.service;
|
|
29086
|
-
const
|
|
29251
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29252
|
+
const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
|
|
29087
29253
|
input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
29088
29254
|
);
|
|
29089
29255
|
const hasFields = Boolean(input.form.schema?.fields.length);
|
|
@@ -29127,6 +29293,18 @@ function validateBookingStep(input) {
|
|
|
29127
29293
|
services: input.services,
|
|
29128
29294
|
defaultServiceId: input.defaultServiceId
|
|
29129
29295
|
});
|
|
29296
|
+
const slidingScale = getBookingServiceSlidingScale(resolution.service);
|
|
29297
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(
|
|
29298
|
+
slidingScale,
|
|
29299
|
+
parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
|
|
29300
|
+
)) {
|
|
29301
|
+
return {
|
|
29302
|
+
ok: false,
|
|
29303
|
+
errors: createFormBookingValidationError(
|
|
29304
|
+
"Please choose an amount within the sliding scale"
|
|
29305
|
+
)
|
|
29306
|
+
};
|
|
29307
|
+
}
|
|
29130
29308
|
if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
|
|
29131
29309
|
return { ok: true };
|
|
29132
29310
|
}
|
|
@@ -29525,6 +29703,7 @@ var init_useHeadlessBookingFlow_state = __esm({
|
|
|
29525
29703
|
"../blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.ts"() {
|
|
29526
29704
|
"use strict";
|
|
29527
29705
|
init_booking_form_headless_state();
|
|
29706
|
+
init_booking_form_state();
|
|
29528
29707
|
}
|
|
29529
29708
|
});
|
|
29530
29709
|
|
|
@@ -29564,11 +29743,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
29564
29743
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
29565
29744
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
29566
29745
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
29746
|
+
const lastSlidingServiceIdRef = useRef6(null);
|
|
29747
|
+
useEffect6(() => {
|
|
29748
|
+
const selectedId = selectedService?.id ?? null;
|
|
29749
|
+
if (lastSlidingServiceIdRef.current === selectedId) return;
|
|
29750
|
+
lastSlidingServiceIdRef.current = selectedId;
|
|
29751
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29752
|
+
dispatch({
|
|
29753
|
+
type: "sliding-amount-changed",
|
|
29754
|
+
value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
29755
|
+
});
|
|
29756
|
+
}, [selectedService]);
|
|
29567
29757
|
const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
|
|
29758
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29759
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
29760
|
+
state.selectedSlidingAmountInput
|
|
29761
|
+
);
|
|
29762
|
+
const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
|
|
29568
29763
|
const canLoadAppointmentPackages = Boolean(
|
|
29569
|
-
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
29764
|
+
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
|
|
29570
29765
|
);
|
|
29571
|
-
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
29766
|
+
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
29572
29767
|
const data = useMemo2(() => toBookingFormData(state), [state]);
|
|
29573
29768
|
const availabilityDatesQuery = useMemo2(
|
|
29574
29769
|
() => buildBookingAvailabilityQuery({
|
|
@@ -29798,13 +29993,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
29798
29993
|
state.selectedSlot
|
|
29799
29994
|
]);
|
|
29800
29995
|
const appointmentDiscountContext = useMemo2(
|
|
29801
|
-
() => selectedService &&
|
|
29802
|
-
[
|
|
29996
|
+
() => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
29997
|
+
[selectedAppointmentPriceAmount, selectedService?.id]
|
|
29803
29998
|
);
|
|
29804
29999
|
const discountUi = useDiscountCodeUi({
|
|
29805
30000
|
api,
|
|
29806
30001
|
discountContext: appointmentDiscountContext,
|
|
29807
|
-
subtotalCents:
|
|
30002
|
+
subtotalCents: selectedAppointmentPriceAmount
|
|
29808
30003
|
});
|
|
29809
30004
|
const { submit, clearFeedback } = useBookingSubmission(options.siteId);
|
|
29810
30005
|
const submittingRef = useRef6(false);
|
|
@@ -29947,6 +30142,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
29947
30142
|
type: "appointment-package-selected",
|
|
29948
30143
|
packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
|
|
29949
30144
|
}),
|
|
30145
|
+
setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
|
|
29950
30146
|
setDiscountCode: (code) => {
|
|
29951
30147
|
dispatch({ type: "discount-code-changed", code });
|
|
29952
30148
|
latestRef.current.setDiscountCode(code);
|
|
@@ -30017,11 +30213,11 @@ function useHeadlessBookingFlow(options) {
|
|
|
30017
30213
|
() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
30018
30214
|
serviceTitle: selectedService.title,
|
|
30019
30215
|
paymentTerms: selectedService.paymentTerms,
|
|
30020
|
-
priceAmount:
|
|
30216
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
30021
30217
|
priceCurrency: selectedService.priceCurrency,
|
|
30022
30218
|
bookingStartAt: state.selectedSlot?.startAt
|
|
30023
30219
|
}) : null,
|
|
30024
|
-
[paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
|
|
30220
|
+
[paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
|
|
30025
30221
|
);
|
|
30026
30222
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
30027
30223
|
const selectedAppointmentPackage = appointmentPackageItems.find(
|
|
@@ -30050,6 +30246,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
30050
30246
|
selection: null,
|
|
30051
30247
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
30052
30248
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
30249
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
30250
|
+
selectedSlidingAmount,
|
|
30251
|
+
slidingScale: selectedServiceSlidingScale,
|
|
30053
30252
|
appointmentPackages: appointmentPackagesModel,
|
|
30054
30253
|
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
30055
30254
|
} : {
|
|
@@ -30058,6 +30257,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
30058
30257
|
selection: paymentSelection,
|
|
30059
30258
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
30060
30259
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
30260
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
30261
|
+
selectedSlidingAmount,
|
|
30262
|
+
slidingScale: selectedServiceSlidingScale,
|
|
30061
30263
|
appointmentPackages: appointmentPackagesModel
|
|
30062
30264
|
};
|
|
30063
30265
|
return {
|
|
@@ -30672,6 +30874,9 @@ var init_FieldValidationMessage = __esm({
|
|
|
30672
30874
|
|
|
30673
30875
|
// ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
30674
30876
|
import { Fragment as Fragment9, jsx as jsx62, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
30877
|
+
function formatBookingAmount(amount, currency) {
|
|
30878
|
+
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
30879
|
+
}
|
|
30675
30880
|
function HeadlessBookingDefaultForm({
|
|
30676
30881
|
booking,
|
|
30677
30882
|
onSubmit
|
|
@@ -30948,6 +31153,7 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
30948
31153
|
}
|
|
30949
31154
|
const packageOptions = booking.payment.appointmentPackages.items;
|
|
30950
31155
|
const hasPackageOptions = packageOptions.length > 0;
|
|
31156
|
+
const slidingScale = booking.payment.slidingScale;
|
|
30951
31157
|
return /* @__PURE__ */ jsxs46("div", { className: "ab-stack", children: [
|
|
30952
31158
|
/* @__PURE__ */ jsxs46("div", { className: "ab-info-box", children: [
|
|
30953
31159
|
/* @__PURE__ */ jsx62("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
|
|
@@ -30958,6 +31164,28 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
30958
31164
|
booking.payment.appointmentPackages.state.message,
|
|
30959
31165
|
" You can continue with the normal payment option."
|
|
30960
31166
|
] }) : null,
|
|
31167
|
+
slidingScale ? /* @__PURE__ */ jsxs46("div", { className: "rb-space-y-2", children: [
|
|
31168
|
+
/* @__PURE__ */ jsx62("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
|
|
31169
|
+
/* @__PURE__ */ jsxs46("p", { className: "rb-caption status-muted", children: [
|
|
31170
|
+
formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
|
|
31171
|
+
" to ",
|
|
31172
|
+
formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
|
|
31173
|
+
slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
|
|
31174
|
+
] }),
|
|
31175
|
+
/* @__PURE__ */ jsx62(
|
|
31176
|
+
"input",
|
|
31177
|
+
{
|
|
31178
|
+
id: "appointment-sliding-amount",
|
|
31179
|
+
type: "number",
|
|
31180
|
+
className: "form-input",
|
|
31181
|
+
min: slidingScale.minAmount / 100,
|
|
31182
|
+
max: slidingScale.maxAmount / 100,
|
|
31183
|
+
step: "0.01",
|
|
31184
|
+
value: booking.payment.selectedSlidingAmountInput,
|
|
31185
|
+
onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
|
|
31186
|
+
}
|
|
31187
|
+
)
|
|
31188
|
+
] }) : null,
|
|
30961
31189
|
/* @__PURE__ */ jsxs46("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
|
|
30962
31190
|
packageOptions.map((appointmentPackage) => {
|
|
30963
31191
|
const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
|
|
@@ -32893,6 +33121,7 @@ function useEligibility(params) {
|
|
|
32893
33121
|
occurrenceId: params.occurrenceId,
|
|
32894
33122
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
32895
33123
|
ticketTypeId: params.ticketTypeId ?? void 0,
|
|
33124
|
+
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
32896
33125
|
email: params.email.trim().toLowerCase(),
|
|
32897
33126
|
ticketsCount: params.ticketsCount
|
|
32898
33127
|
});
|
|
@@ -32913,7 +33142,7 @@ function useEligibility(params) {
|
|
|
32913
33142
|
return () => {
|
|
32914
33143
|
cancelled = true;
|
|
32915
33144
|
};
|
|
32916
|
-
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
|
|
33145
|
+
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
|
|
32917
33146
|
return {
|
|
32918
33147
|
state,
|
|
32919
33148
|
eligibility: state.eligibility,
|
|
@@ -33264,6 +33493,41 @@ function TicketCounterLimit(props2) {
|
|
|
33264
33493
|
] }) : null
|
|
33265
33494
|
] });
|
|
33266
33495
|
}
|
|
33496
|
+
function formatCurrencyInputAmount(amount) {
|
|
33497
|
+
const major = amount / 100;
|
|
33498
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
33499
|
+
}
|
|
33500
|
+
function SlidingScaleAmountField(props2) {
|
|
33501
|
+
const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
|
|
33502
|
+
const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
|
|
33503
|
+
const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
|
|
33504
|
+
return /* @__PURE__ */ jsxs54("div", { className: "er-field", children: [
|
|
33505
|
+
/* @__PURE__ */ jsx77("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
|
|
33506
|
+
/* @__PURE__ */ jsx77(
|
|
33507
|
+
"input",
|
|
33508
|
+
{
|
|
33509
|
+
id: "er-sliding-amount",
|
|
33510
|
+
type: "number",
|
|
33511
|
+
min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
|
|
33512
|
+
max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
|
|
33513
|
+
step: "0.01",
|
|
33514
|
+
inputMode: "decimal",
|
|
33515
|
+
className: "er-input",
|
|
33516
|
+
value: props2.value,
|
|
33517
|
+
onChange: (event) => props2.onChange?.(event.target.value)
|
|
33518
|
+
}
|
|
33519
|
+
),
|
|
33520
|
+
/* @__PURE__ */ jsxs54("p", { className: "er-text er-text--muted", children: [
|
|
33521
|
+
"Choose between ",
|
|
33522
|
+
minLabel,
|
|
33523
|
+
" and ",
|
|
33524
|
+
maxLabel,
|
|
33525
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
33526
|
+
"."
|
|
33527
|
+
] }),
|
|
33528
|
+
props2.message ? /* @__PURE__ */ jsx77("p", { className: "er-text er-text--muted", children: props2.message }) : null
|
|
33529
|
+
] });
|
|
33530
|
+
}
|
|
33267
33531
|
function getTicketTypeCounterAvailabilityLabel(input) {
|
|
33268
33532
|
if (input.selectedRemainingCapacity !== null) {
|
|
33269
33533
|
return `${input.selectedRemainingCapacity} remaining for this ticket type`;
|
|
@@ -33335,6 +33599,10 @@ var init_TicketSelectionStep = __esm({
|
|
|
33335
33599
|
maxTickets,
|
|
33336
33600
|
selectedTicketTypeId = null,
|
|
33337
33601
|
onTicketTypeChange,
|
|
33602
|
+
slidingScale = null,
|
|
33603
|
+
selectedSlidingAmountInput = "",
|
|
33604
|
+
slidingScaleSelectionMessage = null,
|
|
33605
|
+
onSlidingAmountChange,
|
|
33338
33606
|
onTicketsChange
|
|
33339
33607
|
}) => {
|
|
33340
33608
|
const deliveryMode = event?.deliveryMode ?? "in_person";
|
|
@@ -33450,6 +33718,16 @@ var init_TicketSelectionStep = __esm({
|
|
|
33450
33718
|
] })
|
|
33451
33719
|
] })
|
|
33452
33720
|
] }) : /* @__PURE__ */ jsxs54(Fragment12, { children: [
|
|
33721
|
+
slidingScale ? /* @__PURE__ */ jsx77(
|
|
33722
|
+
SlidingScaleAmountField,
|
|
33723
|
+
{
|
|
33724
|
+
slidingScale,
|
|
33725
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
|
|
33726
|
+
value: selectedSlidingAmountInput,
|
|
33727
|
+
message: slidingScaleSelectionMessage,
|
|
33728
|
+
onChange: onSlidingAmountChange
|
|
33729
|
+
}
|
|
33730
|
+
) : null,
|
|
33453
33731
|
/* @__PURE__ */ jsx77("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
|
|
33454
33732
|
/* @__PURE__ */ jsxs54("div", { className: "er-ticket-counter-group", children: [
|
|
33455
33733
|
/* @__PURE__ */ jsx77(
|
|
@@ -34826,6 +35104,10 @@ function EventRegistrationWizardContent(props2) {
|
|
|
34826
35104
|
maxTickets: wizard.maxTicketsNum,
|
|
34827
35105
|
selectedTicketTypeId: wizard.selectedTicketTypeId,
|
|
34828
35106
|
onTicketTypeChange: wizard.setSelectedTicketTypeId,
|
|
35107
|
+
slidingScale: wizard.selectedEventSlidingScale,
|
|
35108
|
+
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
35109
|
+
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
35110
|
+
onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
|
|
34829
35111
|
onTicketsChange: wizard.setTicketsCount
|
|
34830
35112
|
}
|
|
34831
35113
|
)
|
|
@@ -35042,7 +35324,7 @@ function EventRegistrationSummaryBar(props2) {
|
|
|
35042
35324
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
35043
35325
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
35044
35326
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
35045
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
35327
|
+
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
35046
35328
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
|
|
35047
35329
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
35048
35330
|
const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
|
|
@@ -35493,6 +35775,7 @@ function useEventRegistrationSubmit(options) {
|
|
|
35493
35775
|
occurrenceId: submitOccurrenceId,
|
|
35494
35776
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
35495
35777
|
ticketTypeId: options.selectedTicketTypeId ?? void 0,
|
|
35778
|
+
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
35496
35779
|
email: options.formData.email.trim().toLowerCase(),
|
|
35497
35780
|
name: options.formData.name.trim(),
|
|
35498
35781
|
ticketsCount: options.ticketsCount,
|
|
@@ -35602,6 +35885,35 @@ var init_useEventRegistrationSubmit = __esm({
|
|
|
35602
35885
|
|
|
35603
35886
|
// ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
35604
35887
|
import { useCallback as useCallback7, useEffect as useEffect14, useMemo as useMemo7, useReducer as useReducer9, useState as useState4 } from "react";
|
|
35888
|
+
function parseCurrencyInputToCents(value) {
|
|
35889
|
+
const trimmed = value.trim();
|
|
35890
|
+
if (!trimmed) return null;
|
|
35891
|
+
const amount = Number(trimmed);
|
|
35892
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
35893
|
+
return Math.round(amount * 100);
|
|
35894
|
+
}
|
|
35895
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
35896
|
+
const major = amount / 100;
|
|
35897
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
35898
|
+
}
|
|
35899
|
+
function getSlidingScaleForEvent(event) {
|
|
35900
|
+
const pricing = event ? resolveRuntimeEventPricing(event) : null;
|
|
35901
|
+
return pricing?.kind === "sliding_scale" ? {
|
|
35902
|
+
minAmount: pricing.minAmount,
|
|
35903
|
+
maxAmount: pricing.maxAmount,
|
|
35904
|
+
suggestedAmount: pricing.suggestedAmount
|
|
35905
|
+
} : null;
|
|
35906
|
+
}
|
|
35907
|
+
function getSlidingScaleSelectionMessage(input) {
|
|
35908
|
+
if (!input.slidingScale) return null;
|
|
35909
|
+
if (input.selectedAmount === null) {
|
|
35910
|
+
return "Choose an amount to continue.";
|
|
35911
|
+
}
|
|
35912
|
+
if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
|
|
35913
|
+
return "Choose an amount within the sliding scale.";
|
|
35914
|
+
}
|
|
35915
|
+
return null;
|
|
35916
|
+
}
|
|
35605
35917
|
function useEventRegistrationWizard(options) {
|
|
35606
35918
|
const api = useBlockApi();
|
|
35607
35919
|
const registrationEvents = useMemo7(
|
|
@@ -35646,6 +35958,10 @@ function useEventRegistrationWizard(options) {
|
|
|
35646
35958
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
35647
35959
|
);
|
|
35648
35960
|
const [selectedTicketTypeId, setSelectedTicketTypeId] = useState4(null);
|
|
35961
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState4(() => {
|
|
35962
|
+
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
35963
|
+
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
35964
|
+
});
|
|
35649
35965
|
const [registrationResult, setRegistrationResult] = useState4(null);
|
|
35650
35966
|
const [errorMessage, setErrorMessage] = useState4("");
|
|
35651
35967
|
const [altchaSolution, setAltchaSolution] = useState4(null);
|
|
@@ -35682,6 +35998,7 @@ function useEventRegistrationWizard(options) {
|
|
|
35682
35998
|
occurrenceId,
|
|
35683
35999
|
attendanceMode: selectedAttendanceMode,
|
|
35684
36000
|
ticketTypeId: selectedTicketTypeId,
|
|
36001
|
+
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
35685
36002
|
email: formData.email,
|
|
35686
36003
|
ticketsCount
|
|
35687
36004
|
});
|
|
@@ -35817,6 +36134,18 @@ function useEventRegistrationWizard(options) {
|
|
|
35817
36134
|
}),
|
|
35818
36135
|
[selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
|
|
35819
36136
|
);
|
|
36137
|
+
const selectedSlidingAmount = useMemo7(
|
|
36138
|
+
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
36139
|
+
[selectedSlidingAmountInput]
|
|
36140
|
+
);
|
|
36141
|
+
const selectedEventSlidingScale = useMemo7(
|
|
36142
|
+
() => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
|
|
36143
|
+
[selectedEvent, preSelectedEvent]
|
|
36144
|
+
);
|
|
36145
|
+
const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
|
|
36146
|
+
slidingScale: selectedEventSlidingScale,
|
|
36147
|
+
selectedAmount: selectedSlidingAmount
|
|
36148
|
+
});
|
|
35820
36149
|
const ticketTypeSelectionRequired = useMemo7(() => {
|
|
35821
36150
|
const event = selectedEvent ?? preSelectedEvent;
|
|
35822
36151
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
@@ -35885,12 +36214,24 @@ function useEventRegistrationWizard(options) {
|
|
|
35885
36214
|
setGuestSectionShake(false);
|
|
35886
36215
|
};
|
|
35887
36216
|
const eventRequiresPayment = useMemo7(
|
|
35888
|
-
() =>
|
|
36217
|
+
() => {
|
|
36218
|
+
if (selectedEventSlidingScale) {
|
|
36219
|
+
return (selectedSlidingAmount ?? 0) > 0;
|
|
36220
|
+
}
|
|
36221
|
+
return resolveEventRequiresPayment({
|
|
36222
|
+
eligibility,
|
|
36223
|
+
selectedTicketType,
|
|
36224
|
+
event: selectedEvent ?? preSelectedEvent
|
|
36225
|
+
});
|
|
36226
|
+
},
|
|
36227
|
+
[
|
|
35889
36228
|
eligibility,
|
|
35890
36229
|
selectedTicketType,
|
|
35891
|
-
|
|
35892
|
-
|
|
35893
|
-
|
|
36230
|
+
selectedEvent,
|
|
36231
|
+
preSelectedEvent,
|
|
36232
|
+
selectedEventSlidingScale,
|
|
36233
|
+
selectedSlidingAmount
|
|
36234
|
+
]
|
|
35894
36235
|
);
|
|
35895
36236
|
const handleDetailsComplete = async () => {
|
|
35896
36237
|
if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
|
|
@@ -35899,6 +36240,11 @@ function useEventRegistrationWizard(options) {
|
|
|
35899
36240
|
setStep("error");
|
|
35900
36241
|
return { ok: false, reason: "blocked", message };
|
|
35901
36242
|
}
|
|
36243
|
+
if (slidingScaleSelectionMessage) {
|
|
36244
|
+
setErrorMessage(slidingScaleSelectionMessage);
|
|
36245
|
+
setStep("error");
|
|
36246
|
+
return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
|
|
36247
|
+
}
|
|
35902
36248
|
if (!validateForm()) {
|
|
35903
36249
|
setGuestSectionShake(true);
|
|
35904
36250
|
return {
|
|
@@ -35983,9 +36329,18 @@ function useEventRegistrationWizard(options) {
|
|
|
35983
36329
|
const discountSubtotalCents = useMemo7(() => {
|
|
35984
36330
|
if (discountContext?.type !== "event") return void 0;
|
|
35985
36331
|
const event = selectedEvent ?? preSelectedEvent;
|
|
35986
|
-
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
36332
|
+
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
35987
36333
|
return Math.max(0, eventPriceCents * ticketsCount);
|
|
35988
|
-
}, [
|
|
36334
|
+
}, [
|
|
36335
|
+
discountContext,
|
|
36336
|
+
selectedTicketType,
|
|
36337
|
+
eligibility,
|
|
36338
|
+
selectedEvent,
|
|
36339
|
+
preSelectedEvent,
|
|
36340
|
+
selectedEventSlidingScale,
|
|
36341
|
+
selectedSlidingAmount,
|
|
36342
|
+
ticketsCount
|
|
36343
|
+
]);
|
|
35989
36344
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
35990
36345
|
const selectionMethod = paymentSelection.method;
|
|
35991
36346
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -35994,6 +36349,7 @@ function useEventRegistrationWizard(options) {
|
|
|
35994
36349
|
registrationTarget,
|
|
35995
36350
|
selectedAttendanceMode,
|
|
35996
36351
|
selectedTicketTypeId,
|
|
36352
|
+
selectedSlidingAmount,
|
|
35997
36353
|
ticketsCount,
|
|
35998
36354
|
formData,
|
|
35999
36355
|
altchaSolution,
|
|
@@ -36008,6 +36364,10 @@ function useEventRegistrationWizard(options) {
|
|
|
36008
36364
|
});
|
|
36009
36365
|
const handleEventSelect = (event) => {
|
|
36010
36366
|
setSelectedEvent(event);
|
|
36367
|
+
const slidingScale = getSlidingScaleForEvent(event);
|
|
36368
|
+
setSelectedSlidingAmountInput(
|
|
36369
|
+
slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
36370
|
+
);
|
|
36011
36371
|
setSelectedAttendanceMode(
|
|
36012
36372
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
36013
36373
|
);
|
|
@@ -36017,6 +36377,7 @@ function useEventRegistrationWizard(options) {
|
|
|
36017
36377
|
const handleRetry = () => {
|
|
36018
36378
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
36019
36379
|
setSelectedTicketTypeId(null);
|
|
36380
|
+
setSelectedSlidingAmountInput("");
|
|
36020
36381
|
setSelectedAttendanceMode(
|
|
36021
36382
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
36022
36383
|
);
|
|
@@ -36053,6 +36414,11 @@ function useEventRegistrationWizard(options) {
|
|
|
36053
36414
|
setSelectedAttendanceMode,
|
|
36054
36415
|
selectedTicketTypeId,
|
|
36055
36416
|
setSelectedTicketTypeId,
|
|
36417
|
+
selectedSlidingAmountInput,
|
|
36418
|
+
setSelectedSlidingAmountInput,
|
|
36419
|
+
selectedSlidingAmount,
|
|
36420
|
+
selectedEventSlidingScale,
|
|
36421
|
+
slidingScaleSelectionMessage,
|
|
36056
36422
|
selectedTicketType,
|
|
36057
36423
|
visibleTicketTypes,
|
|
36058
36424
|
ticketTypeSelectionRequired,
|
|
@@ -37368,6 +37734,44 @@ function CoursePricingSelector({
|
|
|
37368
37734
|
)
|
|
37369
37735
|
] });
|
|
37370
37736
|
}
|
|
37737
|
+
function CourseSlidingScaleInput({
|
|
37738
|
+
pricing,
|
|
37739
|
+
value,
|
|
37740
|
+
onChange
|
|
37741
|
+
}) {
|
|
37742
|
+
const slidingScale = pricing.slidingScale;
|
|
37743
|
+
if (!slidingScale) {
|
|
37744
|
+
return null;
|
|
37745
|
+
}
|
|
37746
|
+
const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
|
|
37747
|
+
const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
|
|
37748
|
+
const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
|
|
37749
|
+
return /* @__PURE__ */ jsxs75("div", { className: "cr-form__field", children: [
|
|
37750
|
+
/* @__PURE__ */ jsx105("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
|
|
37751
|
+
/* @__PURE__ */ jsx105(
|
|
37752
|
+
"input",
|
|
37753
|
+
{
|
|
37754
|
+
id: "cr-sliding-amount",
|
|
37755
|
+
type: "number",
|
|
37756
|
+
min: slidingScale.minAmount / 100,
|
|
37757
|
+
max: slidingScale.maxAmount / 100,
|
|
37758
|
+
step: "0.01",
|
|
37759
|
+
inputMode: "decimal",
|
|
37760
|
+
className: "cr-form__input",
|
|
37761
|
+
value,
|
|
37762
|
+
onChange: (event) => onChange(event.target.value)
|
|
37763
|
+
}
|
|
37764
|
+
),
|
|
37765
|
+
/* @__PURE__ */ jsxs75("p", { className: "cr-text cr-text--muted", children: [
|
|
37766
|
+
"Choose between ",
|
|
37767
|
+
minLabel,
|
|
37768
|
+
" and ",
|
|
37769
|
+
maxLabel,
|
|
37770
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
37771
|
+
"."
|
|
37772
|
+
] })
|
|
37773
|
+
] });
|
|
37774
|
+
}
|
|
37371
37775
|
function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
|
|
37372
37776
|
const nameErrorId = "cr-name-error";
|
|
37373
37777
|
const emailErrorId = "cr-email-error";
|
|
@@ -37463,6 +37867,17 @@ var init_components2 = __esm({
|
|
|
37463
37867
|
|
|
37464
37868
|
// ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
37465
37869
|
import { useEffect as useEffect18, useMemo as useMemo9, useState as useState9 } from "react";
|
|
37870
|
+
function parseCurrencyInputToCents2(value) {
|
|
37871
|
+
const trimmed = value.trim();
|
|
37872
|
+
if (!trimmed) return null;
|
|
37873
|
+
const amount = Number(trimmed);
|
|
37874
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
37875
|
+
return Math.round(amount * 100);
|
|
37876
|
+
}
|
|
37877
|
+
function formatCentsAsCurrencyInput2(amount) {
|
|
37878
|
+
const major = amount / 100;
|
|
37879
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
37880
|
+
}
|
|
37466
37881
|
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
37467
37882
|
if (!course || portalAuthState === "checking") return false;
|
|
37468
37883
|
if (hasWaitlistClaimToken) return false;
|
|
@@ -37480,12 +37895,27 @@ function getSessionIdFromUrl() {
|
|
|
37480
37895
|
}
|
|
37481
37896
|
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
37482
37897
|
if (pricing?.requiresSelection && !pricing.selectedOption) {
|
|
37898
|
+
if (pricing.slidingScale) {
|
|
37899
|
+
return "Choose an amount to continue.";
|
|
37900
|
+
}
|
|
37483
37901
|
return "Choose a pricing option to continue.";
|
|
37484
37902
|
}
|
|
37903
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
|
|
37904
|
+
return "Choose an amount within the sliding scale.";
|
|
37905
|
+
}
|
|
37906
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
|
|
37907
|
+
return "Choose an amount within the sliding scale.";
|
|
37908
|
+
}
|
|
37485
37909
|
return null;
|
|
37486
37910
|
}
|
|
37487
37911
|
function buildCoursePricingOptionPayload(pricing) {
|
|
37488
|
-
|
|
37912
|
+
if (pricing?.selectedOption) {
|
|
37913
|
+
return { pricingOptionId: pricing.selectedOption.id };
|
|
37914
|
+
}
|
|
37915
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
|
|
37916
|
+
return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
37917
|
+
}
|
|
37918
|
+
return {};
|
|
37489
37919
|
}
|
|
37490
37920
|
function resolveHasCoursePayment(pricing) {
|
|
37491
37921
|
if (!pricing) {
|
|
@@ -37526,6 +37956,7 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37526
37956
|
scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
|
|
37527
37957
|
);
|
|
37528
37958
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState9(null);
|
|
37959
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState9("");
|
|
37529
37960
|
const [formData, setFormData] = useState9({
|
|
37530
37961
|
name: "",
|
|
37531
37962
|
email: "",
|
|
@@ -37547,8 +37978,12 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37547
37978
|
const [bookingMode, setBookingMode] = useState9(null);
|
|
37548
37979
|
const waitlistClaim = useWaitlistClaim();
|
|
37549
37980
|
const selectedCoursePricing = useMemo9(
|
|
37550
|
-
() => selectedCourse ? resolveCoursePricingState(
|
|
37551
|
-
|
|
37981
|
+
() => selectedCourse ? resolveCoursePricingState(
|
|
37982
|
+
selectedCourse,
|
|
37983
|
+
selectedPricingOptionId,
|
|
37984
|
+
parseCurrencyInputToCents2(selectedSlidingAmountInput)
|
|
37985
|
+
) : null,
|
|
37986
|
+
[selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
|
|
37552
37987
|
);
|
|
37553
37988
|
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
|
|
37554
37989
|
selectedCoursePricing
|
|
@@ -37621,9 +38056,13 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37621
38056
|
useEffect18(() => {
|
|
37622
38057
|
if (!selectedCourse) {
|
|
37623
38058
|
setSelectedPricingOptionId(null);
|
|
38059
|
+
setSelectedSlidingAmountInput("");
|
|
37624
38060
|
return;
|
|
37625
38061
|
}
|
|
37626
38062
|
const defaultPricing = resolveCoursePricingState(selectedCourse, null);
|
|
38063
|
+
setSelectedSlidingAmountInput(
|
|
38064
|
+
defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
|
|
38065
|
+
);
|
|
37627
38066
|
setSelectedPricingOptionId((previous) => {
|
|
37628
38067
|
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
|
|
37629
38068
|
return previous;
|
|
@@ -37998,6 +38437,8 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37998
38437
|
selectedCourse,
|
|
37999
38438
|
selectedPricingOptionId,
|
|
38000
38439
|
setSelectedPricingOptionId,
|
|
38440
|
+
selectedSlidingAmountInput,
|
|
38441
|
+
setSelectedSlidingAmountInput,
|
|
38001
38442
|
selectedCoursePricing,
|
|
38002
38443
|
setSelectedCourse,
|
|
38003
38444
|
formData,
|
|
@@ -38063,6 +38504,19 @@ var init_useCourseRegistrationWizard = __esm({
|
|
|
38063
38504
|
|
|
38064
38505
|
// ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.tsx
|
|
38065
38506
|
import { Fragment as Fragment23, jsx as jsx106, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
38507
|
+
function getCourseSlidingScaleMessage(pricing) {
|
|
38508
|
+
if (!pricing.slidingScale) {
|
|
38509
|
+
return null;
|
|
38510
|
+
}
|
|
38511
|
+
const selectedAmount = pricing.selectedSlidingAmount;
|
|
38512
|
+
if (selectedAmount === null) {
|
|
38513
|
+
return "Choose an amount to continue.";
|
|
38514
|
+
}
|
|
38515
|
+
if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
|
|
38516
|
+
return "Choose an amount within the sliding scale.";
|
|
38517
|
+
}
|
|
38518
|
+
return null;
|
|
38519
|
+
}
|
|
38066
38520
|
function CourseRegistrationWizard(props2) {
|
|
38067
38521
|
const {
|
|
38068
38522
|
showSessions = true,
|
|
@@ -38084,6 +38538,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
38084
38538
|
selectedCourse,
|
|
38085
38539
|
selectedPricingOptionId,
|
|
38086
38540
|
setSelectedPricingOptionId,
|
|
38541
|
+
selectedSlidingAmountInput,
|
|
38542
|
+
setSelectedSlidingAmountInput,
|
|
38087
38543
|
selectedCoursePricing,
|
|
38088
38544
|
formData,
|
|
38089
38545
|
setFormData,
|
|
@@ -38158,7 +38614,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
38158
38614
|
const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
|
|
38159
38615
|
const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
|
|
38160
38616
|
const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
|
|
38161
|
-
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
|
|
38617
|
+
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
|
|
38618
|
+
const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
|
|
38162
38619
|
const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
|
|
38163
38620
|
const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
|
|
38164
38621
|
course: selectedCourse,
|
|
@@ -38251,6 +38708,14 @@ function CourseRegistrationWizard(props2) {
|
|
|
38251
38708
|
onSelect: setSelectedPricingOptionId
|
|
38252
38709
|
}
|
|
38253
38710
|
),
|
|
38711
|
+
/* @__PURE__ */ jsx106(
|
|
38712
|
+
CourseSlidingScaleInput,
|
|
38713
|
+
{
|
|
38714
|
+
pricing: selectedCourseWithPricing.pricing,
|
|
38715
|
+
value: selectedSlidingAmountInput,
|
|
38716
|
+
onChange: setSelectedSlidingAmountInput
|
|
38717
|
+
}
|
|
38718
|
+
),
|
|
38254
38719
|
showSpamProtection && /* @__PURE__ */ jsx106("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx106(
|
|
38255
38720
|
AltchaWidget,
|
|
38256
38721
|
{
|
|
@@ -38288,7 +38753,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
38288
38753
|
{
|
|
38289
38754
|
type: "submit",
|
|
38290
38755
|
className: buttonClass,
|
|
38291
|
-
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
|
|
38756
|
+
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
|
|
38292
38757
|
children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
|
|
38293
38758
|
}
|
|
38294
38759
|
)
|
|
@@ -38298,6 +38763,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
38298
38763
|
),
|
|
38299
38764
|
courseSoldOut && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: "This course is fully booked and there is no waitlist available right now." }),
|
|
38300
38765
|
pricingSelectionMissing && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
|
|
38766
|
+
slidingScaleMessage && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
|
|
38301
38767
|
pricingUnavailable && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
|
|
38302
38768
|
eligibilityError && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--error", children: eligibilityError })
|
|
38303
38769
|
] })
|
|
@@ -41897,12 +42363,13 @@ var init_carousel_client = __esm({
|
|
|
41897
42363
|
]
|
|
41898
42364
|
);
|
|
41899
42365
|
const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
|
|
42366
|
+
const canAutoplay = normalized.autoplay && slides.length > 1;
|
|
41900
42367
|
const cssVars = React20.useMemo(
|
|
41901
42368
|
() => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
|
|
41902
42369
|
[normalized.slidesToShow]
|
|
41903
42370
|
);
|
|
41904
42371
|
const plugins = React20.useMemo(() => {
|
|
41905
|
-
if (!
|
|
42372
|
+
if (!canAutoplay) return void 0;
|
|
41906
42373
|
return [
|
|
41907
42374
|
Autoplay({
|
|
41908
42375
|
delay: normalized.autoplayDelay,
|
|
@@ -41912,7 +42379,7 @@ var init_carousel_client = __esm({
|
|
|
41912
42379
|
// Continue after manual navigation
|
|
41913
42380
|
})
|
|
41914
42381
|
];
|
|
41915
|
-
}, [
|
|
42382
|
+
}, [canAutoplay, normalized.autoplayDelay]);
|
|
41916
42383
|
const [viewportRef, api] = useEmblaCarousel(
|
|
41917
42384
|
{
|
|
41918
42385
|
align: "start",
|
|
@@ -41951,7 +42418,7 @@ var init_carousel_client = __esm({
|
|
|
41951
42418
|
};
|
|
41952
42419
|
}, [api]);
|
|
41953
42420
|
React20.useEffect(() => {
|
|
41954
|
-
if (!api || !
|
|
42421
|
+
if (!api || !canAutoplay) return;
|
|
41955
42422
|
const autoplayPlugin = api.plugins()?.autoplay;
|
|
41956
42423
|
if (!autoplayPlugin) return;
|
|
41957
42424
|
const handleVisibility = () => {
|
|
@@ -41960,7 +42427,7 @@ var init_carousel_client = __esm({
|
|
|
41960
42427
|
};
|
|
41961
42428
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
41962
42429
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
41963
|
-
}, [api,
|
|
42430
|
+
}, [api, canAutoplay]);
|
|
41964
42431
|
const inner = /* @__PURE__ */ jsxs81(Fragment25, { children: [
|
|
41965
42432
|
/* @__PURE__ */ jsx113("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx113(
|
|
41966
42433
|
"div",
|
|
@@ -42011,7 +42478,7 @@ var init_carousel_client = __esm({
|
|
|
42011
42478
|
"data-show-controls": normalized.showControls ? "true" : "false",
|
|
42012
42479
|
"data-show-dots": normalized.showDots ? "true" : "false",
|
|
42013
42480
|
"data-arrow-visibility": normalized.arrowVisibility,
|
|
42014
|
-
"data-autoplay":
|
|
42481
|
+
"data-autoplay": canAutoplay ? "true" : "false",
|
|
42015
42482
|
"data-loop": normalized.loop ? "true" : "false",
|
|
42016
42483
|
children: inner
|
|
42017
42484
|
}
|