@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
|
@@ -117,12 +117,13 @@ var init_result = __esm({
|
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
// ../core/src/branded.ts
|
|
120
|
-
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
120
|
+
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
121
121
|
var init_branded = __esm({
|
|
122
122
|
"../core/src/branded.ts"() {
|
|
123
123
|
"use strict";
|
|
124
124
|
unsafeAsMediaAssetId = (id) => id;
|
|
125
125
|
unsafeAsStorageBucketName = (value) => value;
|
|
126
|
+
unsafeAsStoragePath = (value) => value;
|
|
126
127
|
unsafeAsPositiveByteCount = (value) => value;
|
|
127
128
|
unsafeAsPositiveSeconds = (value) => value;
|
|
128
129
|
unsafeAsFormId = (id) => id;
|
|
@@ -268,6 +269,7 @@ function publicEventPricingType(pricing) {
|
|
|
268
269
|
return "free";
|
|
269
270
|
case "single_paid":
|
|
270
271
|
case "ticket_types":
|
|
272
|
+
case "sliding_scale":
|
|
271
273
|
case "course":
|
|
272
274
|
return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
|
|
273
275
|
case "external":
|
|
@@ -280,6 +282,7 @@ function publicEventPricingCurrency(pricing) {
|
|
|
280
282
|
case "free_registration":
|
|
281
283
|
case "single_paid":
|
|
282
284
|
case "ticket_types":
|
|
285
|
+
case "sliding_scale":
|
|
283
286
|
return pricing.currency;
|
|
284
287
|
case "course":
|
|
285
288
|
return pricing.display.display.currency;
|
|
@@ -297,6 +300,8 @@ function publicEventPricingMode(pricing) {
|
|
|
297
300
|
return "single";
|
|
298
301
|
case "ticket_types":
|
|
299
302
|
return "ticket_types";
|
|
303
|
+
case "sliding_scale":
|
|
304
|
+
return "sliding_scale";
|
|
300
305
|
case "drop_in":
|
|
301
306
|
case "course":
|
|
302
307
|
case "external":
|
|
@@ -330,6 +335,8 @@ function formatCoursePriceDisplayLabel(display, options) {
|
|
|
330
335
|
return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
331
336
|
case "from":
|
|
332
337
|
return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
338
|
+
case "range":
|
|
339
|
+
return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
|
|
333
340
|
default:
|
|
334
341
|
return assertNever(display);
|
|
335
342
|
}
|
|
@@ -1074,9 +1081,20 @@ var init_src = __esm({
|
|
|
1074
1081
|
});
|
|
1075
1082
|
|
|
1076
1083
|
// ../media-core/src/fileSafety.ts
|
|
1084
|
+
function containsUnsafePathSegmentCharacter(value) {
|
|
1085
|
+
return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
|
|
1086
|
+
}
|
|
1087
|
+
function isReservedPathSegment(value) {
|
|
1088
|
+
return value === "." || value === "..";
|
|
1089
|
+
}
|
|
1090
|
+
function isUnsafePathSegment(segment) {
|
|
1091
|
+
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
1092
|
+
}
|
|
1093
|
+
var CONTROL_CHARACTER_PATTERN;
|
|
1077
1094
|
var init_fileSafety = __esm({
|
|
1078
1095
|
"../media-core/src/fileSafety.ts"() {
|
|
1079
1096
|
"use strict";
|
|
1097
|
+
CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
1080
1098
|
}
|
|
1081
1099
|
});
|
|
1082
1100
|
|
|
@@ -1116,11 +1134,21 @@ var init_fileDomain = __esm({
|
|
|
1116
1134
|
});
|
|
1117
1135
|
|
|
1118
1136
|
// ../media-core/src/fileStorage.ts
|
|
1137
|
+
function parseStoragePath(value) {
|
|
1138
|
+
return joinStoragePathSegments(value.split("/"));
|
|
1139
|
+
}
|
|
1140
|
+
function joinStoragePathSegments(segments) {
|
|
1141
|
+
if (segments.some(isUnsafePathSegment)) {
|
|
1142
|
+
return err("unsafe-path-segment");
|
|
1143
|
+
}
|
|
1144
|
+
return ok(unsafeAsStoragePath(segments.join("/")));
|
|
1145
|
+
}
|
|
1119
1146
|
var FILE_STORAGE_BUCKETS, PUBLIC_SITE_FILE_STORAGE_BUCKETS, PRIVATE_SITE_FILE_BUCKET_MIME_TYPES, TEMP_UPLOAD_BUCKET_MIME_TYPES;
|
|
1120
1147
|
var init_fileStorage = __esm({
|
|
1121
1148
|
"../media-core/src/fileStorage.ts"() {
|
|
1122
1149
|
"use strict";
|
|
1123
1150
|
init_src();
|
|
1151
|
+
init_fileSafety();
|
|
1124
1152
|
FILE_STORAGE_BUCKETS = {
|
|
1125
1153
|
publicSite: unsafeAsStorageBucketName("media"),
|
|
1126
1154
|
privateSite: unsafeAsStorageBucketName("site-files-private"),
|
|
@@ -1306,14 +1334,18 @@ var init_uploadVerificationContract = __esm({
|
|
|
1306
1334
|
});
|
|
1307
1335
|
|
|
1308
1336
|
// ../media-core/src/videoPrep.ts
|
|
1337
|
+
function unsafeAsPositiveVideoDurationSeconds(value) {
|
|
1338
|
+
return value;
|
|
1339
|
+
}
|
|
1309
1340
|
var VIDEO_PREP_LIMITS;
|
|
1310
1341
|
var init_videoPrep = __esm({
|
|
1311
1342
|
"../media-core/src/videoPrep.ts"() {
|
|
1312
1343
|
"use strict";
|
|
1344
|
+
init_src();
|
|
1313
1345
|
VIDEO_PREP_LIMITS = {
|
|
1314
|
-
maxRawByteCount: 500 * 1024 * 1024,
|
|
1315
|
-
inlineContentMaxDurationSeconds: 60,
|
|
1316
|
-
backgroundVideoMaxDurationSeconds: 30,
|
|
1346
|
+
maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
|
|
1347
|
+
inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
|
|
1348
|
+
backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
|
|
1317
1349
|
targetMaxDimensionPixels: 1080
|
|
1318
1350
|
};
|
|
1319
1351
|
}
|
|
@@ -1384,10 +1416,10 @@ var init_identifiers = __esm({
|
|
|
1384
1416
|
|
|
1385
1417
|
// ../media-core/src/url.ts
|
|
1386
1418
|
function isRelativeDirectImageStoragePath(storagePath) {
|
|
1387
|
-
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
|
|
1419
|
+
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
|
|
1388
1420
|
}
|
|
1389
1421
|
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
1390
|
-
return storagePath.startsWith("sites/");
|
|
1422
|
+
return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
|
|
1391
1423
|
}
|
|
1392
1424
|
function encodeStoragePath(storagePath) {
|
|
1393
1425
|
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
@@ -1468,6 +1500,7 @@ var DEFAULT_BASE_PATH, RELATIVE_STORAGE_PATH_PREFIXES, formatNumber, ORDER, getI
|
|
|
1468
1500
|
var init_url = __esm({
|
|
1469
1501
|
"../media-core/src/url.ts"() {
|
|
1470
1502
|
"use strict";
|
|
1503
|
+
init_fileStorage();
|
|
1471
1504
|
DEFAULT_BASE_PATH = "/api/img";
|
|
1472
1505
|
RELATIVE_STORAGE_PATH_PREFIXES = [
|
|
1473
1506
|
"originals/",
|
|
@@ -2051,9 +2084,12 @@ var init_schemas = __esm({
|
|
|
2051
2084
|
});
|
|
2052
2085
|
coursePricingSchema = z5.object({
|
|
2053
2086
|
bookingRequirement: z5.enum(["none", "required"]),
|
|
2054
|
-
pricingStrategy: z5.enum(["free", "single", "tiered"]),
|
|
2087
|
+
pricingStrategy: z5.enum(["free", "single", "tiered", "sliding_scale"]),
|
|
2055
2088
|
currency: z5.string(),
|
|
2056
2089
|
singlePriceAmount: z5.number().nullable(),
|
|
2090
|
+
slidingMinAmount: z5.number().nullable().optional(),
|
|
2091
|
+
slidingMaxAmount: z5.number().nullable().optional(),
|
|
2092
|
+
slidingSuggestedAmount: z5.number().nullable().optional(),
|
|
2057
2093
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
2058
2094
|
options: z5.array(coursePricingOptionSchema)
|
|
2059
2095
|
});
|
|
@@ -2218,6 +2254,19 @@ var init_schemas2 = __esm({
|
|
|
2218
2254
|
ticketTypes: z6.array(publicEventTicketTypeSchema),
|
|
2219
2255
|
display: publicEventTicketTypePriceDisplaySchema
|
|
2220
2256
|
}),
|
|
2257
|
+
z6.object({
|
|
2258
|
+
kind: z6.literal("sliding_scale"),
|
|
2259
|
+
minAmount: z6.number(),
|
|
2260
|
+
maxAmount: z6.number(),
|
|
2261
|
+
suggestedAmount: z6.number().nullable(),
|
|
2262
|
+
currency: z6.string(),
|
|
2263
|
+
display: z6.object({
|
|
2264
|
+
kind: z6.literal("range"),
|
|
2265
|
+
minAmount: z6.number(),
|
|
2266
|
+
maxAmount: z6.number(),
|
|
2267
|
+
currency: z6.string()
|
|
2268
|
+
})
|
|
2269
|
+
}),
|
|
2221
2270
|
z6.object({
|
|
2222
2271
|
kind: z6.literal("course"),
|
|
2223
2272
|
display: z6.object({ kind: z6.literal("course"), display: publicCoursePriceDisplaySchema })
|
|
@@ -23338,6 +23387,7 @@ var init_booking_form_reserved_fields = __esm({
|
|
|
23338
23387
|
"selectedDate",
|
|
23339
23388
|
"selectedSlot",
|
|
23340
23389
|
"discountCode",
|
|
23390
|
+
"selectedSlidingAmountInput",
|
|
23341
23391
|
"selectedCollectionOptionKind",
|
|
23342
23392
|
"selectedAppointmentPackageId"
|
|
23343
23393
|
];
|
|
@@ -23623,6 +23673,32 @@ function readOptionalString(value) {
|
|
|
23623
23673
|
function readOptionalNumber(value) {
|
|
23624
23674
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
23625
23675
|
}
|
|
23676
|
+
function getBookingServiceSlidingScale(service) {
|
|
23677
|
+
const pricing = service?.pricing;
|
|
23678
|
+
if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
|
|
23679
|
+
return null;
|
|
23680
|
+
}
|
|
23681
|
+
return {
|
|
23682
|
+
minAmount: pricing.slidingMinAmount,
|
|
23683
|
+
maxAmount: pricing.slidingMaxAmount,
|
|
23684
|
+
suggestedAmount: pricing.slidingSuggestedAmount ?? null,
|
|
23685
|
+
currency: pricing.currency
|
|
23686
|
+
};
|
|
23687
|
+
}
|
|
23688
|
+
function parseBookingCurrencyInputToCents(value) {
|
|
23689
|
+
const trimmed = value?.trim() ?? "";
|
|
23690
|
+
if (!trimmed) return null;
|
|
23691
|
+
if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
|
|
23692
|
+
const parsed = Number(trimmed);
|
|
23693
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
23694
|
+
return Math.round(parsed * 100);
|
|
23695
|
+
}
|
|
23696
|
+
function formatBookingCentsAsCurrencyInput(amount) {
|
|
23697
|
+
return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
|
|
23698
|
+
}
|
|
23699
|
+
function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
|
|
23700
|
+
return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
|
|
23701
|
+
}
|
|
23626
23702
|
function readStringArray(value) {
|
|
23627
23703
|
if (!Array.isArray(value)) return void 0;
|
|
23628
23704
|
const strings = value.filter((item) => typeof item === "string");
|
|
@@ -23811,6 +23887,20 @@ function prepareBookingSubmission(input) {
|
|
|
23811
23887
|
};
|
|
23812
23888
|
}
|
|
23813
23889
|
const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
|
|
23890
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
23891
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
23892
|
+
input.data.selectedSlidingAmountInput
|
|
23893
|
+
);
|
|
23894
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
|
|
23895
|
+
return {
|
|
23896
|
+
ok: false,
|
|
23897
|
+
error: {
|
|
23898
|
+
tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
|
|
23899
|
+
serviceId,
|
|
23900
|
+
serviceTitle: selectedService.title || serviceId
|
|
23901
|
+
}
|
|
23902
|
+
};
|
|
23903
|
+
}
|
|
23814
23904
|
if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
|
|
23815
23905
|
return {
|
|
23816
23906
|
ok: false,
|
|
@@ -23838,6 +23928,7 @@ function prepareBookingSubmission(input) {
|
|
|
23838
23928
|
...common,
|
|
23839
23929
|
kind: "standard",
|
|
23840
23930
|
...discountCode ? { discountCode } : {},
|
|
23931
|
+
...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
|
|
23841
23932
|
...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
|
|
23842
23933
|
altchaSolution: input.altchaSolution ?? null
|
|
23843
23934
|
}
|
|
@@ -23851,6 +23942,10 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
23851
23942
|
return `Service not found: ${error.serviceId}`;
|
|
23852
23943
|
case "payment-option-required":
|
|
23853
23944
|
return `Please choose how you want to pay for "${error.serviceTitle}".`;
|
|
23945
|
+
case "sliding-amount-required":
|
|
23946
|
+
return `Please choose an amount for "${error.serviceTitle}".`;
|
|
23947
|
+
case "sliding-amount-out-of-range":
|
|
23948
|
+
return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
23854
23949
|
case "payment-option-unsupported":
|
|
23855
23950
|
return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
23856
23951
|
case "service-missing-duration":
|
|
@@ -24001,6 +24096,7 @@ var init_booking_form_interactive = __esm({
|
|
|
24001
24096
|
title: z36.string(),
|
|
24002
24097
|
description: z36.string().nullable().optional().transform((value) => value ?? void 0),
|
|
24003
24098
|
durationMinutes: z36.number().optional(),
|
|
24099
|
+
pricing: z36.custom().optional(),
|
|
24004
24100
|
priceAmount: z36.number().nullable().optional(),
|
|
24005
24101
|
priceCurrency: z36.string().nullable().optional(),
|
|
24006
24102
|
paymentTerms: blockBookingPaymentTermsSchema.optional(),
|
|
@@ -24989,7 +25085,7 @@ function isRecord6(value) {
|
|
|
24989
25085
|
}
|
|
24990
25086
|
function isPublicEventPricing(value) {
|
|
24991
25087
|
if (!isRecord6(value) || typeof value.kind !== "string") return false;
|
|
24992
|
-
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
|
|
25088
|
+
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";
|
|
24993
25089
|
}
|
|
24994
25090
|
function isPublicEventTicketType(value) {
|
|
24995
25091
|
return isRecord6(value) && typeof value.id === "string";
|
|
@@ -33593,12 +33689,13 @@ var init_carousel_client = __esm({
|
|
|
33593
33689
|
]
|
|
33594
33690
|
);
|
|
33595
33691
|
const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
|
|
33692
|
+
const canAutoplay = normalized.autoplay && slides.length > 1;
|
|
33596
33693
|
const cssVars = React5.useMemo(
|
|
33597
33694
|
() => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
|
|
33598
33695
|
[normalized.slidesToShow]
|
|
33599
33696
|
);
|
|
33600
33697
|
const plugins = React5.useMemo(() => {
|
|
33601
|
-
if (!
|
|
33698
|
+
if (!canAutoplay) return void 0;
|
|
33602
33699
|
return [
|
|
33603
33700
|
Autoplay({
|
|
33604
33701
|
delay: normalized.autoplayDelay,
|
|
@@ -33608,7 +33705,7 @@ var init_carousel_client = __esm({
|
|
|
33608
33705
|
// Continue after manual navigation
|
|
33609
33706
|
})
|
|
33610
33707
|
];
|
|
33611
|
-
}, [
|
|
33708
|
+
}, [canAutoplay, normalized.autoplayDelay]);
|
|
33612
33709
|
const [viewportRef, api] = useEmblaCarousel(
|
|
33613
33710
|
{
|
|
33614
33711
|
align: "start",
|
|
@@ -33647,7 +33744,7 @@ var init_carousel_client = __esm({
|
|
|
33647
33744
|
};
|
|
33648
33745
|
}, [api]);
|
|
33649
33746
|
React5.useEffect(() => {
|
|
33650
|
-
if (!api || !
|
|
33747
|
+
if (!api || !canAutoplay) return;
|
|
33651
33748
|
const autoplayPlugin = api.plugins()?.autoplay;
|
|
33652
33749
|
if (!autoplayPlugin) return;
|
|
33653
33750
|
const handleVisibility = () => {
|
|
@@ -33656,7 +33753,7 @@ var init_carousel_client = __esm({
|
|
|
33656
33753
|
};
|
|
33657
33754
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
33658
33755
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
33659
|
-
}, [api,
|
|
33756
|
+
}, [api, canAutoplay]);
|
|
33660
33757
|
const inner = /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
33661
33758
|
/* @__PURE__ */ jsx15("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx15(
|
|
33662
33759
|
"div",
|
|
@@ -33707,7 +33804,7 @@ var init_carousel_client = __esm({
|
|
|
33707
33804
|
"data-show-controls": normalized.showControls ? "true" : "false",
|
|
33708
33805
|
"data-show-dots": normalized.showDots ? "true" : "false",
|
|
33709
33806
|
"data-arrow-visibility": normalized.arrowVisibility,
|
|
33710
|
-
"data-autoplay":
|
|
33807
|
+
"data-autoplay": canAutoplay ? "true" : "false",
|
|
33711
33808
|
"data-loop": normalized.loop ? "true" : "false",
|
|
33712
33809
|
children: inner
|
|
33713
33810
|
}
|
|
@@ -34710,6 +34807,7 @@ function createBlockApi(config) {
|
|
|
34710
34807
|
body: {
|
|
34711
34808
|
courseId: data.courseId,
|
|
34712
34809
|
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
34810
|
+
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
34713
34811
|
email: data.email,
|
|
34714
34812
|
name: data.name,
|
|
34715
34813
|
phone: data.phone,
|
|
@@ -38947,6 +39045,7 @@ function useBookingSubmission(_siteId) {
|
|
|
38947
39045
|
customFields: data.customFields,
|
|
38948
39046
|
timezone: data.timezone,
|
|
38949
39047
|
discountCode: data.discountCode,
|
|
39048
|
+
selectedSlidingAmount: data.selectedSlidingAmount,
|
|
38950
39049
|
selectedCollectionOptionKind: data.selectedCollectionOptionKind,
|
|
38951
39050
|
altchaSolution: data.altchaSolution ?? null,
|
|
38952
39051
|
successUrl: data.successUrl,
|
|
@@ -39475,6 +39574,9 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
39475
39574
|
fieldValues: collectInitialFieldValues(initialData),
|
|
39476
39575
|
touchedFields: {},
|
|
39477
39576
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
39577
|
+
selectedSlidingAmountInput: toOptionalString(
|
|
39578
|
+
initialData.selectedSlidingAmountInput
|
|
39579
|
+
) ?? "",
|
|
39478
39580
|
selectedCollectionOptionKind: toSelectedCollectionOptionKind(
|
|
39479
39581
|
initialData.selectedCollectionOptionKind
|
|
39480
39582
|
),
|
|
@@ -39527,6 +39629,7 @@ function bookingFlowReducer(state, event) {
|
|
|
39527
39629
|
selectedDate: void 0,
|
|
39528
39630
|
selectedSlot: null,
|
|
39529
39631
|
selectedAppointmentPackageId: void 0,
|
|
39632
|
+
selectedSlidingAmountInput: "",
|
|
39530
39633
|
selectedCollectionOptionKind: void 0,
|
|
39531
39634
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
39532
39635
|
};
|
|
@@ -39580,6 +39683,13 @@ function bookingFlowReducer(state, event) {
|
|
|
39580
39683
|
selectedAppointmentPackageId: void 0,
|
|
39581
39684
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
39582
39685
|
};
|
|
39686
|
+
case "sliding-amount-changed":
|
|
39687
|
+
return {
|
|
39688
|
+
...state,
|
|
39689
|
+
selectedSlidingAmountInput: event.value,
|
|
39690
|
+
selectedAppointmentPackageId: void 0,
|
|
39691
|
+
validationErrors: clearBookingFormError(state.validationErrors)
|
|
39692
|
+
};
|
|
39583
39693
|
case "appointment-package-selected":
|
|
39584
39694
|
return {
|
|
39585
39695
|
...state,
|
|
@@ -39682,6 +39792,7 @@ function toBookingFormData(state) {
|
|
|
39682
39792
|
selectedDate: state.selectedDate,
|
|
39683
39793
|
selectedSlot: state.selectedSlot?.startAt,
|
|
39684
39794
|
discountCode: state.discountCode || void 0,
|
|
39795
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
|
|
39685
39796
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
39686
39797
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId
|
|
39687
39798
|
};
|
|
@@ -39699,7 +39810,8 @@ function buildBookingStepResolution(input) {
|
|
|
39699
39810
|
input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
|
|
39700
39811
|
);
|
|
39701
39812
|
const selectedService = paymentResolution.service;
|
|
39702
|
-
const
|
|
39813
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
39814
|
+
const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
|
|
39703
39815
|
input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
39704
39816
|
);
|
|
39705
39817
|
const hasFields = Boolean(input.form.schema?.fields.length);
|
|
@@ -39743,6 +39855,18 @@ function validateBookingStep(input) {
|
|
|
39743
39855
|
services: input.services,
|
|
39744
39856
|
defaultServiceId: input.defaultServiceId
|
|
39745
39857
|
});
|
|
39858
|
+
const slidingScale = getBookingServiceSlidingScale(resolution.service);
|
|
39859
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(
|
|
39860
|
+
slidingScale,
|
|
39861
|
+
parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
|
|
39862
|
+
)) {
|
|
39863
|
+
return {
|
|
39864
|
+
ok: false,
|
|
39865
|
+
errors: createFormBookingValidationError(
|
|
39866
|
+
"Please choose an amount within the sliding scale"
|
|
39867
|
+
)
|
|
39868
|
+
};
|
|
39869
|
+
}
|
|
39746
39870
|
if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
|
|
39747
39871
|
return { ok: true };
|
|
39748
39872
|
}
|
|
@@ -40141,6 +40265,7 @@ var init_useHeadlessBookingFlow_state = __esm({
|
|
|
40141
40265
|
"../blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.ts"() {
|
|
40142
40266
|
"use strict";
|
|
40143
40267
|
init_booking_form_headless_state();
|
|
40268
|
+
init_booking_form_state();
|
|
40144
40269
|
}
|
|
40145
40270
|
});
|
|
40146
40271
|
|
|
@@ -40180,11 +40305,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
40180
40305
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
40181
40306
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
40182
40307
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
40308
|
+
const lastSlidingServiceIdRef = useRef9(null);
|
|
40309
|
+
useEffect8(() => {
|
|
40310
|
+
const selectedId = selectedService?.id ?? null;
|
|
40311
|
+
if (lastSlidingServiceIdRef.current === selectedId) return;
|
|
40312
|
+
lastSlidingServiceIdRef.current = selectedId;
|
|
40313
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
40314
|
+
dispatch({
|
|
40315
|
+
type: "sliding-amount-changed",
|
|
40316
|
+
value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
40317
|
+
});
|
|
40318
|
+
}, [selectedService]);
|
|
40183
40319
|
const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
|
|
40320
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
40321
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
40322
|
+
state.selectedSlidingAmountInput
|
|
40323
|
+
);
|
|
40324
|
+
const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
|
|
40184
40325
|
const canLoadAppointmentPackages = Boolean(
|
|
40185
|
-
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
40326
|
+
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
|
|
40186
40327
|
);
|
|
40187
|
-
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
40328
|
+
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
40188
40329
|
const data = useMemo6(() => toBookingFormData(state), [state]);
|
|
40189
40330
|
const availabilityDatesQuery = useMemo6(
|
|
40190
40331
|
() => buildBookingAvailabilityQuery({
|
|
@@ -40414,13 +40555,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
40414
40555
|
state.selectedSlot
|
|
40415
40556
|
]);
|
|
40416
40557
|
const appointmentDiscountContext = useMemo6(
|
|
40417
|
-
() => selectedService &&
|
|
40418
|
-
[
|
|
40558
|
+
() => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
40559
|
+
[selectedAppointmentPriceAmount, selectedService?.id]
|
|
40419
40560
|
);
|
|
40420
40561
|
const discountUi = useDiscountCodeUi({
|
|
40421
40562
|
api,
|
|
40422
40563
|
discountContext: appointmentDiscountContext,
|
|
40423
|
-
subtotalCents:
|
|
40564
|
+
subtotalCents: selectedAppointmentPriceAmount
|
|
40424
40565
|
});
|
|
40425
40566
|
const { submit, clearFeedback } = useBookingSubmission(options.siteId);
|
|
40426
40567
|
const submittingRef = useRef9(false);
|
|
@@ -40563,6 +40704,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
40563
40704
|
type: "appointment-package-selected",
|
|
40564
40705
|
packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
|
|
40565
40706
|
}),
|
|
40707
|
+
setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
|
|
40566
40708
|
setDiscountCode: (code) => {
|
|
40567
40709
|
dispatch({ type: "discount-code-changed", code });
|
|
40568
40710
|
latestRef.current.setDiscountCode(code);
|
|
@@ -40633,11 +40775,11 @@ function useHeadlessBookingFlow(options) {
|
|
|
40633
40775
|
() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
40634
40776
|
serviceTitle: selectedService.title,
|
|
40635
40777
|
paymentTerms: selectedService.paymentTerms,
|
|
40636
|
-
priceAmount:
|
|
40778
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
40637
40779
|
priceCurrency: selectedService.priceCurrency,
|
|
40638
40780
|
bookingStartAt: state.selectedSlot?.startAt
|
|
40639
40781
|
}) : null,
|
|
40640
|
-
[paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
|
|
40782
|
+
[paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
|
|
40641
40783
|
);
|
|
40642
40784
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
40643
40785
|
const selectedAppointmentPackage = appointmentPackageItems.find(
|
|
@@ -40666,6 +40808,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
40666
40808
|
selection: null,
|
|
40667
40809
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
40668
40810
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
40811
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
40812
|
+
selectedSlidingAmount,
|
|
40813
|
+
slidingScale: selectedServiceSlidingScale,
|
|
40669
40814
|
appointmentPackages: appointmentPackagesModel,
|
|
40670
40815
|
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
40671
40816
|
} : {
|
|
@@ -40674,6 +40819,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
40674
40819
|
selection: paymentSelection,
|
|
40675
40820
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
40676
40821
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
40822
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
40823
|
+
selectedSlidingAmount,
|
|
40824
|
+
slidingScale: selectedServiceSlidingScale,
|
|
40677
40825
|
appointmentPackages: appointmentPackagesModel
|
|
40678
40826
|
};
|
|
40679
40827
|
return {
|
|
@@ -41368,6 +41516,9 @@ var init_FieldValidationMessage = __esm({
|
|
|
41368
41516
|
|
|
41369
41517
|
// ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
41370
41518
|
import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
41519
|
+
function formatBookingAmount(amount, currency) {
|
|
41520
|
+
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
41521
|
+
}
|
|
41371
41522
|
function HeadlessBookingDefaultForm({
|
|
41372
41523
|
booking,
|
|
41373
41524
|
onSubmit
|
|
@@ -41644,6 +41795,7 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
41644
41795
|
}
|
|
41645
41796
|
const packageOptions = booking.payment.appointmentPackages.items;
|
|
41646
41797
|
const hasPackageOptions = packageOptions.length > 0;
|
|
41798
|
+
const slidingScale = booking.payment.slidingScale;
|
|
41647
41799
|
return /* @__PURE__ */ jsxs21("div", { className: "ab-stack", children: [
|
|
41648
41800
|
/* @__PURE__ */ jsxs21("div", { className: "ab-info-box", children: [
|
|
41649
41801
|
/* @__PURE__ */ jsx27("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
|
|
@@ -41654,6 +41806,28 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
41654
41806
|
booking.payment.appointmentPackages.state.message,
|
|
41655
41807
|
" You can continue with the normal payment option."
|
|
41656
41808
|
] }) : null,
|
|
41809
|
+
slidingScale ? /* @__PURE__ */ jsxs21("div", { className: "rb-space-y-2", children: [
|
|
41810
|
+
/* @__PURE__ */ jsx27("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
|
|
41811
|
+
/* @__PURE__ */ jsxs21("p", { className: "rb-caption status-muted", children: [
|
|
41812
|
+
formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
|
|
41813
|
+
" to ",
|
|
41814
|
+
formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
|
|
41815
|
+
slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
|
|
41816
|
+
] }),
|
|
41817
|
+
/* @__PURE__ */ jsx27(
|
|
41818
|
+
"input",
|
|
41819
|
+
{
|
|
41820
|
+
id: "appointment-sliding-amount",
|
|
41821
|
+
type: "number",
|
|
41822
|
+
className: "form-input",
|
|
41823
|
+
min: slidingScale.minAmount / 100,
|
|
41824
|
+
max: slidingScale.maxAmount / 100,
|
|
41825
|
+
step: "0.01",
|
|
41826
|
+
value: booking.payment.selectedSlidingAmountInput,
|
|
41827
|
+
onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
|
|
41828
|
+
}
|
|
41829
|
+
)
|
|
41830
|
+
] }) : null,
|
|
41657
41831
|
/* @__PURE__ */ jsxs21("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
|
|
41658
41832
|
packageOptions.map((appointmentPackage) => {
|
|
41659
41833
|
const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
|
|
@@ -43500,6 +43674,7 @@ function useEligibility(params) {
|
|
|
43500
43674
|
occurrenceId: params.occurrenceId,
|
|
43501
43675
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
43502
43676
|
ticketTypeId: params.ticketTypeId ?? void 0,
|
|
43677
|
+
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
43503
43678
|
email: params.email.trim().toLowerCase(),
|
|
43504
43679
|
ticketsCount: params.ticketsCount
|
|
43505
43680
|
});
|
|
@@ -43520,7 +43695,7 @@ function useEligibility(params) {
|
|
|
43520
43695
|
return () => {
|
|
43521
43696
|
cancelled = true;
|
|
43522
43697
|
};
|
|
43523
|
-
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
|
|
43698
|
+
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
|
|
43524
43699
|
return {
|
|
43525
43700
|
state,
|
|
43526
43701
|
eligibility: state.eligibility,
|
|
@@ -43871,6 +44046,41 @@ function TicketCounterLimit(props2) {
|
|
|
43871
44046
|
] }) : null
|
|
43872
44047
|
] });
|
|
43873
44048
|
}
|
|
44049
|
+
function formatCurrencyInputAmount(amount) {
|
|
44050
|
+
const major = amount / 100;
|
|
44051
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
44052
|
+
}
|
|
44053
|
+
function SlidingScaleAmountField(props2) {
|
|
44054
|
+
const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
|
|
44055
|
+
const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
|
|
44056
|
+
const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
|
|
44057
|
+
return /* @__PURE__ */ jsxs28("div", { className: "er-field", children: [
|
|
44058
|
+
/* @__PURE__ */ jsx42("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
|
|
44059
|
+
/* @__PURE__ */ jsx42(
|
|
44060
|
+
"input",
|
|
44061
|
+
{
|
|
44062
|
+
id: "er-sliding-amount",
|
|
44063
|
+
type: "number",
|
|
44064
|
+
min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
|
|
44065
|
+
max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
|
|
44066
|
+
step: "0.01",
|
|
44067
|
+
inputMode: "decimal",
|
|
44068
|
+
className: "er-input",
|
|
44069
|
+
value: props2.value,
|
|
44070
|
+
onChange: (event) => props2.onChange?.(event.target.value)
|
|
44071
|
+
}
|
|
44072
|
+
),
|
|
44073
|
+
/* @__PURE__ */ jsxs28("p", { className: "er-text er-text--muted", children: [
|
|
44074
|
+
"Choose between ",
|
|
44075
|
+
minLabel,
|
|
44076
|
+
" and ",
|
|
44077
|
+
maxLabel,
|
|
44078
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
44079
|
+
"."
|
|
44080
|
+
] }),
|
|
44081
|
+
props2.message ? /* @__PURE__ */ jsx42("p", { className: "er-text er-text--muted", children: props2.message }) : null
|
|
44082
|
+
] });
|
|
44083
|
+
}
|
|
43874
44084
|
function getTicketTypeCounterAvailabilityLabel(input) {
|
|
43875
44085
|
if (input.selectedRemainingCapacity !== null) {
|
|
43876
44086
|
return `${input.selectedRemainingCapacity} remaining for this ticket type`;
|
|
@@ -43942,6 +44152,10 @@ var init_TicketSelectionStep = __esm({
|
|
|
43942
44152
|
maxTickets,
|
|
43943
44153
|
selectedTicketTypeId = null,
|
|
43944
44154
|
onTicketTypeChange,
|
|
44155
|
+
slidingScale = null,
|
|
44156
|
+
selectedSlidingAmountInput = "",
|
|
44157
|
+
slidingScaleSelectionMessage = null,
|
|
44158
|
+
onSlidingAmountChange,
|
|
43945
44159
|
onTicketsChange
|
|
43946
44160
|
}) => {
|
|
43947
44161
|
const deliveryMode = event?.deliveryMode ?? "in_person";
|
|
@@ -44057,6 +44271,16 @@ var init_TicketSelectionStep = __esm({
|
|
|
44057
44271
|
] })
|
|
44058
44272
|
] })
|
|
44059
44273
|
] }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
|
|
44274
|
+
slidingScale ? /* @__PURE__ */ jsx42(
|
|
44275
|
+
SlidingScaleAmountField,
|
|
44276
|
+
{
|
|
44277
|
+
slidingScale,
|
|
44278
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
|
|
44279
|
+
value: selectedSlidingAmountInput,
|
|
44280
|
+
message: slidingScaleSelectionMessage,
|
|
44281
|
+
onChange: onSlidingAmountChange
|
|
44282
|
+
}
|
|
44283
|
+
) : null,
|
|
44060
44284
|
/* @__PURE__ */ jsx42("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
|
|
44061
44285
|
/* @__PURE__ */ jsxs28("div", { className: "er-ticket-counter-group", children: [
|
|
44062
44286
|
/* @__PURE__ */ jsx42(
|
|
@@ -45071,6 +45295,10 @@ function EventRegistrationWizardContent(props2) {
|
|
|
45071
45295
|
maxTickets: wizard.maxTicketsNum,
|
|
45072
45296
|
selectedTicketTypeId: wizard.selectedTicketTypeId,
|
|
45073
45297
|
onTicketTypeChange: wizard.setSelectedTicketTypeId,
|
|
45298
|
+
slidingScale: wizard.selectedEventSlidingScale,
|
|
45299
|
+
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
45300
|
+
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
45301
|
+
onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
|
|
45074
45302
|
onTicketsChange: wizard.setTicketsCount
|
|
45075
45303
|
}
|
|
45076
45304
|
)
|
|
@@ -45287,7 +45515,7 @@ function EventRegistrationSummaryBar(props2) {
|
|
|
45287
45515
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
45288
45516
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
45289
45517
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
45290
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
45518
|
+
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
45291
45519
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
|
|
45292
45520
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
45293
45521
|
const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
|
|
@@ -45738,6 +45966,7 @@ function useEventRegistrationSubmit(options) {
|
|
|
45738
45966
|
occurrenceId: submitOccurrenceId,
|
|
45739
45967
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
45740
45968
|
ticketTypeId: options.selectedTicketTypeId ?? void 0,
|
|
45969
|
+
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
45741
45970
|
email: options.formData.email.trim().toLowerCase(),
|
|
45742
45971
|
name: options.formData.name.trim(),
|
|
45743
45972
|
ticketsCount: options.ticketsCount,
|
|
@@ -45847,6 +46076,35 @@ var init_useEventRegistrationSubmit = __esm({
|
|
|
45847
46076
|
|
|
45848
46077
|
// ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
45849
46078
|
import { useCallback as useCallback8, useEffect as useEffect15, useMemo as useMemo10, useReducer as useReducer10, useState as useState7 } from "react";
|
|
46079
|
+
function parseCurrencyInputToCents(value) {
|
|
46080
|
+
const trimmed = value.trim();
|
|
46081
|
+
if (!trimmed) return null;
|
|
46082
|
+
const amount = Number(trimmed);
|
|
46083
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
46084
|
+
return Math.round(amount * 100);
|
|
46085
|
+
}
|
|
46086
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
46087
|
+
const major = amount / 100;
|
|
46088
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
46089
|
+
}
|
|
46090
|
+
function getSlidingScaleForEvent(event) {
|
|
46091
|
+
const pricing = event ? resolveRuntimeEventPricing(event) : null;
|
|
46092
|
+
return pricing?.kind === "sliding_scale" ? {
|
|
46093
|
+
minAmount: pricing.minAmount,
|
|
46094
|
+
maxAmount: pricing.maxAmount,
|
|
46095
|
+
suggestedAmount: pricing.suggestedAmount
|
|
46096
|
+
} : null;
|
|
46097
|
+
}
|
|
46098
|
+
function getSlidingScaleSelectionMessage(input) {
|
|
46099
|
+
if (!input.slidingScale) return null;
|
|
46100
|
+
if (input.selectedAmount === null) {
|
|
46101
|
+
return "Choose an amount to continue.";
|
|
46102
|
+
}
|
|
46103
|
+
if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
|
|
46104
|
+
return "Choose an amount within the sliding scale.";
|
|
46105
|
+
}
|
|
46106
|
+
return null;
|
|
46107
|
+
}
|
|
45850
46108
|
function useEventRegistrationWizard(options) {
|
|
45851
46109
|
const api = useBlockApi();
|
|
45852
46110
|
const registrationEvents = useMemo10(
|
|
@@ -45891,6 +46149,10 @@ function useEventRegistrationWizard(options) {
|
|
|
45891
46149
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
45892
46150
|
);
|
|
45893
46151
|
const [selectedTicketTypeId, setSelectedTicketTypeId] = useState7(null);
|
|
46152
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState7(() => {
|
|
46153
|
+
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
46154
|
+
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
46155
|
+
});
|
|
45894
46156
|
const [registrationResult, setRegistrationResult] = useState7(null);
|
|
45895
46157
|
const [errorMessage, setErrorMessage] = useState7("");
|
|
45896
46158
|
const [altchaSolution, setAltchaSolution] = useState7(null);
|
|
@@ -45927,6 +46189,7 @@ function useEventRegistrationWizard(options) {
|
|
|
45927
46189
|
occurrenceId,
|
|
45928
46190
|
attendanceMode: selectedAttendanceMode,
|
|
45929
46191
|
ticketTypeId: selectedTicketTypeId,
|
|
46192
|
+
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
45930
46193
|
email: formData.email,
|
|
45931
46194
|
ticketsCount
|
|
45932
46195
|
});
|
|
@@ -46062,6 +46325,18 @@ function useEventRegistrationWizard(options) {
|
|
|
46062
46325
|
}),
|
|
46063
46326
|
[selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
|
|
46064
46327
|
);
|
|
46328
|
+
const selectedSlidingAmount = useMemo10(
|
|
46329
|
+
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
46330
|
+
[selectedSlidingAmountInput]
|
|
46331
|
+
);
|
|
46332
|
+
const selectedEventSlidingScale = useMemo10(
|
|
46333
|
+
() => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
|
|
46334
|
+
[selectedEvent, preSelectedEvent]
|
|
46335
|
+
);
|
|
46336
|
+
const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
|
|
46337
|
+
slidingScale: selectedEventSlidingScale,
|
|
46338
|
+
selectedAmount: selectedSlidingAmount
|
|
46339
|
+
});
|
|
46065
46340
|
const ticketTypeSelectionRequired = useMemo10(() => {
|
|
46066
46341
|
const event = selectedEvent ?? preSelectedEvent;
|
|
46067
46342
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
@@ -46130,12 +46405,24 @@ function useEventRegistrationWizard(options) {
|
|
|
46130
46405
|
setGuestSectionShake(false);
|
|
46131
46406
|
};
|
|
46132
46407
|
const eventRequiresPayment = useMemo10(
|
|
46133
|
-
() =>
|
|
46408
|
+
() => {
|
|
46409
|
+
if (selectedEventSlidingScale) {
|
|
46410
|
+
return (selectedSlidingAmount ?? 0) > 0;
|
|
46411
|
+
}
|
|
46412
|
+
return resolveEventRequiresPayment({
|
|
46413
|
+
eligibility,
|
|
46414
|
+
selectedTicketType,
|
|
46415
|
+
event: selectedEvent ?? preSelectedEvent
|
|
46416
|
+
});
|
|
46417
|
+
},
|
|
46418
|
+
[
|
|
46134
46419
|
eligibility,
|
|
46135
46420
|
selectedTicketType,
|
|
46136
|
-
|
|
46137
|
-
|
|
46138
|
-
|
|
46421
|
+
selectedEvent,
|
|
46422
|
+
preSelectedEvent,
|
|
46423
|
+
selectedEventSlidingScale,
|
|
46424
|
+
selectedSlidingAmount
|
|
46425
|
+
]
|
|
46139
46426
|
);
|
|
46140
46427
|
const handleDetailsComplete = async () => {
|
|
46141
46428
|
if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
|
|
@@ -46144,6 +46431,11 @@ function useEventRegistrationWizard(options) {
|
|
|
46144
46431
|
setStep("error");
|
|
46145
46432
|
return { ok: false, reason: "blocked", message };
|
|
46146
46433
|
}
|
|
46434
|
+
if (slidingScaleSelectionMessage) {
|
|
46435
|
+
setErrorMessage(slidingScaleSelectionMessage);
|
|
46436
|
+
setStep("error");
|
|
46437
|
+
return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
|
|
46438
|
+
}
|
|
46147
46439
|
if (!validateForm()) {
|
|
46148
46440
|
setGuestSectionShake(true);
|
|
46149
46441
|
return {
|
|
@@ -46228,9 +46520,18 @@ function useEventRegistrationWizard(options) {
|
|
|
46228
46520
|
const discountSubtotalCents = useMemo10(() => {
|
|
46229
46521
|
if (discountContext?.type !== "event") return void 0;
|
|
46230
46522
|
const event = selectedEvent ?? preSelectedEvent;
|
|
46231
|
-
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
46523
|
+
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
46232
46524
|
return Math.max(0, eventPriceCents * ticketsCount);
|
|
46233
|
-
}, [
|
|
46525
|
+
}, [
|
|
46526
|
+
discountContext,
|
|
46527
|
+
selectedTicketType,
|
|
46528
|
+
eligibility,
|
|
46529
|
+
selectedEvent,
|
|
46530
|
+
preSelectedEvent,
|
|
46531
|
+
selectedEventSlidingScale,
|
|
46532
|
+
selectedSlidingAmount,
|
|
46533
|
+
ticketsCount
|
|
46534
|
+
]);
|
|
46234
46535
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
46235
46536
|
const selectionMethod = paymentSelection.method;
|
|
46236
46537
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -46239,6 +46540,7 @@ function useEventRegistrationWizard(options) {
|
|
|
46239
46540
|
registrationTarget,
|
|
46240
46541
|
selectedAttendanceMode,
|
|
46241
46542
|
selectedTicketTypeId,
|
|
46543
|
+
selectedSlidingAmount,
|
|
46242
46544
|
ticketsCount,
|
|
46243
46545
|
formData,
|
|
46244
46546
|
altchaSolution,
|
|
@@ -46253,6 +46555,10 @@ function useEventRegistrationWizard(options) {
|
|
|
46253
46555
|
});
|
|
46254
46556
|
const handleEventSelect = (event) => {
|
|
46255
46557
|
setSelectedEvent(event);
|
|
46558
|
+
const slidingScale = getSlidingScaleForEvent(event);
|
|
46559
|
+
setSelectedSlidingAmountInput(
|
|
46560
|
+
slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
46561
|
+
);
|
|
46256
46562
|
setSelectedAttendanceMode(
|
|
46257
46563
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
46258
46564
|
);
|
|
@@ -46262,6 +46568,7 @@ function useEventRegistrationWizard(options) {
|
|
|
46262
46568
|
const handleRetry = () => {
|
|
46263
46569
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
46264
46570
|
setSelectedTicketTypeId(null);
|
|
46571
|
+
setSelectedSlidingAmountInput("");
|
|
46265
46572
|
setSelectedAttendanceMode(
|
|
46266
46573
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
46267
46574
|
);
|
|
@@ -46298,6 +46605,11 @@ function useEventRegistrationWizard(options) {
|
|
|
46298
46605
|
setSelectedAttendanceMode,
|
|
46299
46606
|
selectedTicketTypeId,
|
|
46300
46607
|
setSelectedTicketTypeId,
|
|
46608
|
+
selectedSlidingAmountInput,
|
|
46609
|
+
setSelectedSlidingAmountInput,
|
|
46610
|
+
selectedSlidingAmount,
|
|
46611
|
+
selectedEventSlidingScale,
|
|
46612
|
+
slidingScaleSelectionMessage,
|
|
46301
46613
|
selectedTicketType,
|
|
46302
46614
|
visibleTicketTypes,
|
|
46303
46615
|
ticketTypeSelectionRequired,
|
|
@@ -47255,7 +47567,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
47255
47567
|
return left.name.localeCompare(right.name);
|
|
47256
47568
|
});
|
|
47257
47569
|
}
|
|
47258
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
|
|
47570
|
+
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
47571
|
+
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
47572
|
+
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
47259
47573
|
const currency = course.pricing?.currency ?? course.currency;
|
|
47260
47574
|
if (!course.pricing) {
|
|
47261
47575
|
const legacyAmount = course.priceCents ?? 0;
|
|
@@ -47265,6 +47579,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
47265
47579
|
selectableOptions: [],
|
|
47266
47580
|
requiresSelection: false,
|
|
47267
47581
|
selectedOption: null,
|
|
47582
|
+
slidingScale: null,
|
|
47583
|
+
selectedSlidingAmount: null,
|
|
47268
47584
|
selectedPriceAmount: legacyAmount,
|
|
47269
47585
|
selectedRequiresPayment: legacyAmount > 0,
|
|
47270
47586
|
hasPaidSelection: legacyAmount > 0,
|
|
@@ -47279,6 +47595,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
47279
47595
|
selectableOptions: [],
|
|
47280
47596
|
requiresSelection: false,
|
|
47281
47597
|
selectedOption: null,
|
|
47598
|
+
slidingScale: null,
|
|
47599
|
+
selectedSlidingAmount: null,
|
|
47282
47600
|
selectedPriceAmount: 0,
|
|
47283
47601
|
selectedRequiresPayment: false,
|
|
47284
47602
|
hasPaidSelection: false,
|
|
@@ -47292,6 +47610,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
47292
47610
|
selectableOptions: [],
|
|
47293
47611
|
requiresSelection: false,
|
|
47294
47612
|
selectedOption: null,
|
|
47613
|
+
slidingScale: null,
|
|
47614
|
+
selectedSlidingAmount: null,
|
|
47295
47615
|
selectedPriceAmount: amount,
|
|
47296
47616
|
selectedRequiresPayment: amount > 0,
|
|
47297
47617
|
hasPaidSelection: amount > 0,
|
|
@@ -47301,7 +47621,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
47301
47621
|
case "tiered": {
|
|
47302
47622
|
const selectableOptions = getSelectableCoursePricingOptionsForNow(
|
|
47303
47623
|
course,
|
|
47304
|
-
resolvePlanningDateInput(
|
|
47624
|
+
resolvePlanningDateInput(effectiveNowInput)
|
|
47305
47625
|
);
|
|
47306
47626
|
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
47307
47627
|
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
@@ -47317,12 +47637,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
47317
47637
|
selectableOptions,
|
|
47318
47638
|
requiresSelection: selectableOptions.length > 1,
|
|
47319
47639
|
selectedOption,
|
|
47640
|
+
slidingScale: null,
|
|
47641
|
+
selectedSlidingAmount: null,
|
|
47320
47642
|
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
47321
47643
|
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
47322
47644
|
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
47323
47645
|
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
47324
47646
|
};
|
|
47325
47647
|
}
|
|
47648
|
+
case "sliding_scale": {
|
|
47649
|
+
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
47650
|
+
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
47651
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
|
|
47652
|
+
return {
|
|
47653
|
+
currency,
|
|
47654
|
+
display: { kind: "unavailable", currency },
|
|
47655
|
+
selectableOptions: [],
|
|
47656
|
+
requiresSelection: true,
|
|
47657
|
+
selectedOption: null,
|
|
47658
|
+
slidingScale: null,
|
|
47659
|
+
selectedSlidingAmount: null,
|
|
47660
|
+
selectedPriceAmount: null,
|
|
47661
|
+
selectedRequiresPayment: false,
|
|
47662
|
+
hasPaidSelection: false,
|
|
47663
|
+
hasFreeSelection: false
|
|
47664
|
+
};
|
|
47665
|
+
}
|
|
47666
|
+
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
47667
|
+
return {
|
|
47668
|
+
currency,
|
|
47669
|
+
display: { kind: "range", minAmount, maxAmount, currency },
|
|
47670
|
+
selectableOptions: [],
|
|
47671
|
+
requiresSelection: normalizedSelectedAmount === null,
|
|
47672
|
+
selectedOption: null,
|
|
47673
|
+
slidingScale: {
|
|
47674
|
+
minAmount,
|
|
47675
|
+
maxAmount,
|
|
47676
|
+
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
47677
|
+
},
|
|
47678
|
+
selectedSlidingAmount: normalizedSelectedAmount,
|
|
47679
|
+
selectedPriceAmount: normalizedSelectedAmount,
|
|
47680
|
+
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
47681
|
+
hasPaidSelection: maxAmount > 0,
|
|
47682
|
+
hasFreeSelection: minAmount === 0
|
|
47683
|
+
};
|
|
47684
|
+
}
|
|
47326
47685
|
}
|
|
47327
47686
|
}
|
|
47328
47687
|
function formatCoursePriceDisplay(display, locale) {
|
|
@@ -51514,6 +51873,44 @@ function CoursePricingSelector({
|
|
|
51514
51873
|
)
|
|
51515
51874
|
] });
|
|
51516
51875
|
}
|
|
51876
|
+
function CourseSlidingScaleInput({
|
|
51877
|
+
pricing,
|
|
51878
|
+
value,
|
|
51879
|
+
onChange
|
|
51880
|
+
}) {
|
|
51881
|
+
const slidingScale = pricing.slidingScale;
|
|
51882
|
+
if (!slidingScale) {
|
|
51883
|
+
return null;
|
|
51884
|
+
}
|
|
51885
|
+
const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
|
|
51886
|
+
const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
|
|
51887
|
+
const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
|
|
51888
|
+
return /* @__PURE__ */ jsxs65("div", { className: "cr-form__field", children: [
|
|
51889
|
+
/* @__PURE__ */ jsx95("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
|
|
51890
|
+
/* @__PURE__ */ jsx95(
|
|
51891
|
+
"input",
|
|
51892
|
+
{
|
|
51893
|
+
id: "cr-sliding-amount",
|
|
51894
|
+
type: "number",
|
|
51895
|
+
min: slidingScale.minAmount / 100,
|
|
51896
|
+
max: slidingScale.maxAmount / 100,
|
|
51897
|
+
step: "0.01",
|
|
51898
|
+
inputMode: "decimal",
|
|
51899
|
+
className: "cr-form__input",
|
|
51900
|
+
value,
|
|
51901
|
+
onChange: (event) => onChange(event.target.value)
|
|
51902
|
+
}
|
|
51903
|
+
),
|
|
51904
|
+
/* @__PURE__ */ jsxs65("p", { className: "cr-text cr-text--muted", children: [
|
|
51905
|
+
"Choose between ",
|
|
51906
|
+
minLabel,
|
|
51907
|
+
" and ",
|
|
51908
|
+
maxLabel,
|
|
51909
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
51910
|
+
"."
|
|
51911
|
+
] })
|
|
51912
|
+
] });
|
|
51913
|
+
}
|
|
51517
51914
|
function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
|
|
51518
51915
|
const nameErrorId = "cr-name-error";
|
|
51519
51916
|
const emailErrorId = "cr-email-error";
|
|
@@ -51609,6 +52006,17 @@ var init_components2 = __esm({
|
|
|
51609
52006
|
|
|
51610
52007
|
// ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
51611
52008
|
import { useEffect as useEffect25, useMemo as useMemo19, useState as useState18 } from "react";
|
|
52009
|
+
function parseCurrencyInputToCents2(value) {
|
|
52010
|
+
const trimmed = value.trim();
|
|
52011
|
+
if (!trimmed) return null;
|
|
52012
|
+
const amount = Number(trimmed);
|
|
52013
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
52014
|
+
return Math.round(amount * 100);
|
|
52015
|
+
}
|
|
52016
|
+
function formatCentsAsCurrencyInput2(amount) {
|
|
52017
|
+
const major = amount / 100;
|
|
52018
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
52019
|
+
}
|
|
51612
52020
|
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
51613
52021
|
if (!course || portalAuthState === "checking") return false;
|
|
51614
52022
|
if (hasWaitlistClaimToken) return false;
|
|
@@ -51626,12 +52034,27 @@ function getSessionIdFromUrl() {
|
|
|
51626
52034
|
}
|
|
51627
52035
|
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
51628
52036
|
if (pricing?.requiresSelection && !pricing.selectedOption) {
|
|
52037
|
+
if (pricing.slidingScale) {
|
|
52038
|
+
return "Choose an amount to continue.";
|
|
52039
|
+
}
|
|
51629
52040
|
return "Choose a pricing option to continue.";
|
|
51630
52041
|
}
|
|
52042
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
|
|
52043
|
+
return "Choose an amount within the sliding scale.";
|
|
52044
|
+
}
|
|
52045
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
|
|
52046
|
+
return "Choose an amount within the sliding scale.";
|
|
52047
|
+
}
|
|
51631
52048
|
return null;
|
|
51632
52049
|
}
|
|
51633
52050
|
function buildCoursePricingOptionPayload(pricing) {
|
|
51634
|
-
|
|
52051
|
+
if (pricing?.selectedOption) {
|
|
52052
|
+
return { pricingOptionId: pricing.selectedOption.id };
|
|
52053
|
+
}
|
|
52054
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
|
|
52055
|
+
return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
52056
|
+
}
|
|
52057
|
+
return {};
|
|
51635
52058
|
}
|
|
51636
52059
|
function resolveHasCoursePayment(pricing) {
|
|
51637
52060
|
if (!pricing) {
|
|
@@ -51672,6 +52095,7 @@ function useCourseRegistrationWizard(props2) {
|
|
|
51672
52095
|
scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
|
|
51673
52096
|
);
|
|
51674
52097
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState18(null);
|
|
52098
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState18("");
|
|
51675
52099
|
const [formData, setFormData] = useState18({
|
|
51676
52100
|
name: "",
|
|
51677
52101
|
email: "",
|
|
@@ -51693,8 +52117,12 @@ function useCourseRegistrationWizard(props2) {
|
|
|
51693
52117
|
const [bookingMode, setBookingMode] = useState18(null);
|
|
51694
52118
|
const waitlistClaim = useWaitlistClaim();
|
|
51695
52119
|
const selectedCoursePricing = useMemo19(
|
|
51696
|
-
() => selectedCourse ? resolveCoursePricingState(
|
|
51697
|
-
|
|
52120
|
+
() => selectedCourse ? resolveCoursePricingState(
|
|
52121
|
+
selectedCourse,
|
|
52122
|
+
selectedPricingOptionId,
|
|
52123
|
+
parseCurrencyInputToCents2(selectedSlidingAmountInput)
|
|
52124
|
+
) : null,
|
|
52125
|
+
[selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
|
|
51698
52126
|
);
|
|
51699
52127
|
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
|
|
51700
52128
|
selectedCoursePricing
|
|
@@ -51767,9 +52195,13 @@ function useCourseRegistrationWizard(props2) {
|
|
|
51767
52195
|
useEffect25(() => {
|
|
51768
52196
|
if (!selectedCourse) {
|
|
51769
52197
|
setSelectedPricingOptionId(null);
|
|
52198
|
+
setSelectedSlidingAmountInput("");
|
|
51770
52199
|
return;
|
|
51771
52200
|
}
|
|
51772
52201
|
const defaultPricing = resolveCoursePricingState(selectedCourse, null);
|
|
52202
|
+
setSelectedSlidingAmountInput(
|
|
52203
|
+
defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
|
|
52204
|
+
);
|
|
51773
52205
|
setSelectedPricingOptionId((previous) => {
|
|
51774
52206
|
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
|
|
51775
52207
|
return previous;
|
|
@@ -52144,6 +52576,8 @@ function useCourseRegistrationWizard(props2) {
|
|
|
52144
52576
|
selectedCourse,
|
|
52145
52577
|
selectedPricingOptionId,
|
|
52146
52578
|
setSelectedPricingOptionId,
|
|
52579
|
+
selectedSlidingAmountInput,
|
|
52580
|
+
setSelectedSlidingAmountInput,
|
|
52147
52581
|
selectedCoursePricing,
|
|
52148
52582
|
setSelectedCourse,
|
|
52149
52583
|
formData,
|
|
@@ -52209,6 +52643,19 @@ var init_useCourseRegistrationWizard = __esm({
|
|
|
52209
52643
|
|
|
52210
52644
|
// ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.tsx
|
|
52211
52645
|
import { Fragment as Fragment23, jsx as jsx96, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
52646
|
+
function getCourseSlidingScaleMessage(pricing) {
|
|
52647
|
+
if (!pricing.slidingScale) {
|
|
52648
|
+
return null;
|
|
52649
|
+
}
|
|
52650
|
+
const selectedAmount = pricing.selectedSlidingAmount;
|
|
52651
|
+
if (selectedAmount === null) {
|
|
52652
|
+
return "Choose an amount to continue.";
|
|
52653
|
+
}
|
|
52654
|
+
if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
|
|
52655
|
+
return "Choose an amount within the sliding scale.";
|
|
52656
|
+
}
|
|
52657
|
+
return null;
|
|
52658
|
+
}
|
|
52212
52659
|
function CourseRegistrationWizard(props2) {
|
|
52213
52660
|
const {
|
|
52214
52661
|
showSessions = true,
|
|
@@ -52230,6 +52677,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
52230
52677
|
selectedCourse,
|
|
52231
52678
|
selectedPricingOptionId,
|
|
52232
52679
|
setSelectedPricingOptionId,
|
|
52680
|
+
selectedSlidingAmountInput,
|
|
52681
|
+
setSelectedSlidingAmountInput,
|
|
52233
52682
|
selectedCoursePricing,
|
|
52234
52683
|
formData,
|
|
52235
52684
|
setFormData,
|
|
@@ -52304,7 +52753,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
52304
52753
|
const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
|
|
52305
52754
|
const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
|
|
52306
52755
|
const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
|
|
52307
|
-
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
|
|
52756
|
+
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
|
|
52757
|
+
const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
|
|
52308
52758
|
const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
|
|
52309
52759
|
const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
|
|
52310
52760
|
course: selectedCourse,
|
|
@@ -52397,6 +52847,14 @@ function CourseRegistrationWizard(props2) {
|
|
|
52397
52847
|
onSelect: setSelectedPricingOptionId
|
|
52398
52848
|
}
|
|
52399
52849
|
),
|
|
52850
|
+
/* @__PURE__ */ jsx96(
|
|
52851
|
+
CourseSlidingScaleInput,
|
|
52852
|
+
{
|
|
52853
|
+
pricing: selectedCourseWithPricing.pricing,
|
|
52854
|
+
value: selectedSlidingAmountInput,
|
|
52855
|
+
onChange: setSelectedSlidingAmountInput
|
|
52856
|
+
}
|
|
52857
|
+
),
|
|
52400
52858
|
showSpamProtection && /* @__PURE__ */ jsx96("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx96(
|
|
52401
52859
|
AltchaWidget,
|
|
52402
52860
|
{
|
|
@@ -52434,7 +52892,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
52434
52892
|
{
|
|
52435
52893
|
type: "submit",
|
|
52436
52894
|
className: buttonClass,
|
|
52437
|
-
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
|
|
52895
|
+
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
|
|
52438
52896
|
children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
|
|
52439
52897
|
}
|
|
52440
52898
|
)
|
|
@@ -52444,6 +52902,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
52444
52902
|
),
|
|
52445
52903
|
courseSoldOut && /* @__PURE__ */ jsx96("p", { className: "cr-text cr-text--muted", children: "This course is fully booked and there is no waitlist available right now." }),
|
|
52446
52904
|
pricingSelectionMissing && /* @__PURE__ */ jsx96("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
|
|
52905
|
+
slidingScaleMessage && /* @__PURE__ */ jsx96("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
|
|
52447
52906
|
pricingUnavailable && /* @__PURE__ */ jsx96("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
|
|
52448
52907
|
eligibilityError && /* @__PURE__ */ jsx96("p", { className: "cr-text cr-text--error", children: eligibilityError })
|
|
52449
52908
|
] })
|
|
@@ -56754,6 +57213,21 @@ function fieldPlanToZod(plan, options = {}) {
|
|
|
56754
57213
|
}
|
|
56755
57214
|
});
|
|
56756
57215
|
}
|
|
57216
|
+
function fieldPresenceForPlan(plan) {
|
|
57217
|
+
return plan.required ? { kind: "required" } : { kind: "optional" };
|
|
57218
|
+
}
|
|
57219
|
+
function fieldPlanToObjectPropertyZod(plan, options = {}) {
|
|
57220
|
+
const schema = fieldPlanToZod(plan, options);
|
|
57221
|
+
const presence = fieldPresenceForPlan(plan);
|
|
57222
|
+
switch (presence.kind) {
|
|
57223
|
+
case "required":
|
|
57224
|
+
return schema;
|
|
57225
|
+
case "optional":
|
|
57226
|
+
return schema.optional();
|
|
57227
|
+
default:
|
|
57228
|
+
return assertNever7(presence);
|
|
57229
|
+
}
|
|
57230
|
+
}
|
|
56757
57231
|
function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
|
|
56758
57232
|
const message = fieldIssueToMessage(validationIssue);
|
|
56759
57233
|
const path = relativeZodIssuePath(validationIssue.path, rootPath);
|
|
@@ -56966,7 +57440,7 @@ function createManifestValidator(manifestOrFields, options = {}) {
|
|
|
56966
57440
|
function deriveContentZodFromPlans(plans, options) {
|
|
56967
57441
|
const shape = {};
|
|
56968
57442
|
for (const plan of plans) {
|
|
56969
|
-
shape[plan.fieldId] =
|
|
57443
|
+
shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
|
|
56970
57444
|
}
|
|
56971
57445
|
return z54.object(shape).catchall(z54.unknown()).passthrough();
|
|
56972
57446
|
}
|
|
@@ -97877,6 +98351,7 @@ var CANONICAL_REFUND_CONFLICT_CODES = [
|
|
|
97877
98351
|
];
|
|
97878
98352
|
var CANONICAL_REFUND_PLANNER_ERROR_CODES = [
|
|
97879
98353
|
...CANONICAL_REFUND_CONFLICT_CODES,
|
|
98354
|
+
"invalid_amount",
|
|
97880
98355
|
"amount_exceeds_remaining",
|
|
97881
98356
|
"pass_revoke_requires_full_refund",
|
|
97882
98357
|
"refund_failed"
|
|
@@ -97903,6 +98378,7 @@ var CUSTOMER_MEMBERSHIP_PAYMENT_REFUND_FAILED_CODES = [
|
|
|
97903
98378
|
// ../api/src/bookingRefundOutcomes.ts
|
|
97904
98379
|
var STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
|
|
97905
98380
|
"missing_amount",
|
|
98381
|
+
"invalid_amount",
|
|
97906
98382
|
"amount_exceeds_remaining",
|
|
97907
98383
|
"credit_refunds_disabled",
|
|
97908
98384
|
"missing_credit_customer",
|
|
@@ -97917,6 +98393,7 @@ var EVENT_ATTENDEE_REFUND_INVALID_CODES = [
|
|
|
97917
98393
|
var MANAGED_PRODUCT_REFUND_INVALID_CODES = [
|
|
97918
98394
|
"credit_refunds_disabled",
|
|
97919
98395
|
"not_refundable",
|
|
98396
|
+
"invalid_amount",
|
|
97920
98397
|
"amount_exceeds_remaining"
|
|
97921
98398
|
];
|
|
97922
98399
|
var CUSTOMER_PASS_REFUND_INVALID_CODES = [
|