@riverbankcms/sdk 0.91.0 → 0.92.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-3CI5MKV3.mjs} +2 -2
- package/dist/{PreviewEditorUI-ORCLLUNZ.mjs → PreviewEditorUI-DKEP636I.mjs} +2 -2
- package/dist/SdkPreviewModeRuntime-BRGRDQFH.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/customerMembershipOutcomes.d.ts +4 -4
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +6 -0
- 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 +7 -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-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/videoPrep.d.ts +15 -6
- package/dist/_dts/media-core/src/videoSlotPolicy.d.ts +5 -5
- 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-AFPMCLS7.mjs → chunk-6D7PLF4M.mjs} +1 -1
- package/dist/{chunk-RQUZYSES.mjs → chunk-I6EOKV6B.mjs} +520 -40
- package/dist/{chunk-S3YHJWEU.mjs → chunk-LERKJM3E.mjs} +5 -5
- package/dist/{chunk-GDT2QGIL.mjs → chunk-UOMTCHZD.mjs} +1 -1
- package/dist/cli/index.mjs +552 -80
- package/dist/client/{accordion-AFX37652.mjs → accordion-BUDH2G3S.mjs} +2 -2
- package/dist/client/{bookingForm-32V5QCOW.mjs → bookingForm-NQMCELVB.mjs} +89 -14
- package/dist/client/bookings.mjs +243 -17
- package/dist/client/{carousel-TJGQJ7ER.mjs → carousel-ONCEW6IJ.mjs} +3 -3
- package/dist/client/{cart-JUU2JEW4.mjs → cart-V2TCK2GI.mjs} +7 -7
- package/dist/client/{checkout-RD6BTFX4.mjs → checkout-ZI7SWNCS.mjs} +7 -7
- package/dist/client/{chunk-FMZZHAIR.mjs → chunk-AUMRQ242.mjs} +52 -5
- package/dist/client/{chunk-PMNAV6LO.mjs → chunk-B5UC2D6X.mjs} +7 -6
- package/dist/client/{chunk-6RN62XBV.mjs → chunk-ERQDHUS2.mjs} +1 -1
- package/dist/client/{chunk-RWYFG625.mjs → chunk-GH6IIOOE.mjs} +30 -2
- package/dist/client/{chunk-C4LP6BPG.mjs → chunk-HQWIJLYN.mjs} +1 -1
- package/dist/client/{chunk-RMOFBBNA.mjs → chunk-JXY6NHG6.mjs} +6 -6
- package/dist/client/{chunk-6QZIBNGV.mjs → chunk-KXYEKEV6.mjs} +154 -16
- package/dist/client/{chunk-E6VIWZUG.mjs → chunk-N2WJPTF7.mjs} +3 -3
- package/dist/client/{chunk-ISAUXU5R.mjs → chunk-QQNVQ62W.mjs} +1 -1
- package/dist/client/{chunk-MLBNVN4H.mjs → chunk-R3CZQLXF.mjs} +67 -4
- package/dist/client/{chunk-WHZQDPBZ.mjs → chunk-TNGL2WJF.mjs} +1 -0
- package/dist/client/{chunk-CKXEUWWA.mjs → chunk-ZJDBOLX7.mjs} +3 -3
- package/dist/client/client.mjs +515 -38
- package/dist/client/{courseRegistration-X63QAIVV.mjs → courseRegistration-JPWAQ6KM.mjs} +111 -11
- package/dist/client/{eventCalendar-5T24GCZL.mjs → eventCalendar-QDOCHBBV.mjs} +9 -9
- package/dist/client/{eventCombined-AZVTF22X.mjs → eventCombined-ZS2CXSIE.mjs} +9 -9
- package/dist/client/{eventDetails-7GPFNLGF.mjs → eventDetails-5LOBMPLN.mjs} +9 -9
- package/dist/client/{eventListing-QEUMTMUM.mjs → eventListing-SBGY4I3L.mjs} +9 -9
- package/dist/client/{eventRegistration-P2EDKCQZ.mjs → eventRegistration-XGPIU3Z2.mjs} +9 -9
- package/dist/client/{form-NUJ7H4IN.mjs → form-R7D4LZWW.mjs} +3 -3
- package/dist/client/{headerSection-JB7LECPL.mjs → headerSection-RRLYUCGC.mjs} +3 -3
- package/dist/client/hooks.mjs +22 -2
- package/dist/client/{locationMap-UEYWUCSW.mjs → locationMap-35ZJMRBZ.mjs} +3 -3
- package/dist/client/{newsletterForm-S2YZQ2X7.mjs → newsletterForm-MJ2VCFUT.mjs} +3 -3
- package/dist/client/{productDetail-H5MADGG7.mjs → productDetail-2O7YQNBX.mjs} +7 -7
- package/dist/client/{productList-DK7YON7H.mjs → productList-FDP5BH7W.mjs} +7 -7
- package/dist/client/rendering/client.mjs +495 -36
- package/dist/client/rendering/islands.mjs +19 -19
- package/dist/client/rendering.mjs +514 -37
- package/dist/client/{shop-6PA7RDRJ.mjs → shop-BGYJ3LDT.mjs} +7 -7
- package/dist/preview-next/client/runtime.mjs +3 -3
- package/dist/{sdk-runtime-JP5347OB.mjs → sdk-runtime-B3TFXRXZ.mjs} +4 -4
- package/dist/server/components.mjs +166 -7
- package/dist/server/config-validation.mjs +23 -2
- package/dist/server/config.mjs +23 -2
- package/dist/server/data.mjs +22 -2
- package/dist/server/index.mjs +1 -1
- package/dist/server/next.mjs +167 -8
- package/dist/server/page-converter.mjs +19 -2
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +166 -7
- package/dist/server/rendering.mjs +166 -7
- package/dist/server/routing.mjs +29 -5
- package/dist/server/server.mjs +23 -3
- 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/",
|
|
@@ -7098,6 +7132,7 @@ var init_booking_form_reserved_fields = __esm({
|
|
|
7098
7132
|
"selectedDate",
|
|
7099
7133
|
"selectedSlot",
|
|
7100
7134
|
"discountCode",
|
|
7135
|
+
"selectedSlidingAmountInput",
|
|
7101
7136
|
"selectedCollectionOptionKind",
|
|
7102
7137
|
"selectedAppointmentPackageId"
|
|
7103
7138
|
];
|
|
@@ -7383,6 +7418,32 @@ function readOptionalString(value) {
|
|
|
7383
7418
|
function readOptionalNumber(value) {
|
|
7384
7419
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7385
7420
|
}
|
|
7421
|
+
function getBookingServiceSlidingScale(service) {
|
|
7422
|
+
const pricing = service?.pricing;
|
|
7423
|
+
if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
|
|
7424
|
+
return null;
|
|
7425
|
+
}
|
|
7426
|
+
return {
|
|
7427
|
+
minAmount: pricing.slidingMinAmount,
|
|
7428
|
+
maxAmount: pricing.slidingMaxAmount,
|
|
7429
|
+
suggestedAmount: pricing.slidingSuggestedAmount ?? null,
|
|
7430
|
+
currency: pricing.currency
|
|
7431
|
+
};
|
|
7432
|
+
}
|
|
7433
|
+
function parseBookingCurrencyInputToCents(value) {
|
|
7434
|
+
const trimmed = value?.trim() ?? "";
|
|
7435
|
+
if (!trimmed) return null;
|
|
7436
|
+
if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
|
|
7437
|
+
const parsed = Number(trimmed);
|
|
7438
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
7439
|
+
return Math.round(parsed * 100);
|
|
7440
|
+
}
|
|
7441
|
+
function formatBookingCentsAsCurrencyInput(amount) {
|
|
7442
|
+
return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
|
|
7443
|
+
}
|
|
7444
|
+
function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
|
|
7445
|
+
return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
|
|
7446
|
+
}
|
|
7386
7447
|
function readStringArray(value) {
|
|
7387
7448
|
if (!Array.isArray(value)) return void 0;
|
|
7388
7449
|
const strings = value.filter((item) => typeof item === "string");
|
|
@@ -7571,6 +7632,20 @@ function prepareBookingSubmission(input) {
|
|
|
7571
7632
|
};
|
|
7572
7633
|
}
|
|
7573
7634
|
const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
|
|
7635
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
7636
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
7637
|
+
input.data.selectedSlidingAmountInput
|
|
7638
|
+
);
|
|
7639
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
|
|
7640
|
+
return {
|
|
7641
|
+
ok: false,
|
|
7642
|
+
error: {
|
|
7643
|
+
tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
|
|
7644
|
+
serviceId,
|
|
7645
|
+
serviceTitle: selectedService.title || serviceId
|
|
7646
|
+
}
|
|
7647
|
+
};
|
|
7648
|
+
}
|
|
7574
7649
|
if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
|
|
7575
7650
|
return {
|
|
7576
7651
|
ok: false,
|
|
@@ -7598,6 +7673,7 @@ function prepareBookingSubmission(input) {
|
|
|
7598
7673
|
...common,
|
|
7599
7674
|
kind: "standard",
|
|
7600
7675
|
...discountCode ? { discountCode } : {},
|
|
7676
|
+
...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
|
|
7601
7677
|
...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
|
|
7602
7678
|
altchaSolution: input.altchaSolution ?? null
|
|
7603
7679
|
}
|
|
@@ -7611,6 +7687,10 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
7611
7687
|
return `Service not found: ${error.serviceId}`;
|
|
7612
7688
|
case "payment-option-required":
|
|
7613
7689
|
return `Please choose how you want to pay for "${error.serviceTitle}".`;
|
|
7690
|
+
case "sliding-amount-required":
|
|
7691
|
+
return `Please choose an amount for "${error.serviceTitle}".`;
|
|
7692
|
+
case "sliding-amount-out-of-range":
|
|
7693
|
+
return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
7614
7694
|
case "payment-option-unsupported":
|
|
7615
7695
|
return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
7616
7696
|
case "service-missing-duration":
|
|
@@ -7831,6 +7911,7 @@ var init_booking_form_interactive = __esm({
|
|
|
7831
7911
|
title: z10.string(),
|
|
7832
7912
|
description: z10.string().nullable().optional().transform((value) => value ?? void 0),
|
|
7833
7913
|
durationMinutes: z10.number().optional(),
|
|
7914
|
+
pricing: z10.custom().optional(),
|
|
7834
7915
|
priceAmount: z10.number().nullable().optional(),
|
|
7835
7916
|
priceCurrency: z10.string().nullable().optional(),
|
|
7836
7917
|
paymentTerms: blockBookingPaymentTermsSchema.optional(),
|
|
@@ -8117,9 +8198,12 @@ var init_schemas = __esm({
|
|
|
8117
8198
|
});
|
|
8118
8199
|
coursePricingSchema = z11.object({
|
|
8119
8200
|
bookingRequirement: z11.enum(["none", "required"]),
|
|
8120
|
-
pricingStrategy: z11.enum(["free", "single", "tiered"]),
|
|
8201
|
+
pricingStrategy: z11.enum(["free", "single", "tiered", "sliding_scale"]),
|
|
8121
8202
|
currency: z11.string(),
|
|
8122
8203
|
singlePriceAmount: z11.number().nullable(),
|
|
8204
|
+
slidingMinAmount: z11.number().nullable().optional(),
|
|
8205
|
+
slidingMaxAmount: z11.number().nullable().optional(),
|
|
8206
|
+
slidingSuggestedAmount: z11.number().nullable().optional(),
|
|
8123
8207
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
8124
8208
|
options: z11.array(coursePricingOptionSchema)
|
|
8125
8209
|
});
|
|
@@ -8181,7 +8265,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
8181
8265
|
return left.name.localeCompare(right.name);
|
|
8182
8266
|
});
|
|
8183
8267
|
}
|
|
8184
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
|
|
8268
|
+
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
8269
|
+
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
8270
|
+
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
8185
8271
|
const currency = course.pricing?.currency ?? course.currency;
|
|
8186
8272
|
if (!course.pricing) {
|
|
8187
8273
|
const legacyAmount = course.priceCents ?? 0;
|
|
@@ -8191,6 +8277,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8191
8277
|
selectableOptions: [],
|
|
8192
8278
|
requiresSelection: false,
|
|
8193
8279
|
selectedOption: null,
|
|
8280
|
+
slidingScale: null,
|
|
8281
|
+
selectedSlidingAmount: null,
|
|
8194
8282
|
selectedPriceAmount: legacyAmount,
|
|
8195
8283
|
selectedRequiresPayment: legacyAmount > 0,
|
|
8196
8284
|
hasPaidSelection: legacyAmount > 0,
|
|
@@ -8205,6 +8293,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8205
8293
|
selectableOptions: [],
|
|
8206
8294
|
requiresSelection: false,
|
|
8207
8295
|
selectedOption: null,
|
|
8296
|
+
slidingScale: null,
|
|
8297
|
+
selectedSlidingAmount: null,
|
|
8208
8298
|
selectedPriceAmount: 0,
|
|
8209
8299
|
selectedRequiresPayment: false,
|
|
8210
8300
|
hasPaidSelection: false,
|
|
@@ -8218,6 +8308,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8218
8308
|
selectableOptions: [],
|
|
8219
8309
|
requiresSelection: false,
|
|
8220
8310
|
selectedOption: null,
|
|
8311
|
+
slidingScale: null,
|
|
8312
|
+
selectedSlidingAmount: null,
|
|
8221
8313
|
selectedPriceAmount: amount,
|
|
8222
8314
|
selectedRequiresPayment: amount > 0,
|
|
8223
8315
|
hasPaidSelection: amount > 0,
|
|
@@ -8227,7 +8319,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8227
8319
|
case "tiered": {
|
|
8228
8320
|
const selectableOptions = getSelectableCoursePricingOptionsForNow(
|
|
8229
8321
|
course,
|
|
8230
|
-
resolvePlanningDateInput(
|
|
8322
|
+
resolvePlanningDateInput(effectiveNowInput)
|
|
8231
8323
|
);
|
|
8232
8324
|
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
8233
8325
|
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
@@ -8243,12 +8335,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
8243
8335
|
selectableOptions,
|
|
8244
8336
|
requiresSelection: selectableOptions.length > 1,
|
|
8245
8337
|
selectedOption,
|
|
8338
|
+
slidingScale: null,
|
|
8339
|
+
selectedSlidingAmount: null,
|
|
8246
8340
|
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
8247
8341
|
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
8248
8342
|
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
8249
8343
|
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
8250
8344
|
};
|
|
8251
8345
|
}
|
|
8346
|
+
case "sliding_scale": {
|
|
8347
|
+
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
8348
|
+
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
8349
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
|
|
8350
|
+
return {
|
|
8351
|
+
currency,
|
|
8352
|
+
display: { kind: "unavailable", currency },
|
|
8353
|
+
selectableOptions: [],
|
|
8354
|
+
requiresSelection: true,
|
|
8355
|
+
selectedOption: null,
|
|
8356
|
+
slidingScale: null,
|
|
8357
|
+
selectedSlidingAmount: null,
|
|
8358
|
+
selectedPriceAmount: null,
|
|
8359
|
+
selectedRequiresPayment: false,
|
|
8360
|
+
hasPaidSelection: false,
|
|
8361
|
+
hasFreeSelection: false
|
|
8362
|
+
};
|
|
8363
|
+
}
|
|
8364
|
+
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
8365
|
+
return {
|
|
8366
|
+
currency,
|
|
8367
|
+
display: { kind: "range", minAmount, maxAmount, currency },
|
|
8368
|
+
selectableOptions: [],
|
|
8369
|
+
requiresSelection: normalizedSelectedAmount === null,
|
|
8370
|
+
selectedOption: null,
|
|
8371
|
+
slidingScale: {
|
|
8372
|
+
minAmount,
|
|
8373
|
+
maxAmount,
|
|
8374
|
+
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
8375
|
+
},
|
|
8376
|
+
selectedSlidingAmount: normalizedSelectedAmount,
|
|
8377
|
+
selectedPriceAmount: normalizedSelectedAmount,
|
|
8378
|
+
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
8379
|
+
hasPaidSelection: maxAmount > 0,
|
|
8380
|
+
hasFreeSelection: minAmount === 0
|
|
8381
|
+
};
|
|
8382
|
+
}
|
|
8252
8383
|
}
|
|
8253
8384
|
}
|
|
8254
8385
|
function formatCoursePriceDisplay(display, locale) {
|
|
@@ -8357,7 +8488,7 @@ function isRecord7(value) {
|
|
|
8357
8488
|
}
|
|
8358
8489
|
function isPublicEventPricing(value) {
|
|
8359
8490
|
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";
|
|
8491
|
+
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
8492
|
}
|
|
8362
8493
|
function isPublicEventTicketType(value) {
|
|
8363
8494
|
return isRecord7(value) && typeof value.id === "string";
|
|
@@ -10388,6 +10519,19 @@ var init_schemas2 = __esm({
|
|
|
10388
10519
|
ticketTypes: z14.array(publicEventTicketTypeSchema),
|
|
10389
10520
|
display: publicEventTicketTypePriceDisplaySchema
|
|
10390
10521
|
}),
|
|
10522
|
+
z14.object({
|
|
10523
|
+
kind: z14.literal("sliding_scale"),
|
|
10524
|
+
minAmount: z14.number(),
|
|
10525
|
+
maxAmount: z14.number(),
|
|
10526
|
+
suggestedAmount: z14.number().nullable(),
|
|
10527
|
+
currency: z14.string(),
|
|
10528
|
+
display: z14.object({
|
|
10529
|
+
kind: z14.literal("range"),
|
|
10530
|
+
minAmount: z14.number(),
|
|
10531
|
+
maxAmount: z14.number(),
|
|
10532
|
+
currency: z14.string()
|
|
10533
|
+
})
|
|
10534
|
+
}),
|
|
10391
10535
|
z14.object({
|
|
10392
10536
|
kind: z14.literal("course"),
|
|
10393
10537
|
display: z14.object({ kind: z14.literal("course"), display: publicCoursePriceDisplaySchema })
|
|
@@ -28331,6 +28475,7 @@ function useBookingSubmission(_siteId) {
|
|
|
28331
28475
|
customFields: data.customFields,
|
|
28332
28476
|
timezone: data.timezone,
|
|
28333
28477
|
discountCode: data.discountCode,
|
|
28478
|
+
selectedSlidingAmount: data.selectedSlidingAmount,
|
|
28334
28479
|
selectedCollectionOptionKind: data.selectedCollectionOptionKind,
|
|
28335
28480
|
altchaSolution: data.altchaSolution ?? null,
|
|
28336
28481
|
successUrl: data.successUrl,
|
|
@@ -28859,6 +29004,9 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
28859
29004
|
fieldValues: collectInitialFieldValues(initialData),
|
|
28860
29005
|
touchedFields: {},
|
|
28861
29006
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
29007
|
+
selectedSlidingAmountInput: toOptionalString(
|
|
29008
|
+
initialData.selectedSlidingAmountInput
|
|
29009
|
+
) ?? "",
|
|
28862
29010
|
selectedCollectionOptionKind: toSelectedCollectionOptionKind(
|
|
28863
29011
|
initialData.selectedCollectionOptionKind
|
|
28864
29012
|
),
|
|
@@ -28911,6 +29059,7 @@ function bookingFlowReducer(state, event) {
|
|
|
28911
29059
|
selectedDate: void 0,
|
|
28912
29060
|
selectedSlot: null,
|
|
28913
29061
|
selectedAppointmentPackageId: void 0,
|
|
29062
|
+
selectedSlidingAmountInput: "",
|
|
28914
29063
|
selectedCollectionOptionKind: void 0,
|
|
28915
29064
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
28916
29065
|
};
|
|
@@ -28964,6 +29113,13 @@ function bookingFlowReducer(state, event) {
|
|
|
28964
29113
|
selectedAppointmentPackageId: void 0,
|
|
28965
29114
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
28966
29115
|
};
|
|
29116
|
+
case "sliding-amount-changed":
|
|
29117
|
+
return {
|
|
29118
|
+
...state,
|
|
29119
|
+
selectedSlidingAmountInput: event.value,
|
|
29120
|
+
selectedAppointmentPackageId: void 0,
|
|
29121
|
+
validationErrors: clearBookingFormError(state.validationErrors)
|
|
29122
|
+
};
|
|
28967
29123
|
case "appointment-package-selected":
|
|
28968
29124
|
return {
|
|
28969
29125
|
...state,
|
|
@@ -29066,6 +29222,7 @@ function toBookingFormData(state) {
|
|
|
29066
29222
|
selectedDate: state.selectedDate,
|
|
29067
29223
|
selectedSlot: state.selectedSlot?.startAt,
|
|
29068
29224
|
discountCode: state.discountCode || void 0,
|
|
29225
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
|
|
29069
29226
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
29070
29227
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId
|
|
29071
29228
|
};
|
|
@@ -29083,7 +29240,8 @@ function buildBookingStepResolution(input) {
|
|
|
29083
29240
|
input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
|
|
29084
29241
|
);
|
|
29085
29242
|
const selectedService = paymentResolution.service;
|
|
29086
|
-
const
|
|
29243
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29244
|
+
const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
|
|
29087
29245
|
input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
29088
29246
|
);
|
|
29089
29247
|
const hasFields = Boolean(input.form.schema?.fields.length);
|
|
@@ -29127,6 +29285,18 @@ function validateBookingStep(input) {
|
|
|
29127
29285
|
services: input.services,
|
|
29128
29286
|
defaultServiceId: input.defaultServiceId
|
|
29129
29287
|
});
|
|
29288
|
+
const slidingScale = getBookingServiceSlidingScale(resolution.service);
|
|
29289
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(
|
|
29290
|
+
slidingScale,
|
|
29291
|
+
parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
|
|
29292
|
+
)) {
|
|
29293
|
+
return {
|
|
29294
|
+
ok: false,
|
|
29295
|
+
errors: createFormBookingValidationError(
|
|
29296
|
+
"Please choose an amount within the sliding scale"
|
|
29297
|
+
)
|
|
29298
|
+
};
|
|
29299
|
+
}
|
|
29130
29300
|
if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
|
|
29131
29301
|
return { ok: true };
|
|
29132
29302
|
}
|
|
@@ -29525,6 +29695,7 @@ var init_useHeadlessBookingFlow_state = __esm({
|
|
|
29525
29695
|
"../blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.ts"() {
|
|
29526
29696
|
"use strict";
|
|
29527
29697
|
init_booking_form_headless_state();
|
|
29698
|
+
init_booking_form_state();
|
|
29528
29699
|
}
|
|
29529
29700
|
});
|
|
29530
29701
|
|
|
@@ -29564,11 +29735,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
29564
29735
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
29565
29736
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
29566
29737
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
29738
|
+
const lastSlidingServiceIdRef = useRef6(null);
|
|
29739
|
+
useEffect6(() => {
|
|
29740
|
+
const selectedId = selectedService?.id ?? null;
|
|
29741
|
+
if (lastSlidingServiceIdRef.current === selectedId) return;
|
|
29742
|
+
lastSlidingServiceIdRef.current = selectedId;
|
|
29743
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29744
|
+
dispatch({
|
|
29745
|
+
type: "sliding-amount-changed",
|
|
29746
|
+
value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
29747
|
+
});
|
|
29748
|
+
}, [selectedService]);
|
|
29567
29749
|
const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
|
|
29750
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29751
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
29752
|
+
state.selectedSlidingAmountInput
|
|
29753
|
+
);
|
|
29754
|
+
const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
|
|
29568
29755
|
const canLoadAppointmentPackages = Boolean(
|
|
29569
|
-
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
29756
|
+
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
|
|
29570
29757
|
);
|
|
29571
|
-
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
29758
|
+
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
29572
29759
|
const data = useMemo2(() => toBookingFormData(state), [state]);
|
|
29573
29760
|
const availabilityDatesQuery = useMemo2(
|
|
29574
29761
|
() => buildBookingAvailabilityQuery({
|
|
@@ -29798,13 +29985,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
29798
29985
|
state.selectedSlot
|
|
29799
29986
|
]);
|
|
29800
29987
|
const appointmentDiscountContext = useMemo2(
|
|
29801
|
-
() => selectedService &&
|
|
29802
|
-
[
|
|
29988
|
+
() => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
29989
|
+
[selectedAppointmentPriceAmount, selectedService?.id]
|
|
29803
29990
|
);
|
|
29804
29991
|
const discountUi = useDiscountCodeUi({
|
|
29805
29992
|
api,
|
|
29806
29993
|
discountContext: appointmentDiscountContext,
|
|
29807
|
-
subtotalCents:
|
|
29994
|
+
subtotalCents: selectedAppointmentPriceAmount
|
|
29808
29995
|
});
|
|
29809
29996
|
const { submit, clearFeedback } = useBookingSubmission(options.siteId);
|
|
29810
29997
|
const submittingRef = useRef6(false);
|
|
@@ -29947,6 +30134,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
29947
30134
|
type: "appointment-package-selected",
|
|
29948
30135
|
packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
|
|
29949
30136
|
}),
|
|
30137
|
+
setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
|
|
29950
30138
|
setDiscountCode: (code) => {
|
|
29951
30139
|
dispatch({ type: "discount-code-changed", code });
|
|
29952
30140
|
latestRef.current.setDiscountCode(code);
|
|
@@ -30017,11 +30205,11 @@ function useHeadlessBookingFlow(options) {
|
|
|
30017
30205
|
() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
30018
30206
|
serviceTitle: selectedService.title,
|
|
30019
30207
|
paymentTerms: selectedService.paymentTerms,
|
|
30020
|
-
priceAmount:
|
|
30208
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
30021
30209
|
priceCurrency: selectedService.priceCurrency,
|
|
30022
30210
|
bookingStartAt: state.selectedSlot?.startAt
|
|
30023
30211
|
}) : null,
|
|
30024
|
-
[paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
|
|
30212
|
+
[paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
|
|
30025
30213
|
);
|
|
30026
30214
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
30027
30215
|
const selectedAppointmentPackage = appointmentPackageItems.find(
|
|
@@ -30050,6 +30238,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
30050
30238
|
selection: null,
|
|
30051
30239
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
30052
30240
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
30241
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
30242
|
+
selectedSlidingAmount,
|
|
30243
|
+
slidingScale: selectedServiceSlidingScale,
|
|
30053
30244
|
appointmentPackages: appointmentPackagesModel,
|
|
30054
30245
|
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
30055
30246
|
} : {
|
|
@@ -30058,6 +30249,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
30058
30249
|
selection: paymentSelection,
|
|
30059
30250
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
30060
30251
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
30252
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
30253
|
+
selectedSlidingAmount,
|
|
30254
|
+
slidingScale: selectedServiceSlidingScale,
|
|
30061
30255
|
appointmentPackages: appointmentPackagesModel
|
|
30062
30256
|
};
|
|
30063
30257
|
return {
|
|
@@ -30672,6 +30866,9 @@ var init_FieldValidationMessage = __esm({
|
|
|
30672
30866
|
|
|
30673
30867
|
// ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
30674
30868
|
import { Fragment as Fragment9, jsx as jsx62, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
30869
|
+
function formatBookingAmount(amount, currency) {
|
|
30870
|
+
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
30871
|
+
}
|
|
30675
30872
|
function HeadlessBookingDefaultForm({
|
|
30676
30873
|
booking,
|
|
30677
30874
|
onSubmit
|
|
@@ -30948,6 +31145,7 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
30948
31145
|
}
|
|
30949
31146
|
const packageOptions = booking.payment.appointmentPackages.items;
|
|
30950
31147
|
const hasPackageOptions = packageOptions.length > 0;
|
|
31148
|
+
const slidingScale = booking.payment.slidingScale;
|
|
30951
31149
|
return /* @__PURE__ */ jsxs46("div", { className: "ab-stack", children: [
|
|
30952
31150
|
/* @__PURE__ */ jsxs46("div", { className: "ab-info-box", children: [
|
|
30953
31151
|
/* @__PURE__ */ jsx62("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
|
|
@@ -30958,6 +31156,28 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
30958
31156
|
booking.payment.appointmentPackages.state.message,
|
|
30959
31157
|
" You can continue with the normal payment option."
|
|
30960
31158
|
] }) : null,
|
|
31159
|
+
slidingScale ? /* @__PURE__ */ jsxs46("div", { className: "rb-space-y-2", children: [
|
|
31160
|
+
/* @__PURE__ */ jsx62("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
|
|
31161
|
+
/* @__PURE__ */ jsxs46("p", { className: "rb-caption status-muted", children: [
|
|
31162
|
+
formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
|
|
31163
|
+
" to ",
|
|
31164
|
+
formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
|
|
31165
|
+
slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
|
|
31166
|
+
] }),
|
|
31167
|
+
/* @__PURE__ */ jsx62(
|
|
31168
|
+
"input",
|
|
31169
|
+
{
|
|
31170
|
+
id: "appointment-sliding-amount",
|
|
31171
|
+
type: "number",
|
|
31172
|
+
className: "form-input",
|
|
31173
|
+
min: slidingScale.minAmount / 100,
|
|
31174
|
+
max: slidingScale.maxAmount / 100,
|
|
31175
|
+
step: "0.01",
|
|
31176
|
+
value: booking.payment.selectedSlidingAmountInput,
|
|
31177
|
+
onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
|
|
31178
|
+
}
|
|
31179
|
+
)
|
|
31180
|
+
] }) : null,
|
|
30961
31181
|
/* @__PURE__ */ jsxs46("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
|
|
30962
31182
|
packageOptions.map((appointmentPackage) => {
|
|
30963
31183
|
const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
|
|
@@ -32893,6 +33113,7 @@ function useEligibility(params) {
|
|
|
32893
33113
|
occurrenceId: params.occurrenceId,
|
|
32894
33114
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
32895
33115
|
ticketTypeId: params.ticketTypeId ?? void 0,
|
|
33116
|
+
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
32896
33117
|
email: params.email.trim().toLowerCase(),
|
|
32897
33118
|
ticketsCount: params.ticketsCount
|
|
32898
33119
|
});
|
|
@@ -32913,7 +33134,7 @@ function useEligibility(params) {
|
|
|
32913
33134
|
return () => {
|
|
32914
33135
|
cancelled = true;
|
|
32915
33136
|
};
|
|
32916
|
-
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
|
|
33137
|
+
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
|
|
32917
33138
|
return {
|
|
32918
33139
|
state,
|
|
32919
33140
|
eligibility: state.eligibility,
|
|
@@ -33264,6 +33485,41 @@ function TicketCounterLimit(props2) {
|
|
|
33264
33485
|
] }) : null
|
|
33265
33486
|
] });
|
|
33266
33487
|
}
|
|
33488
|
+
function formatCurrencyInputAmount(amount) {
|
|
33489
|
+
const major = amount / 100;
|
|
33490
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
33491
|
+
}
|
|
33492
|
+
function SlidingScaleAmountField(props2) {
|
|
33493
|
+
const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
|
|
33494
|
+
const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
|
|
33495
|
+
const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
|
|
33496
|
+
return /* @__PURE__ */ jsxs54("div", { className: "er-field", children: [
|
|
33497
|
+
/* @__PURE__ */ jsx77("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
|
|
33498
|
+
/* @__PURE__ */ jsx77(
|
|
33499
|
+
"input",
|
|
33500
|
+
{
|
|
33501
|
+
id: "er-sliding-amount",
|
|
33502
|
+
type: "number",
|
|
33503
|
+
min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
|
|
33504
|
+
max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
|
|
33505
|
+
step: "0.01",
|
|
33506
|
+
inputMode: "decimal",
|
|
33507
|
+
className: "er-input",
|
|
33508
|
+
value: props2.value,
|
|
33509
|
+
onChange: (event) => props2.onChange?.(event.target.value)
|
|
33510
|
+
}
|
|
33511
|
+
),
|
|
33512
|
+
/* @__PURE__ */ jsxs54("p", { className: "er-text er-text--muted", children: [
|
|
33513
|
+
"Choose between ",
|
|
33514
|
+
minLabel,
|
|
33515
|
+
" and ",
|
|
33516
|
+
maxLabel,
|
|
33517
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
33518
|
+
"."
|
|
33519
|
+
] }),
|
|
33520
|
+
props2.message ? /* @__PURE__ */ jsx77("p", { className: "er-text er-text--muted", children: props2.message }) : null
|
|
33521
|
+
] });
|
|
33522
|
+
}
|
|
33267
33523
|
function getTicketTypeCounterAvailabilityLabel(input) {
|
|
33268
33524
|
if (input.selectedRemainingCapacity !== null) {
|
|
33269
33525
|
return `${input.selectedRemainingCapacity} remaining for this ticket type`;
|
|
@@ -33335,6 +33591,10 @@ var init_TicketSelectionStep = __esm({
|
|
|
33335
33591
|
maxTickets,
|
|
33336
33592
|
selectedTicketTypeId = null,
|
|
33337
33593
|
onTicketTypeChange,
|
|
33594
|
+
slidingScale = null,
|
|
33595
|
+
selectedSlidingAmountInput = "",
|
|
33596
|
+
slidingScaleSelectionMessage = null,
|
|
33597
|
+
onSlidingAmountChange,
|
|
33338
33598
|
onTicketsChange
|
|
33339
33599
|
}) => {
|
|
33340
33600
|
const deliveryMode = event?.deliveryMode ?? "in_person";
|
|
@@ -33450,6 +33710,16 @@ var init_TicketSelectionStep = __esm({
|
|
|
33450
33710
|
] })
|
|
33451
33711
|
] })
|
|
33452
33712
|
] }) : /* @__PURE__ */ jsxs54(Fragment12, { children: [
|
|
33713
|
+
slidingScale ? /* @__PURE__ */ jsx77(
|
|
33714
|
+
SlidingScaleAmountField,
|
|
33715
|
+
{
|
|
33716
|
+
slidingScale,
|
|
33717
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
|
|
33718
|
+
value: selectedSlidingAmountInput,
|
|
33719
|
+
message: slidingScaleSelectionMessage,
|
|
33720
|
+
onChange: onSlidingAmountChange
|
|
33721
|
+
}
|
|
33722
|
+
) : null,
|
|
33453
33723
|
/* @__PURE__ */ jsx77("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
|
|
33454
33724
|
/* @__PURE__ */ jsxs54("div", { className: "er-ticket-counter-group", children: [
|
|
33455
33725
|
/* @__PURE__ */ jsx77(
|
|
@@ -34826,6 +35096,10 @@ function EventRegistrationWizardContent(props2) {
|
|
|
34826
35096
|
maxTickets: wizard.maxTicketsNum,
|
|
34827
35097
|
selectedTicketTypeId: wizard.selectedTicketTypeId,
|
|
34828
35098
|
onTicketTypeChange: wizard.setSelectedTicketTypeId,
|
|
35099
|
+
slidingScale: wizard.selectedEventSlidingScale,
|
|
35100
|
+
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
35101
|
+
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
35102
|
+
onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
|
|
34829
35103
|
onTicketsChange: wizard.setTicketsCount
|
|
34830
35104
|
}
|
|
34831
35105
|
)
|
|
@@ -35042,7 +35316,7 @@ function EventRegistrationSummaryBar(props2) {
|
|
|
35042
35316
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
35043
35317
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
35044
35318
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
35045
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
35319
|
+
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
35046
35320
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
|
|
35047
35321
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
35048
35322
|
const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
|
|
@@ -35493,6 +35767,7 @@ function useEventRegistrationSubmit(options) {
|
|
|
35493
35767
|
occurrenceId: submitOccurrenceId,
|
|
35494
35768
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
35495
35769
|
ticketTypeId: options.selectedTicketTypeId ?? void 0,
|
|
35770
|
+
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
35496
35771
|
email: options.formData.email.trim().toLowerCase(),
|
|
35497
35772
|
name: options.formData.name.trim(),
|
|
35498
35773
|
ticketsCount: options.ticketsCount,
|
|
@@ -35602,6 +35877,35 @@ var init_useEventRegistrationSubmit = __esm({
|
|
|
35602
35877
|
|
|
35603
35878
|
// ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
35604
35879
|
import { useCallback as useCallback7, useEffect as useEffect14, useMemo as useMemo7, useReducer as useReducer9, useState as useState4 } from "react";
|
|
35880
|
+
function parseCurrencyInputToCents(value) {
|
|
35881
|
+
const trimmed = value.trim();
|
|
35882
|
+
if (!trimmed) return null;
|
|
35883
|
+
const amount = Number(trimmed);
|
|
35884
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
35885
|
+
return Math.round(amount * 100);
|
|
35886
|
+
}
|
|
35887
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
35888
|
+
const major = amount / 100;
|
|
35889
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
35890
|
+
}
|
|
35891
|
+
function getSlidingScaleForEvent(event) {
|
|
35892
|
+
const pricing = event ? resolveRuntimeEventPricing(event) : null;
|
|
35893
|
+
return pricing?.kind === "sliding_scale" ? {
|
|
35894
|
+
minAmount: pricing.minAmount,
|
|
35895
|
+
maxAmount: pricing.maxAmount,
|
|
35896
|
+
suggestedAmount: pricing.suggestedAmount
|
|
35897
|
+
} : null;
|
|
35898
|
+
}
|
|
35899
|
+
function getSlidingScaleSelectionMessage(input) {
|
|
35900
|
+
if (!input.slidingScale) return null;
|
|
35901
|
+
if (input.selectedAmount === null) {
|
|
35902
|
+
return "Choose an amount to continue.";
|
|
35903
|
+
}
|
|
35904
|
+
if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
|
|
35905
|
+
return "Choose an amount within the sliding scale.";
|
|
35906
|
+
}
|
|
35907
|
+
return null;
|
|
35908
|
+
}
|
|
35605
35909
|
function useEventRegistrationWizard(options) {
|
|
35606
35910
|
const api = useBlockApi();
|
|
35607
35911
|
const registrationEvents = useMemo7(
|
|
@@ -35646,6 +35950,10 @@ function useEventRegistrationWizard(options) {
|
|
|
35646
35950
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
35647
35951
|
);
|
|
35648
35952
|
const [selectedTicketTypeId, setSelectedTicketTypeId] = useState4(null);
|
|
35953
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState4(() => {
|
|
35954
|
+
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
35955
|
+
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
35956
|
+
});
|
|
35649
35957
|
const [registrationResult, setRegistrationResult] = useState4(null);
|
|
35650
35958
|
const [errorMessage, setErrorMessage] = useState4("");
|
|
35651
35959
|
const [altchaSolution, setAltchaSolution] = useState4(null);
|
|
@@ -35682,6 +35990,7 @@ function useEventRegistrationWizard(options) {
|
|
|
35682
35990
|
occurrenceId,
|
|
35683
35991
|
attendanceMode: selectedAttendanceMode,
|
|
35684
35992
|
ticketTypeId: selectedTicketTypeId,
|
|
35993
|
+
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
35685
35994
|
email: formData.email,
|
|
35686
35995
|
ticketsCount
|
|
35687
35996
|
});
|
|
@@ -35817,6 +36126,18 @@ function useEventRegistrationWizard(options) {
|
|
|
35817
36126
|
}),
|
|
35818
36127
|
[selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
|
|
35819
36128
|
);
|
|
36129
|
+
const selectedSlidingAmount = useMemo7(
|
|
36130
|
+
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
36131
|
+
[selectedSlidingAmountInput]
|
|
36132
|
+
);
|
|
36133
|
+
const selectedEventSlidingScale = useMemo7(
|
|
36134
|
+
() => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
|
|
36135
|
+
[selectedEvent, preSelectedEvent]
|
|
36136
|
+
);
|
|
36137
|
+
const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
|
|
36138
|
+
slidingScale: selectedEventSlidingScale,
|
|
36139
|
+
selectedAmount: selectedSlidingAmount
|
|
36140
|
+
});
|
|
35820
36141
|
const ticketTypeSelectionRequired = useMemo7(() => {
|
|
35821
36142
|
const event = selectedEvent ?? preSelectedEvent;
|
|
35822
36143
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
@@ -35885,12 +36206,24 @@ function useEventRegistrationWizard(options) {
|
|
|
35885
36206
|
setGuestSectionShake(false);
|
|
35886
36207
|
};
|
|
35887
36208
|
const eventRequiresPayment = useMemo7(
|
|
35888
|
-
() =>
|
|
36209
|
+
() => {
|
|
36210
|
+
if (selectedEventSlidingScale) {
|
|
36211
|
+
return (selectedSlidingAmount ?? 0) > 0;
|
|
36212
|
+
}
|
|
36213
|
+
return resolveEventRequiresPayment({
|
|
36214
|
+
eligibility,
|
|
36215
|
+
selectedTicketType,
|
|
36216
|
+
event: selectedEvent ?? preSelectedEvent
|
|
36217
|
+
});
|
|
36218
|
+
},
|
|
36219
|
+
[
|
|
35889
36220
|
eligibility,
|
|
35890
36221
|
selectedTicketType,
|
|
35891
|
-
|
|
35892
|
-
|
|
35893
|
-
|
|
36222
|
+
selectedEvent,
|
|
36223
|
+
preSelectedEvent,
|
|
36224
|
+
selectedEventSlidingScale,
|
|
36225
|
+
selectedSlidingAmount
|
|
36226
|
+
]
|
|
35894
36227
|
);
|
|
35895
36228
|
const handleDetailsComplete = async () => {
|
|
35896
36229
|
if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
|
|
@@ -35899,6 +36232,11 @@ function useEventRegistrationWizard(options) {
|
|
|
35899
36232
|
setStep("error");
|
|
35900
36233
|
return { ok: false, reason: "blocked", message };
|
|
35901
36234
|
}
|
|
36235
|
+
if (slidingScaleSelectionMessage) {
|
|
36236
|
+
setErrorMessage(slidingScaleSelectionMessage);
|
|
36237
|
+
setStep("error");
|
|
36238
|
+
return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
|
|
36239
|
+
}
|
|
35902
36240
|
if (!validateForm()) {
|
|
35903
36241
|
setGuestSectionShake(true);
|
|
35904
36242
|
return {
|
|
@@ -35983,9 +36321,18 @@ function useEventRegistrationWizard(options) {
|
|
|
35983
36321
|
const discountSubtotalCents = useMemo7(() => {
|
|
35984
36322
|
if (discountContext?.type !== "event") return void 0;
|
|
35985
36323
|
const event = selectedEvent ?? preSelectedEvent;
|
|
35986
|
-
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
36324
|
+
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
35987
36325
|
return Math.max(0, eventPriceCents * ticketsCount);
|
|
35988
|
-
}, [
|
|
36326
|
+
}, [
|
|
36327
|
+
discountContext,
|
|
36328
|
+
selectedTicketType,
|
|
36329
|
+
eligibility,
|
|
36330
|
+
selectedEvent,
|
|
36331
|
+
preSelectedEvent,
|
|
36332
|
+
selectedEventSlidingScale,
|
|
36333
|
+
selectedSlidingAmount,
|
|
36334
|
+
ticketsCount
|
|
36335
|
+
]);
|
|
35989
36336
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
35990
36337
|
const selectionMethod = paymentSelection.method;
|
|
35991
36338
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -35994,6 +36341,7 @@ function useEventRegistrationWizard(options) {
|
|
|
35994
36341
|
registrationTarget,
|
|
35995
36342
|
selectedAttendanceMode,
|
|
35996
36343
|
selectedTicketTypeId,
|
|
36344
|
+
selectedSlidingAmount,
|
|
35997
36345
|
ticketsCount,
|
|
35998
36346
|
formData,
|
|
35999
36347
|
altchaSolution,
|
|
@@ -36008,6 +36356,10 @@ function useEventRegistrationWizard(options) {
|
|
|
36008
36356
|
});
|
|
36009
36357
|
const handleEventSelect = (event) => {
|
|
36010
36358
|
setSelectedEvent(event);
|
|
36359
|
+
const slidingScale = getSlidingScaleForEvent(event);
|
|
36360
|
+
setSelectedSlidingAmountInput(
|
|
36361
|
+
slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
36362
|
+
);
|
|
36011
36363
|
setSelectedAttendanceMode(
|
|
36012
36364
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
36013
36365
|
);
|
|
@@ -36017,6 +36369,7 @@ function useEventRegistrationWizard(options) {
|
|
|
36017
36369
|
const handleRetry = () => {
|
|
36018
36370
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
36019
36371
|
setSelectedTicketTypeId(null);
|
|
36372
|
+
setSelectedSlidingAmountInput("");
|
|
36020
36373
|
setSelectedAttendanceMode(
|
|
36021
36374
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
36022
36375
|
);
|
|
@@ -36053,6 +36406,11 @@ function useEventRegistrationWizard(options) {
|
|
|
36053
36406
|
setSelectedAttendanceMode,
|
|
36054
36407
|
selectedTicketTypeId,
|
|
36055
36408
|
setSelectedTicketTypeId,
|
|
36409
|
+
selectedSlidingAmountInput,
|
|
36410
|
+
setSelectedSlidingAmountInput,
|
|
36411
|
+
selectedSlidingAmount,
|
|
36412
|
+
selectedEventSlidingScale,
|
|
36413
|
+
slidingScaleSelectionMessage,
|
|
36056
36414
|
selectedTicketType,
|
|
36057
36415
|
visibleTicketTypes,
|
|
36058
36416
|
ticketTypeSelectionRequired,
|
|
@@ -37368,6 +37726,44 @@ function CoursePricingSelector({
|
|
|
37368
37726
|
)
|
|
37369
37727
|
] });
|
|
37370
37728
|
}
|
|
37729
|
+
function CourseSlidingScaleInput({
|
|
37730
|
+
pricing,
|
|
37731
|
+
value,
|
|
37732
|
+
onChange
|
|
37733
|
+
}) {
|
|
37734
|
+
const slidingScale = pricing.slidingScale;
|
|
37735
|
+
if (!slidingScale) {
|
|
37736
|
+
return null;
|
|
37737
|
+
}
|
|
37738
|
+
const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
|
|
37739
|
+
const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
|
|
37740
|
+
const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
|
|
37741
|
+
return /* @__PURE__ */ jsxs75("div", { className: "cr-form__field", children: [
|
|
37742
|
+
/* @__PURE__ */ jsx105("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
|
|
37743
|
+
/* @__PURE__ */ jsx105(
|
|
37744
|
+
"input",
|
|
37745
|
+
{
|
|
37746
|
+
id: "cr-sliding-amount",
|
|
37747
|
+
type: "number",
|
|
37748
|
+
min: slidingScale.minAmount / 100,
|
|
37749
|
+
max: slidingScale.maxAmount / 100,
|
|
37750
|
+
step: "0.01",
|
|
37751
|
+
inputMode: "decimal",
|
|
37752
|
+
className: "cr-form__input",
|
|
37753
|
+
value,
|
|
37754
|
+
onChange: (event) => onChange(event.target.value)
|
|
37755
|
+
}
|
|
37756
|
+
),
|
|
37757
|
+
/* @__PURE__ */ jsxs75("p", { className: "cr-text cr-text--muted", children: [
|
|
37758
|
+
"Choose between ",
|
|
37759
|
+
minLabel,
|
|
37760
|
+
" and ",
|
|
37761
|
+
maxLabel,
|
|
37762
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
37763
|
+
"."
|
|
37764
|
+
] })
|
|
37765
|
+
] });
|
|
37766
|
+
}
|
|
37371
37767
|
function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
|
|
37372
37768
|
const nameErrorId = "cr-name-error";
|
|
37373
37769
|
const emailErrorId = "cr-email-error";
|
|
@@ -37463,6 +37859,17 @@ var init_components2 = __esm({
|
|
|
37463
37859
|
|
|
37464
37860
|
// ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
37465
37861
|
import { useEffect as useEffect18, useMemo as useMemo9, useState as useState9 } from "react";
|
|
37862
|
+
function parseCurrencyInputToCents2(value) {
|
|
37863
|
+
const trimmed = value.trim();
|
|
37864
|
+
if (!trimmed) return null;
|
|
37865
|
+
const amount = Number(trimmed);
|
|
37866
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
37867
|
+
return Math.round(amount * 100);
|
|
37868
|
+
}
|
|
37869
|
+
function formatCentsAsCurrencyInput2(amount) {
|
|
37870
|
+
const major = amount / 100;
|
|
37871
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
37872
|
+
}
|
|
37466
37873
|
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
37467
37874
|
if (!course || portalAuthState === "checking") return false;
|
|
37468
37875
|
if (hasWaitlistClaimToken) return false;
|
|
@@ -37480,12 +37887,27 @@ function getSessionIdFromUrl() {
|
|
|
37480
37887
|
}
|
|
37481
37888
|
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
37482
37889
|
if (pricing?.requiresSelection && !pricing.selectedOption) {
|
|
37890
|
+
if (pricing.slidingScale) {
|
|
37891
|
+
return "Choose an amount to continue.";
|
|
37892
|
+
}
|
|
37483
37893
|
return "Choose a pricing option to continue.";
|
|
37484
37894
|
}
|
|
37895
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
|
|
37896
|
+
return "Choose an amount within the sliding scale.";
|
|
37897
|
+
}
|
|
37898
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
|
|
37899
|
+
return "Choose an amount within the sliding scale.";
|
|
37900
|
+
}
|
|
37485
37901
|
return null;
|
|
37486
37902
|
}
|
|
37487
37903
|
function buildCoursePricingOptionPayload(pricing) {
|
|
37488
|
-
|
|
37904
|
+
if (pricing?.selectedOption) {
|
|
37905
|
+
return { pricingOptionId: pricing.selectedOption.id };
|
|
37906
|
+
}
|
|
37907
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
|
|
37908
|
+
return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
37909
|
+
}
|
|
37910
|
+
return {};
|
|
37489
37911
|
}
|
|
37490
37912
|
function resolveHasCoursePayment(pricing) {
|
|
37491
37913
|
if (!pricing) {
|
|
@@ -37526,6 +37948,7 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37526
37948
|
scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
|
|
37527
37949
|
);
|
|
37528
37950
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState9(null);
|
|
37951
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState9("");
|
|
37529
37952
|
const [formData, setFormData] = useState9({
|
|
37530
37953
|
name: "",
|
|
37531
37954
|
email: "",
|
|
@@ -37547,8 +37970,12 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37547
37970
|
const [bookingMode, setBookingMode] = useState9(null);
|
|
37548
37971
|
const waitlistClaim = useWaitlistClaim();
|
|
37549
37972
|
const selectedCoursePricing = useMemo9(
|
|
37550
|
-
() => selectedCourse ? resolveCoursePricingState(
|
|
37551
|
-
|
|
37973
|
+
() => selectedCourse ? resolveCoursePricingState(
|
|
37974
|
+
selectedCourse,
|
|
37975
|
+
selectedPricingOptionId,
|
|
37976
|
+
parseCurrencyInputToCents2(selectedSlidingAmountInput)
|
|
37977
|
+
) : null,
|
|
37978
|
+
[selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
|
|
37552
37979
|
);
|
|
37553
37980
|
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
|
|
37554
37981
|
selectedCoursePricing
|
|
@@ -37621,9 +38048,13 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37621
38048
|
useEffect18(() => {
|
|
37622
38049
|
if (!selectedCourse) {
|
|
37623
38050
|
setSelectedPricingOptionId(null);
|
|
38051
|
+
setSelectedSlidingAmountInput("");
|
|
37624
38052
|
return;
|
|
37625
38053
|
}
|
|
37626
38054
|
const defaultPricing = resolveCoursePricingState(selectedCourse, null);
|
|
38055
|
+
setSelectedSlidingAmountInput(
|
|
38056
|
+
defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
|
|
38057
|
+
);
|
|
37627
38058
|
setSelectedPricingOptionId((previous) => {
|
|
37628
38059
|
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
|
|
37629
38060
|
return previous;
|
|
@@ -37998,6 +38429,8 @@ function useCourseRegistrationWizard(props2) {
|
|
|
37998
38429
|
selectedCourse,
|
|
37999
38430
|
selectedPricingOptionId,
|
|
38000
38431
|
setSelectedPricingOptionId,
|
|
38432
|
+
selectedSlidingAmountInput,
|
|
38433
|
+
setSelectedSlidingAmountInput,
|
|
38001
38434
|
selectedCoursePricing,
|
|
38002
38435
|
setSelectedCourse,
|
|
38003
38436
|
formData,
|
|
@@ -38063,6 +38496,19 @@ var init_useCourseRegistrationWizard = __esm({
|
|
|
38063
38496
|
|
|
38064
38497
|
// ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.tsx
|
|
38065
38498
|
import { Fragment as Fragment23, jsx as jsx106, jsxs as jsxs76 } from "react/jsx-runtime";
|
|
38499
|
+
function getCourseSlidingScaleMessage(pricing) {
|
|
38500
|
+
if (!pricing.slidingScale) {
|
|
38501
|
+
return null;
|
|
38502
|
+
}
|
|
38503
|
+
const selectedAmount = pricing.selectedSlidingAmount;
|
|
38504
|
+
if (selectedAmount === null) {
|
|
38505
|
+
return "Choose an amount to continue.";
|
|
38506
|
+
}
|
|
38507
|
+
if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
|
|
38508
|
+
return "Choose an amount within the sliding scale.";
|
|
38509
|
+
}
|
|
38510
|
+
return null;
|
|
38511
|
+
}
|
|
38066
38512
|
function CourseRegistrationWizard(props2) {
|
|
38067
38513
|
const {
|
|
38068
38514
|
showSessions = true,
|
|
@@ -38084,6 +38530,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
38084
38530
|
selectedCourse,
|
|
38085
38531
|
selectedPricingOptionId,
|
|
38086
38532
|
setSelectedPricingOptionId,
|
|
38533
|
+
selectedSlidingAmountInput,
|
|
38534
|
+
setSelectedSlidingAmountInput,
|
|
38087
38535
|
selectedCoursePricing,
|
|
38088
38536
|
formData,
|
|
38089
38537
|
setFormData,
|
|
@@ -38158,7 +38606,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
38158
38606
|
const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
|
|
38159
38607
|
const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
|
|
38160
38608
|
const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
|
|
38161
|
-
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
|
|
38609
|
+
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
|
|
38610
|
+
const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
|
|
38162
38611
|
const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
|
|
38163
38612
|
const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
|
|
38164
38613
|
course: selectedCourse,
|
|
@@ -38251,6 +38700,14 @@ function CourseRegistrationWizard(props2) {
|
|
|
38251
38700
|
onSelect: setSelectedPricingOptionId
|
|
38252
38701
|
}
|
|
38253
38702
|
),
|
|
38703
|
+
/* @__PURE__ */ jsx106(
|
|
38704
|
+
CourseSlidingScaleInput,
|
|
38705
|
+
{
|
|
38706
|
+
pricing: selectedCourseWithPricing.pricing,
|
|
38707
|
+
value: selectedSlidingAmountInput,
|
|
38708
|
+
onChange: setSelectedSlidingAmountInput
|
|
38709
|
+
}
|
|
38710
|
+
),
|
|
38254
38711
|
showSpamProtection && /* @__PURE__ */ jsx106("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx106(
|
|
38255
38712
|
AltchaWidget,
|
|
38256
38713
|
{
|
|
@@ -38288,7 +38745,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
38288
38745
|
{
|
|
38289
38746
|
type: "submit",
|
|
38290
38747
|
className: buttonClass,
|
|
38291
|
-
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
|
|
38748
|
+
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
|
|
38292
38749
|
children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
|
|
38293
38750
|
}
|
|
38294
38751
|
)
|
|
@@ -38298,6 +38755,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
38298
38755
|
),
|
|
38299
38756
|
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
38757
|
pricingSelectionMissing && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
|
|
38758
|
+
slidingScaleMessage && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
|
|
38301
38759
|
pricingUnavailable && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
|
|
38302
38760
|
eligibilityError && /* @__PURE__ */ jsx106("p", { className: "cr-text cr-text--error", children: eligibilityError })
|
|
38303
38761
|
] })
|
|
@@ -41897,12 +42355,13 @@ var init_carousel_client = __esm({
|
|
|
41897
42355
|
]
|
|
41898
42356
|
);
|
|
41899
42357
|
const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
|
|
42358
|
+
const canAutoplay = normalized.autoplay && slides.length > 1;
|
|
41900
42359
|
const cssVars = React20.useMemo(
|
|
41901
42360
|
() => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
|
|
41902
42361
|
[normalized.slidesToShow]
|
|
41903
42362
|
);
|
|
41904
42363
|
const plugins = React20.useMemo(() => {
|
|
41905
|
-
if (!
|
|
42364
|
+
if (!canAutoplay) return void 0;
|
|
41906
42365
|
return [
|
|
41907
42366
|
Autoplay({
|
|
41908
42367
|
delay: normalized.autoplayDelay,
|
|
@@ -41912,7 +42371,7 @@ var init_carousel_client = __esm({
|
|
|
41912
42371
|
// Continue after manual navigation
|
|
41913
42372
|
})
|
|
41914
42373
|
];
|
|
41915
|
-
}, [
|
|
42374
|
+
}, [canAutoplay, normalized.autoplayDelay]);
|
|
41916
42375
|
const [viewportRef, api] = useEmblaCarousel(
|
|
41917
42376
|
{
|
|
41918
42377
|
align: "start",
|
|
@@ -41951,7 +42410,7 @@ var init_carousel_client = __esm({
|
|
|
41951
42410
|
};
|
|
41952
42411
|
}, [api]);
|
|
41953
42412
|
React20.useEffect(() => {
|
|
41954
|
-
if (!api || !
|
|
42413
|
+
if (!api || !canAutoplay) return;
|
|
41955
42414
|
const autoplayPlugin = api.plugins()?.autoplay;
|
|
41956
42415
|
if (!autoplayPlugin) return;
|
|
41957
42416
|
const handleVisibility = () => {
|
|
@@ -41960,7 +42419,7 @@ var init_carousel_client = __esm({
|
|
|
41960
42419
|
};
|
|
41961
42420
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
41962
42421
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
41963
|
-
}, [api,
|
|
42422
|
+
}, [api, canAutoplay]);
|
|
41964
42423
|
const inner = /* @__PURE__ */ jsxs81(Fragment25, { children: [
|
|
41965
42424
|
/* @__PURE__ */ jsx113("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx113(
|
|
41966
42425
|
"div",
|
|
@@ -42011,7 +42470,7 @@ var init_carousel_client = __esm({
|
|
|
42011
42470
|
"data-show-controls": normalized.showControls ? "true" : "false",
|
|
42012
42471
|
"data-show-dots": normalized.showDots ? "true" : "false",
|
|
42013
42472
|
"data-arrow-visibility": normalized.arrowVisibility,
|
|
42014
|
-
"data-autoplay":
|
|
42473
|
+
"data-autoplay": canAutoplay ? "true" : "false",
|
|
42015
42474
|
"data-loop": normalized.loop ? "true" : "false",
|
|
42016
42475
|
children: inner
|
|
42017
42476
|
}
|