@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
package/dist/client/client.mjs
CHANGED
|
@@ -23,12 +23,13 @@ var init_result = __esm({
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
// ../core/src/branded.ts
|
|
26
|
-
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
26
|
+
var unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId;
|
|
27
27
|
var init_branded = __esm({
|
|
28
28
|
"../core/src/branded.ts"() {
|
|
29
29
|
"use strict";
|
|
30
30
|
unsafeAsMediaAssetId = (id) => id;
|
|
31
31
|
unsafeAsStorageBucketName = (value) => value;
|
|
32
|
+
unsafeAsStoragePath = (value) => value;
|
|
32
33
|
unsafeAsPositiveByteCount = (value) => value;
|
|
33
34
|
unsafeAsPositiveSeconds = (value) => value;
|
|
34
35
|
unsafeAsFormId = (id) => id;
|
|
@@ -174,6 +175,7 @@ function publicEventPricingType(pricing) {
|
|
|
174
175
|
return "free";
|
|
175
176
|
case "single_paid":
|
|
176
177
|
case "ticket_types":
|
|
178
|
+
case "sliding_scale":
|
|
177
179
|
case "course":
|
|
178
180
|
return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
|
|
179
181
|
case "external":
|
|
@@ -186,6 +188,7 @@ function publicEventPricingCurrency(pricing) {
|
|
|
186
188
|
case "free_registration":
|
|
187
189
|
case "single_paid":
|
|
188
190
|
case "ticket_types":
|
|
191
|
+
case "sliding_scale":
|
|
189
192
|
return pricing.currency;
|
|
190
193
|
case "course":
|
|
191
194
|
return pricing.display.display.currency;
|
|
@@ -203,6 +206,8 @@ function publicEventPricingMode(pricing) {
|
|
|
203
206
|
return "single";
|
|
204
207
|
case "ticket_types":
|
|
205
208
|
return "ticket_types";
|
|
209
|
+
case "sliding_scale":
|
|
210
|
+
return "sliding_scale";
|
|
206
211
|
case "drop_in":
|
|
207
212
|
case "course":
|
|
208
213
|
case "external":
|
|
@@ -236,6 +241,8 @@ function formatCoursePriceDisplayLabel(display, options) {
|
|
|
236
241
|
return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
237
242
|
case "from":
|
|
238
243
|
return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
244
|
+
case "range":
|
|
245
|
+
return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
|
|
239
246
|
default:
|
|
240
247
|
return assertNever(display);
|
|
241
248
|
}
|
|
@@ -1039,9 +1046,20 @@ var init_types = __esm({
|
|
|
1039
1046
|
});
|
|
1040
1047
|
|
|
1041
1048
|
// ../media-core/src/fileSafety.ts
|
|
1049
|
+
function containsUnsafePathSegmentCharacter(value) {
|
|
1050
|
+
return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
|
|
1051
|
+
}
|
|
1052
|
+
function isReservedPathSegment(value) {
|
|
1053
|
+
return value === "." || value === "..";
|
|
1054
|
+
}
|
|
1055
|
+
function isUnsafePathSegment(segment) {
|
|
1056
|
+
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
1057
|
+
}
|
|
1058
|
+
var CONTROL_CHARACTER_PATTERN;
|
|
1042
1059
|
var init_fileSafety = __esm({
|
|
1043
1060
|
"../media-core/src/fileSafety.ts"() {
|
|
1044
1061
|
"use strict";
|
|
1062
|
+
CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
1045
1063
|
}
|
|
1046
1064
|
});
|
|
1047
1065
|
|
|
@@ -1081,11 +1099,21 @@ var init_fileDomain = __esm({
|
|
|
1081
1099
|
});
|
|
1082
1100
|
|
|
1083
1101
|
// ../media-core/src/fileStorage.ts
|
|
1102
|
+
function parseStoragePath(value) {
|
|
1103
|
+
return joinStoragePathSegments(value.split("/"));
|
|
1104
|
+
}
|
|
1105
|
+
function joinStoragePathSegments(segments) {
|
|
1106
|
+
if (segments.some(isUnsafePathSegment)) {
|
|
1107
|
+
return err("unsafe-path-segment");
|
|
1108
|
+
}
|
|
1109
|
+
return ok(unsafeAsStoragePath(segments.join("/")));
|
|
1110
|
+
}
|
|
1084
1111
|
var FILE_STORAGE_BUCKETS, PUBLIC_SITE_FILE_STORAGE_BUCKETS, PRIVATE_SITE_FILE_BUCKET_MIME_TYPES, TEMP_UPLOAD_BUCKET_MIME_TYPES;
|
|
1085
1112
|
var init_fileStorage = __esm({
|
|
1086
1113
|
"../media-core/src/fileStorage.ts"() {
|
|
1087
1114
|
"use strict";
|
|
1088
1115
|
init_src();
|
|
1116
|
+
init_fileSafety();
|
|
1089
1117
|
FILE_STORAGE_BUCKETS = {
|
|
1090
1118
|
publicSite: unsafeAsStorageBucketName("media"),
|
|
1091
1119
|
privateSite: unsafeAsStorageBucketName("site-files-private"),
|
|
@@ -1271,14 +1299,18 @@ var init_uploadVerificationContract = __esm({
|
|
|
1271
1299
|
});
|
|
1272
1300
|
|
|
1273
1301
|
// ../media-core/src/videoPrep.ts
|
|
1302
|
+
function unsafeAsPositiveVideoDurationSeconds(value) {
|
|
1303
|
+
return value;
|
|
1304
|
+
}
|
|
1274
1305
|
var VIDEO_PREP_LIMITS;
|
|
1275
1306
|
var init_videoPrep = __esm({
|
|
1276
1307
|
"../media-core/src/videoPrep.ts"() {
|
|
1277
1308
|
"use strict";
|
|
1309
|
+
init_src();
|
|
1278
1310
|
VIDEO_PREP_LIMITS = {
|
|
1279
|
-
maxRawByteCount: 500 * 1024 * 1024,
|
|
1280
|
-
inlineContentMaxDurationSeconds: 60,
|
|
1281
|
-
backgroundVideoMaxDurationSeconds: 30,
|
|
1311
|
+
maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
|
|
1312
|
+
inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
|
|
1313
|
+
backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
|
|
1282
1314
|
targetMaxDimensionPixels: 1080
|
|
1283
1315
|
};
|
|
1284
1316
|
}
|
|
@@ -1349,10 +1381,10 @@ var init_identifiers = __esm({
|
|
|
1349
1381
|
|
|
1350
1382
|
// ../media-core/src/url.ts
|
|
1351
1383
|
function isRelativeDirectImageStoragePath(storagePath) {
|
|
1352
|
-
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
|
|
1384
|
+
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
|
|
1353
1385
|
}
|
|
1354
1386
|
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
1355
|
-
return storagePath.startsWith("sites/");
|
|
1387
|
+
return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
|
|
1356
1388
|
}
|
|
1357
1389
|
function encodeStoragePath(storagePath) {
|
|
1358
1390
|
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
@@ -1433,6 +1465,7 @@ var DEFAULT_BASE_PATH, RELATIVE_STORAGE_PATH_PREFIXES, formatNumber, ORDER, getI
|
|
|
1433
1465
|
var init_url = __esm({
|
|
1434
1466
|
"../media-core/src/url.ts"() {
|
|
1435
1467
|
"use strict";
|
|
1468
|
+
init_fileStorage();
|
|
1436
1469
|
DEFAULT_BASE_PATH = "/api/img";
|
|
1437
1470
|
RELATIVE_STORAGE_PATH_PREFIXES = [
|
|
1438
1471
|
"originals/",
|
|
@@ -22919,9 +22952,12 @@ var init_schemas = __esm({
|
|
|
22919
22952
|
});
|
|
22920
22953
|
coursePricingSchema = z45.object({
|
|
22921
22954
|
bookingRequirement: z45.enum(["none", "required"]),
|
|
22922
|
-
pricingStrategy: z45.enum(["free", "single", "tiered"]),
|
|
22955
|
+
pricingStrategy: z45.enum(["free", "single", "tiered", "sliding_scale"]),
|
|
22923
22956
|
currency: z45.string(),
|
|
22924
22957
|
singlePriceAmount: z45.number().nullable(),
|
|
22958
|
+
slidingMinAmount: z45.number().nullable().optional(),
|
|
22959
|
+
slidingMaxAmount: z45.number().nullable().optional(),
|
|
22960
|
+
slidingSuggestedAmount: z45.number().nullable().optional(),
|
|
22925
22961
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
22926
22962
|
options: z45.array(coursePricingOptionSchema)
|
|
22927
22963
|
});
|
|
@@ -23086,6 +23122,19 @@ var init_schemas2 = __esm({
|
|
|
23086
23122
|
ticketTypes: z46.array(publicEventTicketTypeSchema),
|
|
23087
23123
|
display: publicEventTicketTypePriceDisplaySchema
|
|
23088
23124
|
}),
|
|
23125
|
+
z46.object({
|
|
23126
|
+
kind: z46.literal("sliding_scale"),
|
|
23127
|
+
minAmount: z46.number(),
|
|
23128
|
+
maxAmount: z46.number(),
|
|
23129
|
+
suggestedAmount: z46.number().nullable(),
|
|
23130
|
+
currency: z46.string(),
|
|
23131
|
+
display: z46.object({
|
|
23132
|
+
kind: z46.literal("range"),
|
|
23133
|
+
minAmount: z46.number(),
|
|
23134
|
+
maxAmount: z46.number(),
|
|
23135
|
+
currency: z46.string()
|
|
23136
|
+
})
|
|
23137
|
+
}),
|
|
23089
23138
|
z46.object({
|
|
23090
23139
|
kind: z46.literal("course"),
|
|
23091
23140
|
display: z46.object({ kind: z46.literal("course"), display: publicCoursePriceDisplaySchema })
|
|
@@ -23554,7 +23603,7 @@ function isRecord6(value) {
|
|
|
23554
23603
|
}
|
|
23555
23604
|
function isPublicEventPricing(value) {
|
|
23556
23605
|
if (!isRecord6(value) || typeof value.kind !== "string") return false;
|
|
23557
|
-
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
|
|
23606
|
+
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";
|
|
23558
23607
|
}
|
|
23559
23608
|
function isPublicEventTicketType(value) {
|
|
23560
23609
|
return isRecord6(value) && typeof value.id === "string";
|
|
@@ -24067,7 +24116,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
24067
24116
|
return left.name.localeCompare(right.name);
|
|
24068
24117
|
});
|
|
24069
24118
|
}
|
|
24070
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
|
|
24119
|
+
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
24120
|
+
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
24121
|
+
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
24071
24122
|
const currency = course.pricing?.currency ?? course.currency;
|
|
24072
24123
|
if (!course.pricing) {
|
|
24073
24124
|
const legacyAmount = course.priceCents ?? 0;
|
|
@@ -24077,6 +24128,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
24077
24128
|
selectableOptions: [],
|
|
24078
24129
|
requiresSelection: false,
|
|
24079
24130
|
selectedOption: null,
|
|
24131
|
+
slidingScale: null,
|
|
24132
|
+
selectedSlidingAmount: null,
|
|
24080
24133
|
selectedPriceAmount: legacyAmount,
|
|
24081
24134
|
selectedRequiresPayment: legacyAmount > 0,
|
|
24082
24135
|
hasPaidSelection: legacyAmount > 0,
|
|
@@ -24091,6 +24144,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
24091
24144
|
selectableOptions: [],
|
|
24092
24145
|
requiresSelection: false,
|
|
24093
24146
|
selectedOption: null,
|
|
24147
|
+
slidingScale: null,
|
|
24148
|
+
selectedSlidingAmount: null,
|
|
24094
24149
|
selectedPriceAmount: 0,
|
|
24095
24150
|
selectedRequiresPayment: false,
|
|
24096
24151
|
hasPaidSelection: false,
|
|
@@ -24104,6 +24159,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
24104
24159
|
selectableOptions: [],
|
|
24105
24160
|
requiresSelection: false,
|
|
24106
24161
|
selectedOption: null,
|
|
24162
|
+
slidingScale: null,
|
|
24163
|
+
selectedSlidingAmount: null,
|
|
24107
24164
|
selectedPriceAmount: amount,
|
|
24108
24165
|
selectedRequiresPayment: amount > 0,
|
|
24109
24166
|
hasPaidSelection: amount > 0,
|
|
@@ -24113,7 +24170,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
24113
24170
|
case "tiered": {
|
|
24114
24171
|
const selectableOptions = getSelectableCoursePricingOptionsForNow(
|
|
24115
24172
|
course,
|
|
24116
|
-
resolvePlanningDateInput(
|
|
24173
|
+
resolvePlanningDateInput(effectiveNowInput)
|
|
24117
24174
|
);
|
|
24118
24175
|
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
24119
24176
|
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
@@ -24129,12 +24186,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
24129
24186
|
selectableOptions,
|
|
24130
24187
|
requiresSelection: selectableOptions.length > 1,
|
|
24131
24188
|
selectedOption,
|
|
24189
|
+
slidingScale: null,
|
|
24190
|
+
selectedSlidingAmount: null,
|
|
24132
24191
|
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
24133
24192
|
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
24134
24193
|
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
24135
24194
|
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
24136
24195
|
};
|
|
24137
24196
|
}
|
|
24197
|
+
case "sliding_scale": {
|
|
24198
|
+
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
24199
|
+
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
24200
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
|
|
24201
|
+
return {
|
|
24202
|
+
currency,
|
|
24203
|
+
display: { kind: "unavailable", currency },
|
|
24204
|
+
selectableOptions: [],
|
|
24205
|
+
requiresSelection: true,
|
|
24206
|
+
selectedOption: null,
|
|
24207
|
+
slidingScale: null,
|
|
24208
|
+
selectedSlidingAmount: null,
|
|
24209
|
+
selectedPriceAmount: null,
|
|
24210
|
+
selectedRequiresPayment: false,
|
|
24211
|
+
hasPaidSelection: false,
|
|
24212
|
+
hasFreeSelection: false
|
|
24213
|
+
};
|
|
24214
|
+
}
|
|
24215
|
+
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
24216
|
+
return {
|
|
24217
|
+
currency,
|
|
24218
|
+
display: { kind: "range", minAmount, maxAmount, currency },
|
|
24219
|
+
selectableOptions: [],
|
|
24220
|
+
requiresSelection: normalizedSelectedAmount === null,
|
|
24221
|
+
selectedOption: null,
|
|
24222
|
+
slidingScale: {
|
|
24223
|
+
minAmount,
|
|
24224
|
+
maxAmount,
|
|
24225
|
+
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
24226
|
+
},
|
|
24227
|
+
selectedSlidingAmount: normalizedSelectedAmount,
|
|
24228
|
+
selectedPriceAmount: normalizedSelectedAmount,
|
|
24229
|
+
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
24230
|
+
hasPaidSelection: maxAmount > 0,
|
|
24231
|
+
hasFreeSelection: minAmount === 0
|
|
24232
|
+
};
|
|
24233
|
+
}
|
|
24138
24234
|
}
|
|
24139
24235
|
}
|
|
24140
24236
|
function formatCoursePriceDisplay(display, locale) {
|
|
@@ -29382,6 +29478,7 @@ var init_booking_form_reserved_fields = __esm({
|
|
|
29382
29478
|
"selectedDate",
|
|
29383
29479
|
"selectedSlot",
|
|
29384
29480
|
"discountCode",
|
|
29481
|
+
"selectedSlidingAmountInput",
|
|
29385
29482
|
"selectedCollectionOptionKind",
|
|
29386
29483
|
"selectedAppointmentPackageId"
|
|
29387
29484
|
];
|
|
@@ -29667,6 +29764,32 @@ function readOptionalString(value) {
|
|
|
29667
29764
|
function readOptionalNumber(value) {
|
|
29668
29765
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
29669
29766
|
}
|
|
29767
|
+
function getBookingServiceSlidingScale(service) {
|
|
29768
|
+
const pricing = service?.pricing;
|
|
29769
|
+
if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
|
|
29770
|
+
return null;
|
|
29771
|
+
}
|
|
29772
|
+
return {
|
|
29773
|
+
minAmount: pricing.slidingMinAmount,
|
|
29774
|
+
maxAmount: pricing.slidingMaxAmount,
|
|
29775
|
+
suggestedAmount: pricing.slidingSuggestedAmount ?? null,
|
|
29776
|
+
currency: pricing.currency
|
|
29777
|
+
};
|
|
29778
|
+
}
|
|
29779
|
+
function parseBookingCurrencyInputToCents(value) {
|
|
29780
|
+
const trimmed = value?.trim() ?? "";
|
|
29781
|
+
if (!trimmed) return null;
|
|
29782
|
+
if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
|
|
29783
|
+
const parsed = Number(trimmed);
|
|
29784
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
29785
|
+
return Math.round(parsed * 100);
|
|
29786
|
+
}
|
|
29787
|
+
function formatBookingCentsAsCurrencyInput(amount) {
|
|
29788
|
+
return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
|
|
29789
|
+
}
|
|
29790
|
+
function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
|
|
29791
|
+
return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
|
|
29792
|
+
}
|
|
29670
29793
|
function readStringArray(value) {
|
|
29671
29794
|
if (!Array.isArray(value)) return void 0;
|
|
29672
29795
|
const strings = value.filter((item) => typeof item === "string");
|
|
@@ -29855,6 +29978,20 @@ function prepareBookingSubmission(input) {
|
|
|
29855
29978
|
};
|
|
29856
29979
|
}
|
|
29857
29980
|
const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
|
|
29981
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
29982
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
29983
|
+
input.data.selectedSlidingAmountInput
|
|
29984
|
+
);
|
|
29985
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
|
|
29986
|
+
return {
|
|
29987
|
+
ok: false,
|
|
29988
|
+
error: {
|
|
29989
|
+
tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
|
|
29990
|
+
serviceId,
|
|
29991
|
+
serviceTitle: selectedService.title || serviceId
|
|
29992
|
+
}
|
|
29993
|
+
};
|
|
29994
|
+
}
|
|
29858
29995
|
if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
|
|
29859
29996
|
return {
|
|
29860
29997
|
ok: false,
|
|
@@ -29882,6 +30019,7 @@ function prepareBookingSubmission(input) {
|
|
|
29882
30019
|
...common,
|
|
29883
30020
|
kind: "standard",
|
|
29884
30021
|
...discountCode ? { discountCode } : {},
|
|
30022
|
+
...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
|
|
29885
30023
|
...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
|
|
29886
30024
|
altchaSolution: input.altchaSolution ?? null
|
|
29887
30025
|
}
|
|
@@ -29895,6 +30033,10 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
29895
30033
|
return `Service not found: ${error.serviceId}`;
|
|
29896
30034
|
case "payment-option-required":
|
|
29897
30035
|
return `Please choose how you want to pay for "${error.serviceTitle}".`;
|
|
30036
|
+
case "sliding-amount-required":
|
|
30037
|
+
return `Please choose an amount for "${error.serviceTitle}".`;
|
|
30038
|
+
case "sliding-amount-out-of-range":
|
|
30039
|
+
return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
29898
30040
|
case "payment-option-unsupported":
|
|
29899
30041
|
return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
29900
30042
|
case "service-missing-duration":
|
|
@@ -30045,6 +30187,7 @@ var init_booking_form_interactive = __esm({
|
|
|
30045
30187
|
title: z66.string(),
|
|
30046
30188
|
description: z66.string().nullable().optional().transform((value) => value ?? void 0),
|
|
30047
30189
|
durationMinutes: z66.number().optional(),
|
|
30190
|
+
pricing: z66.custom().optional(),
|
|
30048
30191
|
priceAmount: z66.number().nullable().optional(),
|
|
30049
30192
|
priceCurrency: z66.string().nullable().optional(),
|
|
30050
30193
|
paymentTerms: blockBookingPaymentTermsSchema.optional(),
|
|
@@ -34963,12 +35106,13 @@ var init_carousel_client = __esm({
|
|
|
34963
35106
|
]
|
|
34964
35107
|
);
|
|
34965
35108
|
const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
|
|
35109
|
+
const canAutoplay = normalized.autoplay && slides.length > 1;
|
|
34966
35110
|
const cssVars = React12.useMemo(
|
|
34967
35111
|
() => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
|
|
34968
35112
|
[normalized.slidesToShow]
|
|
34969
35113
|
);
|
|
34970
35114
|
const plugins = React12.useMemo(() => {
|
|
34971
|
-
if (!
|
|
35115
|
+
if (!canAutoplay) return void 0;
|
|
34972
35116
|
return [
|
|
34973
35117
|
Autoplay({
|
|
34974
35118
|
delay: normalized.autoplayDelay,
|
|
@@ -34978,7 +35122,7 @@ var init_carousel_client = __esm({
|
|
|
34978
35122
|
// Continue after manual navigation
|
|
34979
35123
|
})
|
|
34980
35124
|
];
|
|
34981
|
-
}, [
|
|
35125
|
+
}, [canAutoplay, normalized.autoplayDelay]);
|
|
34982
35126
|
const [viewportRef, api] = useEmblaCarousel(
|
|
34983
35127
|
{
|
|
34984
35128
|
align: "start",
|
|
@@ -35017,7 +35161,7 @@ var init_carousel_client = __esm({
|
|
|
35017
35161
|
};
|
|
35018
35162
|
}, [api]);
|
|
35019
35163
|
React12.useEffect(() => {
|
|
35020
|
-
if (!api || !
|
|
35164
|
+
if (!api || !canAutoplay) return;
|
|
35021
35165
|
const autoplayPlugin = api.plugins()?.autoplay;
|
|
35022
35166
|
if (!autoplayPlugin) return;
|
|
35023
35167
|
const handleVisibility = () => {
|
|
@@ -35026,7 +35170,7 @@ var init_carousel_client = __esm({
|
|
|
35026
35170
|
};
|
|
35027
35171
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
35028
35172
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
35029
|
-
}, [api,
|
|
35173
|
+
}, [api, canAutoplay]);
|
|
35030
35174
|
const inner = /* @__PURE__ */ jsxs53(Fragment13, { children: [
|
|
35031
35175
|
/* @__PURE__ */ jsx68("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx68(
|
|
35032
35176
|
"div",
|
|
@@ -35077,7 +35221,7 @@ var init_carousel_client = __esm({
|
|
|
35077
35221
|
"data-show-controls": normalized.showControls ? "true" : "false",
|
|
35078
35222
|
"data-show-dots": normalized.showDots ? "true" : "false",
|
|
35079
35223
|
"data-arrow-visibility": normalized.arrowVisibility,
|
|
35080
|
-
"data-autoplay":
|
|
35224
|
+
"data-autoplay": canAutoplay ? "true" : "false",
|
|
35081
35225
|
"data-loop": normalized.loop ? "true" : "false",
|
|
35082
35226
|
children: inner
|
|
35083
35227
|
}
|
|
@@ -36080,6 +36224,7 @@ function createBlockApi(config) {
|
|
|
36080
36224
|
body: {
|
|
36081
36225
|
courseId: data.courseId,
|
|
36082
36226
|
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
36227
|
+
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
36083
36228
|
email: data.email,
|
|
36084
36229
|
name: data.name,
|
|
36085
36230
|
phone: data.phone,
|
|
@@ -40280,6 +40425,7 @@ function useBookingSubmission(_siteId) {
|
|
|
40280
40425
|
customFields: data.customFields,
|
|
40281
40426
|
timezone: data.timezone,
|
|
40282
40427
|
discountCode: data.discountCode,
|
|
40428
|
+
selectedSlidingAmount: data.selectedSlidingAmount,
|
|
40283
40429
|
selectedCollectionOptionKind: data.selectedCollectionOptionKind,
|
|
40284
40430
|
altchaSolution: data.altchaSolution ?? null,
|
|
40285
40431
|
successUrl: data.successUrl,
|
|
@@ -40808,6 +40954,9 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
40808
40954
|
fieldValues: collectInitialFieldValues(initialData),
|
|
40809
40955
|
touchedFields: {},
|
|
40810
40956
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
40957
|
+
selectedSlidingAmountInput: toOptionalString(
|
|
40958
|
+
initialData.selectedSlidingAmountInput
|
|
40959
|
+
) ?? "",
|
|
40811
40960
|
selectedCollectionOptionKind: toSelectedCollectionOptionKind(
|
|
40812
40961
|
initialData.selectedCollectionOptionKind
|
|
40813
40962
|
),
|
|
@@ -40860,6 +41009,7 @@ function bookingFlowReducer(state, event) {
|
|
|
40860
41009
|
selectedDate: void 0,
|
|
40861
41010
|
selectedSlot: null,
|
|
40862
41011
|
selectedAppointmentPackageId: void 0,
|
|
41012
|
+
selectedSlidingAmountInput: "",
|
|
40863
41013
|
selectedCollectionOptionKind: void 0,
|
|
40864
41014
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
40865
41015
|
};
|
|
@@ -40913,6 +41063,13 @@ function bookingFlowReducer(state, event) {
|
|
|
40913
41063
|
selectedAppointmentPackageId: void 0,
|
|
40914
41064
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
40915
41065
|
};
|
|
41066
|
+
case "sliding-amount-changed":
|
|
41067
|
+
return {
|
|
41068
|
+
...state,
|
|
41069
|
+
selectedSlidingAmountInput: event.value,
|
|
41070
|
+
selectedAppointmentPackageId: void 0,
|
|
41071
|
+
validationErrors: clearBookingFormError(state.validationErrors)
|
|
41072
|
+
};
|
|
40916
41073
|
case "appointment-package-selected":
|
|
40917
41074
|
return {
|
|
40918
41075
|
...state,
|
|
@@ -41015,6 +41172,7 @@ function toBookingFormData(state) {
|
|
|
41015
41172
|
selectedDate: state.selectedDate,
|
|
41016
41173
|
selectedSlot: state.selectedSlot?.startAt,
|
|
41017
41174
|
discountCode: state.discountCode || void 0,
|
|
41175
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
|
|
41018
41176
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
41019
41177
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId
|
|
41020
41178
|
};
|
|
@@ -41032,7 +41190,8 @@ function buildBookingStepResolution(input) {
|
|
|
41032
41190
|
input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
|
|
41033
41191
|
);
|
|
41034
41192
|
const selectedService = paymentResolution.service;
|
|
41035
|
-
const
|
|
41193
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
41194
|
+
const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
|
|
41036
41195
|
input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
41037
41196
|
);
|
|
41038
41197
|
const hasFields = Boolean(input.form.schema?.fields.length);
|
|
@@ -41076,6 +41235,18 @@ function validateBookingStep(input) {
|
|
|
41076
41235
|
services: input.services,
|
|
41077
41236
|
defaultServiceId: input.defaultServiceId
|
|
41078
41237
|
});
|
|
41238
|
+
const slidingScale = getBookingServiceSlidingScale(resolution.service);
|
|
41239
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(
|
|
41240
|
+
slidingScale,
|
|
41241
|
+
parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
|
|
41242
|
+
)) {
|
|
41243
|
+
return {
|
|
41244
|
+
ok: false,
|
|
41245
|
+
errors: createFormBookingValidationError(
|
|
41246
|
+
"Please choose an amount within the sliding scale"
|
|
41247
|
+
)
|
|
41248
|
+
};
|
|
41249
|
+
}
|
|
41079
41250
|
if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
|
|
41080
41251
|
return { ok: true };
|
|
41081
41252
|
}
|
|
@@ -41474,6 +41645,7 @@ var init_useHeadlessBookingFlow_state = __esm({
|
|
|
41474
41645
|
"../blocks/src/system/runtime/hooks/useHeadlessBookingFlow.state.ts"() {
|
|
41475
41646
|
"use strict";
|
|
41476
41647
|
init_booking_form_headless_state();
|
|
41648
|
+
init_booking_form_state();
|
|
41477
41649
|
}
|
|
41478
41650
|
});
|
|
41479
41651
|
|
|
@@ -41513,11 +41685,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
41513
41685
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
41514
41686
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
41515
41687
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
41688
|
+
const lastSlidingServiceIdRef = useRef9(null);
|
|
41689
|
+
useEffect10(() => {
|
|
41690
|
+
const selectedId = selectedService?.id ?? null;
|
|
41691
|
+
if (lastSlidingServiceIdRef.current === selectedId) return;
|
|
41692
|
+
lastSlidingServiceIdRef.current = selectedId;
|
|
41693
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
41694
|
+
dispatch({
|
|
41695
|
+
type: "sliding-amount-changed",
|
|
41696
|
+
value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
41697
|
+
});
|
|
41698
|
+
}, [selectedService]);
|
|
41516
41699
|
const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
|
|
41700
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
41701
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
41702
|
+
state.selectedSlidingAmountInput
|
|
41703
|
+
);
|
|
41704
|
+
const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
|
|
41517
41705
|
const canLoadAppointmentPackages = Boolean(
|
|
41518
|
-
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
41706
|
+
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
|
|
41519
41707
|
);
|
|
41520
|
-
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
41708
|
+
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
41521
41709
|
const data = useMemo8(() => toBookingFormData(state), [state]);
|
|
41522
41710
|
const availabilityDatesQuery = useMemo8(
|
|
41523
41711
|
() => buildBookingAvailabilityQuery({
|
|
@@ -41747,13 +41935,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
41747
41935
|
state.selectedSlot
|
|
41748
41936
|
]);
|
|
41749
41937
|
const appointmentDiscountContext = useMemo8(
|
|
41750
|
-
() => selectedService &&
|
|
41751
|
-
[
|
|
41938
|
+
() => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
41939
|
+
[selectedAppointmentPriceAmount, selectedService?.id]
|
|
41752
41940
|
);
|
|
41753
41941
|
const discountUi = useDiscountCodeUi({
|
|
41754
41942
|
api,
|
|
41755
41943
|
discountContext: appointmentDiscountContext,
|
|
41756
|
-
subtotalCents:
|
|
41944
|
+
subtotalCents: selectedAppointmentPriceAmount
|
|
41757
41945
|
});
|
|
41758
41946
|
const { submit, clearFeedback } = useBookingSubmission(options.siteId);
|
|
41759
41947
|
const submittingRef = useRef9(false);
|
|
@@ -41896,6 +42084,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
41896
42084
|
type: "appointment-package-selected",
|
|
41897
42085
|
packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
|
|
41898
42086
|
}),
|
|
42087
|
+
setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
|
|
41899
42088
|
setDiscountCode: (code) => {
|
|
41900
42089
|
dispatch({ type: "discount-code-changed", code });
|
|
41901
42090
|
latestRef.current.setDiscountCode(code);
|
|
@@ -41966,11 +42155,11 @@ function useHeadlessBookingFlow(options) {
|
|
|
41966
42155
|
() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
41967
42156
|
serviceTitle: selectedService.title,
|
|
41968
42157
|
paymentTerms: selectedService.paymentTerms,
|
|
41969
|
-
priceAmount:
|
|
42158
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
41970
42159
|
priceCurrency: selectedService.priceCurrency,
|
|
41971
42160
|
bookingStartAt: state.selectedSlot?.startAt
|
|
41972
42161
|
}) : null,
|
|
41973
|
-
[paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
|
|
42162
|
+
[paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
|
|
41974
42163
|
);
|
|
41975
42164
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
41976
42165
|
const selectedAppointmentPackage = appointmentPackageItems.find(
|
|
@@ -41999,6 +42188,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
41999
42188
|
selection: null,
|
|
42000
42189
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
42001
42190
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
42191
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
42192
|
+
selectedSlidingAmount,
|
|
42193
|
+
slidingScale: selectedServiceSlidingScale,
|
|
42002
42194
|
appointmentPackages: appointmentPackagesModel,
|
|
42003
42195
|
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
42004
42196
|
} : {
|
|
@@ -42007,6 +42199,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
42007
42199
|
selection: paymentSelection,
|
|
42008
42200
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
42009
42201
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
42202
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
42203
|
+
selectedSlidingAmount,
|
|
42204
|
+
slidingScale: selectedServiceSlidingScale,
|
|
42010
42205
|
appointmentPackages: appointmentPackagesModel
|
|
42011
42206
|
};
|
|
42012
42207
|
return {
|
|
@@ -42621,6 +42816,9 @@ var init_FieldValidationMessage = __esm({
|
|
|
42621
42816
|
|
|
42622
42817
|
// ../blocks/src/system/runtime/nodes/booking-form.default-ui.tsx
|
|
42623
42818
|
import { Fragment as Fragment15, jsx as jsx78, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
42819
|
+
function formatBookingAmount(amount, currency) {
|
|
42820
|
+
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
42821
|
+
}
|
|
42624
42822
|
function HeadlessBookingDefaultForm({
|
|
42625
42823
|
booking,
|
|
42626
42824
|
onSubmit
|
|
@@ -42897,6 +43095,7 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
42897
43095
|
}
|
|
42898
43096
|
const packageOptions = booking.payment.appointmentPackages.items;
|
|
42899
43097
|
const hasPackageOptions = packageOptions.length > 0;
|
|
43098
|
+
const slidingScale = booking.payment.slidingScale;
|
|
42900
43099
|
return /* @__PURE__ */ jsxs59("div", { className: "ab-stack", children: [
|
|
42901
43100
|
/* @__PURE__ */ jsxs59("div", { className: "ab-info-box", children: [
|
|
42902
43101
|
/* @__PURE__ */ jsx78("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
|
|
@@ -42907,6 +43106,28 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
42907
43106
|
booking.payment.appointmentPackages.state.message,
|
|
42908
43107
|
" You can continue with the normal payment option."
|
|
42909
43108
|
] }) : null,
|
|
43109
|
+
slidingScale ? /* @__PURE__ */ jsxs59("div", { className: "rb-space-y-2", children: [
|
|
43110
|
+
/* @__PURE__ */ jsx78("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
|
|
43111
|
+
/* @__PURE__ */ jsxs59("p", { className: "rb-caption status-muted", children: [
|
|
43112
|
+
formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
|
|
43113
|
+
" to ",
|
|
43114
|
+
formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
|
|
43115
|
+
slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
|
|
43116
|
+
] }),
|
|
43117
|
+
/* @__PURE__ */ jsx78(
|
|
43118
|
+
"input",
|
|
43119
|
+
{
|
|
43120
|
+
id: "appointment-sliding-amount",
|
|
43121
|
+
type: "number",
|
|
43122
|
+
className: "form-input",
|
|
43123
|
+
min: slidingScale.minAmount / 100,
|
|
43124
|
+
max: slidingScale.maxAmount / 100,
|
|
43125
|
+
step: "0.01",
|
|
43126
|
+
value: booking.payment.selectedSlidingAmountInput,
|
|
43127
|
+
onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
|
|
43128
|
+
}
|
|
43129
|
+
)
|
|
43130
|
+
] }) : null,
|
|
42910
43131
|
/* @__PURE__ */ jsxs59("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
|
|
42911
43132
|
packageOptions.map((appointmentPackage) => {
|
|
42912
43133
|
const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
|
|
@@ -44753,6 +44974,7 @@ function useEligibility(params) {
|
|
|
44753
44974
|
occurrenceId: params.occurrenceId,
|
|
44754
44975
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
44755
44976
|
ticketTypeId: params.ticketTypeId ?? void 0,
|
|
44977
|
+
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
44756
44978
|
email: params.email.trim().toLowerCase(),
|
|
44757
44979
|
ticketsCount: params.ticketsCount
|
|
44758
44980
|
});
|
|
@@ -44773,7 +44995,7 @@ function useEligibility(params) {
|
|
|
44773
44995
|
return () => {
|
|
44774
44996
|
cancelled = true;
|
|
44775
44997
|
};
|
|
44776
|
-
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
|
|
44998
|
+
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
|
|
44777
44999
|
return {
|
|
44778
45000
|
state,
|
|
44779
45001
|
eligibility: state.eligibility,
|
|
@@ -45124,6 +45346,41 @@ function TicketCounterLimit(props2) {
|
|
|
45124
45346
|
] }) : null
|
|
45125
45347
|
] });
|
|
45126
45348
|
}
|
|
45349
|
+
function formatCurrencyInputAmount(amount) {
|
|
45350
|
+
const major = amount / 100;
|
|
45351
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
45352
|
+
}
|
|
45353
|
+
function SlidingScaleAmountField(props2) {
|
|
45354
|
+
const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
|
|
45355
|
+
const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
|
|
45356
|
+
const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
|
|
45357
|
+
return /* @__PURE__ */ jsxs66("div", { className: "er-field", children: [
|
|
45358
|
+
/* @__PURE__ */ jsx93("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
|
|
45359
|
+
/* @__PURE__ */ jsx93(
|
|
45360
|
+
"input",
|
|
45361
|
+
{
|
|
45362
|
+
id: "er-sliding-amount",
|
|
45363
|
+
type: "number",
|
|
45364
|
+
min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
|
|
45365
|
+
max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
|
|
45366
|
+
step: "0.01",
|
|
45367
|
+
inputMode: "decimal",
|
|
45368
|
+
className: "er-input",
|
|
45369
|
+
value: props2.value,
|
|
45370
|
+
onChange: (event) => props2.onChange?.(event.target.value)
|
|
45371
|
+
}
|
|
45372
|
+
),
|
|
45373
|
+
/* @__PURE__ */ jsxs66("p", { className: "er-text er-text--muted", children: [
|
|
45374
|
+
"Choose between ",
|
|
45375
|
+
minLabel,
|
|
45376
|
+
" and ",
|
|
45377
|
+
maxLabel,
|
|
45378
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
45379
|
+
"."
|
|
45380
|
+
] }),
|
|
45381
|
+
props2.message ? /* @__PURE__ */ jsx93("p", { className: "er-text er-text--muted", children: props2.message }) : null
|
|
45382
|
+
] });
|
|
45383
|
+
}
|
|
45127
45384
|
function getTicketTypeCounterAvailabilityLabel(input) {
|
|
45128
45385
|
if (input.selectedRemainingCapacity !== null) {
|
|
45129
45386
|
return `${input.selectedRemainingCapacity} remaining for this ticket type`;
|
|
@@ -45195,6 +45452,10 @@ var init_TicketSelectionStep = __esm({
|
|
|
45195
45452
|
maxTickets,
|
|
45196
45453
|
selectedTicketTypeId = null,
|
|
45197
45454
|
onTicketTypeChange,
|
|
45455
|
+
slidingScale = null,
|
|
45456
|
+
selectedSlidingAmountInput = "",
|
|
45457
|
+
slidingScaleSelectionMessage = null,
|
|
45458
|
+
onSlidingAmountChange,
|
|
45198
45459
|
onTicketsChange
|
|
45199
45460
|
}) => {
|
|
45200
45461
|
const deliveryMode = event?.deliveryMode ?? "in_person";
|
|
@@ -45310,6 +45571,16 @@ var init_TicketSelectionStep = __esm({
|
|
|
45310
45571
|
] })
|
|
45311
45572
|
] })
|
|
45312
45573
|
] }) : /* @__PURE__ */ jsxs66(Fragment18, { children: [
|
|
45574
|
+
slidingScale ? /* @__PURE__ */ jsx93(
|
|
45575
|
+
SlidingScaleAmountField,
|
|
45576
|
+
{
|
|
45577
|
+
slidingScale,
|
|
45578
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
|
|
45579
|
+
value: selectedSlidingAmountInput,
|
|
45580
|
+
message: slidingScaleSelectionMessage,
|
|
45581
|
+
onChange: onSlidingAmountChange
|
|
45582
|
+
}
|
|
45583
|
+
) : null,
|
|
45313
45584
|
/* @__PURE__ */ jsx93("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
|
|
45314
45585
|
/* @__PURE__ */ jsxs66("div", { className: "er-ticket-counter-group", children: [
|
|
45315
45586
|
/* @__PURE__ */ jsx93(
|
|
@@ -46324,6 +46595,10 @@ function EventRegistrationWizardContent(props2) {
|
|
|
46324
46595
|
maxTickets: wizard.maxTicketsNum,
|
|
46325
46596
|
selectedTicketTypeId: wizard.selectedTicketTypeId,
|
|
46326
46597
|
onTicketTypeChange: wizard.setSelectedTicketTypeId,
|
|
46598
|
+
slidingScale: wizard.selectedEventSlidingScale,
|
|
46599
|
+
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
46600
|
+
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
46601
|
+
onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
|
|
46327
46602
|
onTicketsChange: wizard.setTicketsCount
|
|
46328
46603
|
}
|
|
46329
46604
|
)
|
|
@@ -46540,7 +46815,7 @@ function EventRegistrationSummaryBar(props2) {
|
|
|
46540
46815
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
46541
46816
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
46542
46817
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
46543
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
46818
|
+
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
46544
46819
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
|
|
46545
46820
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
46546
46821
|
const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
|
|
@@ -46991,6 +47266,7 @@ function useEventRegistrationSubmit(options) {
|
|
|
46991
47266
|
occurrenceId: submitOccurrenceId,
|
|
46992
47267
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
46993
47268
|
ticketTypeId: options.selectedTicketTypeId ?? void 0,
|
|
47269
|
+
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
46994
47270
|
email: options.formData.email.trim().toLowerCase(),
|
|
46995
47271
|
name: options.formData.name.trim(),
|
|
46996
47272
|
ticketsCount: options.ticketsCount,
|
|
@@ -47100,6 +47376,35 @@ var init_useEventRegistrationSubmit = __esm({
|
|
|
47100
47376
|
|
|
47101
47377
|
// ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
47102
47378
|
import { useCallback as useCallback8, useEffect as useEffect17, useMemo as useMemo12, useReducer as useReducer10, useState as useState9 } from "react";
|
|
47379
|
+
function parseCurrencyInputToCents(value) {
|
|
47380
|
+
const trimmed = value.trim();
|
|
47381
|
+
if (!trimmed) return null;
|
|
47382
|
+
const amount = Number(trimmed);
|
|
47383
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
47384
|
+
return Math.round(amount * 100);
|
|
47385
|
+
}
|
|
47386
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
47387
|
+
const major = amount / 100;
|
|
47388
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
47389
|
+
}
|
|
47390
|
+
function getSlidingScaleForEvent(event) {
|
|
47391
|
+
const pricing = event ? resolveRuntimeEventPricing(event) : null;
|
|
47392
|
+
return pricing?.kind === "sliding_scale" ? {
|
|
47393
|
+
minAmount: pricing.minAmount,
|
|
47394
|
+
maxAmount: pricing.maxAmount,
|
|
47395
|
+
suggestedAmount: pricing.suggestedAmount
|
|
47396
|
+
} : null;
|
|
47397
|
+
}
|
|
47398
|
+
function getSlidingScaleSelectionMessage(input) {
|
|
47399
|
+
if (!input.slidingScale) return null;
|
|
47400
|
+
if (input.selectedAmount === null) {
|
|
47401
|
+
return "Choose an amount to continue.";
|
|
47402
|
+
}
|
|
47403
|
+
if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
|
|
47404
|
+
return "Choose an amount within the sliding scale.";
|
|
47405
|
+
}
|
|
47406
|
+
return null;
|
|
47407
|
+
}
|
|
47103
47408
|
function useEventRegistrationWizard(options) {
|
|
47104
47409
|
const api = useBlockApi();
|
|
47105
47410
|
const registrationEvents = useMemo12(
|
|
@@ -47144,6 +47449,10 @@ function useEventRegistrationWizard(options) {
|
|
|
47144
47449
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
47145
47450
|
);
|
|
47146
47451
|
const [selectedTicketTypeId, setSelectedTicketTypeId] = useState9(null);
|
|
47452
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState9(() => {
|
|
47453
|
+
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
47454
|
+
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
47455
|
+
});
|
|
47147
47456
|
const [registrationResult, setRegistrationResult] = useState9(null);
|
|
47148
47457
|
const [errorMessage, setErrorMessage] = useState9("");
|
|
47149
47458
|
const [altchaSolution, setAltchaSolution] = useState9(null);
|
|
@@ -47180,6 +47489,7 @@ function useEventRegistrationWizard(options) {
|
|
|
47180
47489
|
occurrenceId,
|
|
47181
47490
|
attendanceMode: selectedAttendanceMode,
|
|
47182
47491
|
ticketTypeId: selectedTicketTypeId,
|
|
47492
|
+
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
47183
47493
|
email: formData.email,
|
|
47184
47494
|
ticketsCount
|
|
47185
47495
|
});
|
|
@@ -47315,6 +47625,18 @@ function useEventRegistrationWizard(options) {
|
|
|
47315
47625
|
}),
|
|
47316
47626
|
[selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
|
|
47317
47627
|
);
|
|
47628
|
+
const selectedSlidingAmount = useMemo12(
|
|
47629
|
+
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
47630
|
+
[selectedSlidingAmountInput]
|
|
47631
|
+
);
|
|
47632
|
+
const selectedEventSlidingScale = useMemo12(
|
|
47633
|
+
() => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
|
|
47634
|
+
[selectedEvent, preSelectedEvent]
|
|
47635
|
+
);
|
|
47636
|
+
const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
|
|
47637
|
+
slidingScale: selectedEventSlidingScale,
|
|
47638
|
+
selectedAmount: selectedSlidingAmount
|
|
47639
|
+
});
|
|
47318
47640
|
const ticketTypeSelectionRequired = useMemo12(() => {
|
|
47319
47641
|
const event = selectedEvent ?? preSelectedEvent;
|
|
47320
47642
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
@@ -47383,12 +47705,24 @@ function useEventRegistrationWizard(options) {
|
|
|
47383
47705
|
setGuestSectionShake(false);
|
|
47384
47706
|
};
|
|
47385
47707
|
const eventRequiresPayment = useMemo12(
|
|
47386
|
-
() =>
|
|
47708
|
+
() => {
|
|
47709
|
+
if (selectedEventSlidingScale) {
|
|
47710
|
+
return (selectedSlidingAmount ?? 0) > 0;
|
|
47711
|
+
}
|
|
47712
|
+
return resolveEventRequiresPayment({
|
|
47713
|
+
eligibility,
|
|
47714
|
+
selectedTicketType,
|
|
47715
|
+
event: selectedEvent ?? preSelectedEvent
|
|
47716
|
+
});
|
|
47717
|
+
},
|
|
47718
|
+
[
|
|
47387
47719
|
eligibility,
|
|
47388
47720
|
selectedTicketType,
|
|
47389
|
-
|
|
47390
|
-
|
|
47391
|
-
|
|
47721
|
+
selectedEvent,
|
|
47722
|
+
preSelectedEvent,
|
|
47723
|
+
selectedEventSlidingScale,
|
|
47724
|
+
selectedSlidingAmount
|
|
47725
|
+
]
|
|
47392
47726
|
);
|
|
47393
47727
|
const handleDetailsComplete = async () => {
|
|
47394
47728
|
if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
|
|
@@ -47397,6 +47731,11 @@ function useEventRegistrationWizard(options) {
|
|
|
47397
47731
|
setStep("error");
|
|
47398
47732
|
return { ok: false, reason: "blocked", message };
|
|
47399
47733
|
}
|
|
47734
|
+
if (slidingScaleSelectionMessage) {
|
|
47735
|
+
setErrorMessage(slidingScaleSelectionMessage);
|
|
47736
|
+
setStep("error");
|
|
47737
|
+
return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
|
|
47738
|
+
}
|
|
47400
47739
|
if (!validateForm()) {
|
|
47401
47740
|
setGuestSectionShake(true);
|
|
47402
47741
|
return {
|
|
@@ -47481,9 +47820,18 @@ function useEventRegistrationWizard(options) {
|
|
|
47481
47820
|
const discountSubtotalCents = useMemo12(() => {
|
|
47482
47821
|
if (discountContext?.type !== "event") return void 0;
|
|
47483
47822
|
const event = selectedEvent ?? preSelectedEvent;
|
|
47484
|
-
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
47823
|
+
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
47485
47824
|
return Math.max(0, eventPriceCents * ticketsCount);
|
|
47486
|
-
}, [
|
|
47825
|
+
}, [
|
|
47826
|
+
discountContext,
|
|
47827
|
+
selectedTicketType,
|
|
47828
|
+
eligibility,
|
|
47829
|
+
selectedEvent,
|
|
47830
|
+
preSelectedEvent,
|
|
47831
|
+
selectedEventSlidingScale,
|
|
47832
|
+
selectedSlidingAmount,
|
|
47833
|
+
ticketsCount
|
|
47834
|
+
]);
|
|
47487
47835
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
47488
47836
|
const selectionMethod = paymentSelection.method;
|
|
47489
47837
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -47492,6 +47840,7 @@ function useEventRegistrationWizard(options) {
|
|
|
47492
47840
|
registrationTarget,
|
|
47493
47841
|
selectedAttendanceMode,
|
|
47494
47842
|
selectedTicketTypeId,
|
|
47843
|
+
selectedSlidingAmount,
|
|
47495
47844
|
ticketsCount,
|
|
47496
47845
|
formData,
|
|
47497
47846
|
altchaSolution,
|
|
@@ -47506,6 +47855,10 @@ function useEventRegistrationWizard(options) {
|
|
|
47506
47855
|
});
|
|
47507
47856
|
const handleEventSelect = (event) => {
|
|
47508
47857
|
setSelectedEvent(event);
|
|
47858
|
+
const slidingScale = getSlidingScaleForEvent(event);
|
|
47859
|
+
setSelectedSlidingAmountInput(
|
|
47860
|
+
slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
47861
|
+
);
|
|
47509
47862
|
setSelectedAttendanceMode(
|
|
47510
47863
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
47511
47864
|
);
|
|
@@ -47515,6 +47868,7 @@ function useEventRegistrationWizard(options) {
|
|
|
47515
47868
|
const handleRetry = () => {
|
|
47516
47869
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
47517
47870
|
setSelectedTicketTypeId(null);
|
|
47871
|
+
setSelectedSlidingAmountInput("");
|
|
47518
47872
|
setSelectedAttendanceMode(
|
|
47519
47873
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
47520
47874
|
);
|
|
@@ -47551,6 +47905,11 @@ function useEventRegistrationWizard(options) {
|
|
|
47551
47905
|
setSelectedAttendanceMode,
|
|
47552
47906
|
selectedTicketTypeId,
|
|
47553
47907
|
setSelectedTicketTypeId,
|
|
47908
|
+
selectedSlidingAmountInput,
|
|
47909
|
+
setSelectedSlidingAmountInput,
|
|
47910
|
+
selectedSlidingAmount,
|
|
47911
|
+
selectedEventSlidingScale,
|
|
47912
|
+
slidingScaleSelectionMessage,
|
|
47554
47913
|
selectedTicketType,
|
|
47555
47914
|
visibleTicketTypes,
|
|
47556
47915
|
ticketTypeSelectionRequired,
|
|
@@ -51869,6 +52228,44 @@ function CoursePricingSelector({
|
|
|
51869
52228
|
)
|
|
51870
52229
|
] });
|
|
51871
52230
|
}
|
|
52231
|
+
function CourseSlidingScaleInput({
|
|
52232
|
+
pricing,
|
|
52233
|
+
value,
|
|
52234
|
+
onChange
|
|
52235
|
+
}) {
|
|
52236
|
+
const slidingScale = pricing.slidingScale;
|
|
52237
|
+
if (!slidingScale) {
|
|
52238
|
+
return null;
|
|
52239
|
+
}
|
|
52240
|
+
const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
|
|
52241
|
+
const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
|
|
52242
|
+
const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
|
|
52243
|
+
return /* @__PURE__ */ jsxs97("div", { className: "cr-form__field", children: [
|
|
52244
|
+
/* @__PURE__ */ jsx140("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
|
|
52245
|
+
/* @__PURE__ */ jsx140(
|
|
52246
|
+
"input",
|
|
52247
|
+
{
|
|
52248
|
+
id: "cr-sliding-amount",
|
|
52249
|
+
type: "number",
|
|
52250
|
+
min: slidingScale.minAmount / 100,
|
|
52251
|
+
max: slidingScale.maxAmount / 100,
|
|
52252
|
+
step: "0.01",
|
|
52253
|
+
inputMode: "decimal",
|
|
52254
|
+
className: "cr-form__input",
|
|
52255
|
+
value,
|
|
52256
|
+
onChange: (event) => onChange(event.target.value)
|
|
52257
|
+
}
|
|
52258
|
+
),
|
|
52259
|
+
/* @__PURE__ */ jsxs97("p", { className: "cr-text cr-text--muted", children: [
|
|
52260
|
+
"Choose between ",
|
|
52261
|
+
minLabel,
|
|
52262
|
+
" and ",
|
|
52263
|
+
maxLabel,
|
|
52264
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
52265
|
+
"."
|
|
52266
|
+
] })
|
|
52267
|
+
] });
|
|
52268
|
+
}
|
|
51872
52269
|
function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
|
|
51873
52270
|
const nameErrorId = "cr-name-error";
|
|
51874
52271
|
const emailErrorId = "cr-email-error";
|
|
@@ -51964,6 +52361,17 @@ var init_components2 = __esm({
|
|
|
51964
52361
|
|
|
51965
52362
|
// ../blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.ts
|
|
51966
52363
|
import { useEffect as useEffect27, useMemo as useMemo21, useState as useState20 } from "react";
|
|
52364
|
+
function parseCurrencyInputToCents2(value) {
|
|
52365
|
+
const trimmed = value.trim();
|
|
52366
|
+
if (!trimmed) return null;
|
|
52367
|
+
const amount = Number(trimmed);
|
|
52368
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
52369
|
+
return Math.round(amount * 100);
|
|
52370
|
+
}
|
|
52371
|
+
function formatCentsAsCurrencyInput2(amount) {
|
|
52372
|
+
const major = amount / 100;
|
|
52373
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
52374
|
+
}
|
|
51967
52375
|
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
51968
52376
|
if (!course || portalAuthState === "checking") return false;
|
|
51969
52377
|
if (hasWaitlistClaimToken) return false;
|
|
@@ -51981,12 +52389,27 @@ function getSessionIdFromUrl() {
|
|
|
51981
52389
|
}
|
|
51982
52390
|
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
51983
52391
|
if (pricing?.requiresSelection && !pricing.selectedOption) {
|
|
52392
|
+
if (pricing.slidingScale) {
|
|
52393
|
+
return "Choose an amount to continue.";
|
|
52394
|
+
}
|
|
51984
52395
|
return "Choose a pricing option to continue.";
|
|
51985
52396
|
}
|
|
52397
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
|
|
52398
|
+
return "Choose an amount within the sliding scale.";
|
|
52399
|
+
}
|
|
52400
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
|
|
52401
|
+
return "Choose an amount within the sliding scale.";
|
|
52402
|
+
}
|
|
51986
52403
|
return null;
|
|
51987
52404
|
}
|
|
51988
52405
|
function buildCoursePricingOptionPayload(pricing) {
|
|
51989
|
-
|
|
52406
|
+
if (pricing?.selectedOption) {
|
|
52407
|
+
return { pricingOptionId: pricing.selectedOption.id };
|
|
52408
|
+
}
|
|
52409
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
|
|
52410
|
+
return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
52411
|
+
}
|
|
52412
|
+
return {};
|
|
51990
52413
|
}
|
|
51991
52414
|
function resolveHasCoursePayment(pricing) {
|
|
51992
52415
|
if (!pricing) {
|
|
@@ -52027,6 +52450,7 @@ function useCourseRegistrationWizard(props2) {
|
|
|
52027
52450
|
scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
|
|
52028
52451
|
);
|
|
52029
52452
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState20(null);
|
|
52453
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState20("");
|
|
52030
52454
|
const [formData, setFormData] = useState20({
|
|
52031
52455
|
name: "",
|
|
52032
52456
|
email: "",
|
|
@@ -52048,8 +52472,12 @@ function useCourseRegistrationWizard(props2) {
|
|
|
52048
52472
|
const [bookingMode, setBookingMode] = useState20(null);
|
|
52049
52473
|
const waitlistClaim = useWaitlistClaim();
|
|
52050
52474
|
const selectedCoursePricing = useMemo21(
|
|
52051
|
-
() => selectedCourse ? resolveCoursePricingState(
|
|
52052
|
-
|
|
52475
|
+
() => selectedCourse ? resolveCoursePricingState(
|
|
52476
|
+
selectedCourse,
|
|
52477
|
+
selectedPricingOptionId,
|
|
52478
|
+
parseCurrencyInputToCents2(selectedSlidingAmountInput)
|
|
52479
|
+
) : null,
|
|
52480
|
+
[selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
|
|
52053
52481
|
);
|
|
52054
52482
|
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
|
|
52055
52483
|
selectedCoursePricing
|
|
@@ -52122,9 +52550,13 @@ function useCourseRegistrationWizard(props2) {
|
|
|
52122
52550
|
useEffect27(() => {
|
|
52123
52551
|
if (!selectedCourse) {
|
|
52124
52552
|
setSelectedPricingOptionId(null);
|
|
52553
|
+
setSelectedSlidingAmountInput("");
|
|
52125
52554
|
return;
|
|
52126
52555
|
}
|
|
52127
52556
|
const defaultPricing = resolveCoursePricingState(selectedCourse, null);
|
|
52557
|
+
setSelectedSlidingAmountInput(
|
|
52558
|
+
defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
|
|
52559
|
+
);
|
|
52128
52560
|
setSelectedPricingOptionId((previous) => {
|
|
52129
52561
|
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
|
|
52130
52562
|
return previous;
|
|
@@ -52499,6 +52931,8 @@ function useCourseRegistrationWizard(props2) {
|
|
|
52499
52931
|
selectedCourse,
|
|
52500
52932
|
selectedPricingOptionId,
|
|
52501
52933
|
setSelectedPricingOptionId,
|
|
52934
|
+
selectedSlidingAmountInput,
|
|
52935
|
+
setSelectedSlidingAmountInput,
|
|
52502
52936
|
selectedCoursePricing,
|
|
52503
52937
|
setSelectedCourse,
|
|
52504
52938
|
formData,
|
|
@@ -52564,6 +52998,19 @@ var init_useCourseRegistrationWizard = __esm({
|
|
|
52564
52998
|
|
|
52565
52999
|
// ../blocks/src/system/runtime/nodes/course-registration/CourseRegistrationWizard.tsx
|
|
52566
53000
|
import { Fragment as Fragment31, jsx as jsx141, jsxs as jsxs98 } from "react/jsx-runtime";
|
|
53001
|
+
function getCourseSlidingScaleMessage(pricing) {
|
|
53002
|
+
if (!pricing.slidingScale) {
|
|
53003
|
+
return null;
|
|
53004
|
+
}
|
|
53005
|
+
const selectedAmount = pricing.selectedSlidingAmount;
|
|
53006
|
+
if (selectedAmount === null) {
|
|
53007
|
+
return "Choose an amount to continue.";
|
|
53008
|
+
}
|
|
53009
|
+
if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
|
|
53010
|
+
return "Choose an amount within the sliding scale.";
|
|
53011
|
+
}
|
|
53012
|
+
return null;
|
|
53013
|
+
}
|
|
52567
53014
|
function CourseRegistrationWizard(props2) {
|
|
52568
53015
|
const {
|
|
52569
53016
|
showSessions = true,
|
|
@@ -52585,6 +53032,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
52585
53032
|
selectedCourse,
|
|
52586
53033
|
selectedPricingOptionId,
|
|
52587
53034
|
setSelectedPricingOptionId,
|
|
53035
|
+
selectedSlidingAmountInput,
|
|
53036
|
+
setSelectedSlidingAmountInput,
|
|
52588
53037
|
selectedCoursePricing,
|
|
52589
53038
|
formData,
|
|
52590
53039
|
setFormData,
|
|
@@ -52659,7 +53108,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
52659
53108
|
const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
|
|
52660
53109
|
const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
|
|
52661
53110
|
const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
|
|
52662
|
-
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
|
|
53111
|
+
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
|
|
53112
|
+
const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
|
|
52663
53113
|
const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
|
|
52664
53114
|
const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
|
|
52665
53115
|
course: selectedCourse,
|
|
@@ -52752,6 +53202,14 @@ function CourseRegistrationWizard(props2) {
|
|
|
52752
53202
|
onSelect: setSelectedPricingOptionId
|
|
52753
53203
|
}
|
|
52754
53204
|
),
|
|
53205
|
+
/* @__PURE__ */ jsx141(
|
|
53206
|
+
CourseSlidingScaleInput,
|
|
53207
|
+
{
|
|
53208
|
+
pricing: selectedCourseWithPricing.pricing,
|
|
53209
|
+
value: selectedSlidingAmountInput,
|
|
53210
|
+
onChange: setSelectedSlidingAmountInput
|
|
53211
|
+
}
|
|
53212
|
+
),
|
|
52755
53213
|
showSpamProtection && /* @__PURE__ */ jsx141("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx141(
|
|
52756
53214
|
AltchaWidget,
|
|
52757
53215
|
{
|
|
@@ -52789,7 +53247,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
52789
53247
|
{
|
|
52790
53248
|
type: "submit",
|
|
52791
53249
|
className: buttonClass,
|
|
52792
|
-
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
|
|
53250
|
+
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
|
|
52793
53251
|
children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
|
|
52794
53252
|
}
|
|
52795
53253
|
)
|
|
@@ -52799,6 +53257,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
52799
53257
|
),
|
|
52800
53258
|
courseSoldOut && /* @__PURE__ */ jsx141("p", { className: "cr-text cr-text--muted", children: "This course is fully booked and there is no waitlist available right now." }),
|
|
52801
53259
|
pricingSelectionMissing && /* @__PURE__ */ jsx141("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
|
|
53260
|
+
slidingScaleMessage && /* @__PURE__ */ jsx141("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
|
|
52802
53261
|
pricingUnavailable && /* @__PURE__ */ jsx141("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
|
|
52803
53262
|
eligibilityError && /* @__PURE__ */ jsx141("p", { className: "cr-text cr-text--error", children: eligibilityError })
|
|
52804
53263
|
] })
|
|
@@ -62952,6 +63411,21 @@ function fieldPlanToZod(plan, options = {}) {
|
|
|
62952
63411
|
}
|
|
62953
63412
|
});
|
|
62954
63413
|
}
|
|
63414
|
+
function fieldPresenceForPlan(plan) {
|
|
63415
|
+
return plan.required ? { kind: "required" } : { kind: "optional" };
|
|
63416
|
+
}
|
|
63417
|
+
function fieldPlanToObjectPropertyZod(plan, options = {}) {
|
|
63418
|
+
const schema = fieldPlanToZod(plan, options);
|
|
63419
|
+
const presence = fieldPresenceForPlan(plan);
|
|
63420
|
+
switch (presence.kind) {
|
|
63421
|
+
case "required":
|
|
63422
|
+
return schema;
|
|
63423
|
+
case "optional":
|
|
63424
|
+
return schema.optional();
|
|
63425
|
+
default:
|
|
63426
|
+
return assertNever4(presence);
|
|
63427
|
+
}
|
|
63428
|
+
}
|
|
62955
63429
|
function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
|
|
62956
63430
|
const message = fieldIssueToMessage(validationIssue);
|
|
62957
63431
|
const path = relativeZodIssuePath(validationIssue.path, rootPath);
|
|
@@ -63164,7 +63638,7 @@ function createManifestValidator(manifestOrFields, options = {}) {
|
|
|
63164
63638
|
function deriveContentZodFromPlans(plans, options) {
|
|
63165
63639
|
const shape = {};
|
|
63166
63640
|
for (const plan of plans) {
|
|
63167
|
-
shape[plan.fieldId] =
|
|
63641
|
+
shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
|
|
63168
63642
|
}
|
|
63169
63643
|
return z7.object(shape).catchall(z7.unknown()).passthrough();
|
|
63170
63644
|
}
|
|
@@ -97086,6 +97560,7 @@ var CANONICAL_REFUND_CONFLICT_CODES = [
|
|
|
97086
97560
|
];
|
|
97087
97561
|
var CANONICAL_REFUND_PLANNER_ERROR_CODES = [
|
|
97088
97562
|
...CANONICAL_REFUND_CONFLICT_CODES,
|
|
97563
|
+
"invalid_amount",
|
|
97089
97564
|
"amount_exceeds_remaining",
|
|
97090
97565
|
"pass_revoke_requires_full_refund",
|
|
97091
97566
|
"refund_failed"
|
|
@@ -97112,6 +97587,7 @@ var CUSTOMER_MEMBERSHIP_PAYMENT_REFUND_FAILED_CODES = [
|
|
|
97112
97587
|
// ../api/src/bookingRefundOutcomes.ts
|
|
97113
97588
|
var STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
|
|
97114
97589
|
"missing_amount",
|
|
97590
|
+
"invalid_amount",
|
|
97115
97591
|
"amount_exceeds_remaining",
|
|
97116
97592
|
"credit_refunds_disabled",
|
|
97117
97593
|
"missing_credit_customer",
|
|
@@ -97126,6 +97602,7 @@ var EVENT_ATTENDEE_REFUND_INVALID_CODES = [
|
|
|
97126
97602
|
var MANAGED_PRODUCT_REFUND_INVALID_CODES = [
|
|
97127
97603
|
"credit_refunds_disabled",
|
|
97128
97604
|
"not_refundable",
|
|
97605
|
+
"invalid_amount",
|
|
97129
97606
|
"amount_exceeds_remaining"
|
|
97130
97607
|
];
|
|
97131
97608
|
var CUSTOMER_PASS_REFUND_INVALID_CODES = [
|
|
@@ -99098,7 +99575,7 @@ var SimpleCache = class {
|
|
|
99098
99575
|
};
|
|
99099
99576
|
|
|
99100
99577
|
// src/version.ts
|
|
99101
|
-
var SDK_VERSION = "0.
|
|
99578
|
+
var SDK_VERSION = "0.92.0";
|
|
99102
99579
|
|
|
99103
99580
|
// src/client/error.ts
|
|
99104
99581
|
var RiverbankApiError = class _RiverbankApiError extends Error {
|