@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
|
@@ -129,6 +129,8 @@ function expectParsedBrandedId(result) {
|
|
|
129
129
|
}
|
|
130
130
|
var unsafeAsSiteId = (id) => id;
|
|
131
131
|
var unsafeAsMediaAssetId = (id) => id;
|
|
132
|
+
var unsafeAsStoragePath = (value) => value;
|
|
133
|
+
var unsafeAsPositiveByteCount = (value) => value;
|
|
132
134
|
var unsafeAsFormId = (id) => id;
|
|
133
135
|
var unsafeAsPassId = (id) => id;
|
|
134
136
|
var unsafeAsCustomerPassId = (id) => id;
|
|
@@ -207,6 +209,7 @@ function publicEventPricingType(pricing) {
|
|
|
207
209
|
return "free";
|
|
208
210
|
case "single_paid":
|
|
209
211
|
case "ticket_types":
|
|
212
|
+
case "sliding_scale":
|
|
210
213
|
case "course":
|
|
211
214
|
return isFreePublicEventPriceDisplay(pricing.display) ? "free" : "paid";
|
|
212
215
|
case "external":
|
|
@@ -219,6 +222,7 @@ function publicEventPricingCurrency(pricing) {
|
|
|
219
222
|
case "free_registration":
|
|
220
223
|
case "single_paid":
|
|
221
224
|
case "ticket_types":
|
|
225
|
+
case "sliding_scale":
|
|
222
226
|
return pricing.currency;
|
|
223
227
|
case "course":
|
|
224
228
|
return pricing.display.display.currency;
|
|
@@ -236,6 +240,8 @@ function publicEventPricingMode(pricing) {
|
|
|
236
240
|
return "single";
|
|
237
241
|
case "ticket_types":
|
|
238
242
|
return "ticket_types";
|
|
243
|
+
case "sliding_scale":
|
|
244
|
+
return "sliding_scale";
|
|
239
245
|
case "drop_in":
|
|
240
246
|
case "course":
|
|
241
247
|
case "external":
|
|
@@ -269,6 +275,8 @@ function formatCoursePriceDisplayLabel(display, options) {
|
|
|
269
275
|
return `Course (${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
270
276
|
case "from":
|
|
271
277
|
return `Course (From ${formatCurrencyAmount(display.amount, display.currency, options)})`;
|
|
278
|
+
case "range":
|
|
279
|
+
return `Course (${formatCurrencyAmount(display.minAmount, display.currency, options)} - ${formatCurrencyAmount(display.maxAmount, display.currency, options)})`;
|
|
272
280
|
default:
|
|
273
281
|
return assertNever(display);
|
|
274
282
|
}
|
|
@@ -30396,6 +30404,18 @@ var SVG_MIME_TYPE = "image/svg+xml";
|
|
|
30396
30404
|
function isSvgMimeType(mimeType) {
|
|
30397
30405
|
return mimeType === SVG_MIME_TYPE;
|
|
30398
30406
|
}
|
|
30407
|
+
|
|
30408
|
+
// ../media-core/src/fileSafety.ts
|
|
30409
|
+
var CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
30410
|
+
function containsUnsafePathSegmentCharacter(value) {
|
|
30411
|
+
return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
|
|
30412
|
+
}
|
|
30413
|
+
function isReservedPathSegment(value) {
|
|
30414
|
+
return value === "." || value === "..";
|
|
30415
|
+
}
|
|
30416
|
+
function isUnsafePathSegment(segment) {
|
|
30417
|
+
return segment.trim().length === 0 || segment !== segment.trim() || isReservedPathSegment(segment) || containsUnsafePathSegmentCharacter(segment);
|
|
30418
|
+
}
|
|
30399
30419
|
function classifyKnownMimeType(mimeType) {
|
|
30400
30420
|
const normalized = normalizeMimeType(mimeType);
|
|
30401
30421
|
switch (normalized) {
|
|
@@ -30462,6 +30482,15 @@ function classifyKnownMimeType(mimeType) {
|
|
|
30462
30482
|
function normalizeMimeType(mimeType) {
|
|
30463
30483
|
return (mimeType ?? "").split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
30464
30484
|
}
|
|
30485
|
+
function parseStoragePath(value) {
|
|
30486
|
+
return joinStoragePathSegments(value.split("/"));
|
|
30487
|
+
}
|
|
30488
|
+
function joinStoragePathSegments(segments) {
|
|
30489
|
+
if (segments.some(isUnsafePathSegment)) {
|
|
30490
|
+
return err("unsafe-path-segment");
|
|
30491
|
+
}
|
|
30492
|
+
return ok(unsafeAsStoragePath(segments.join("/")));
|
|
30493
|
+
}
|
|
30465
30494
|
|
|
30466
30495
|
// ../media-core/src/typeGuards.ts
|
|
30467
30496
|
function isRecord(value) {
|
|
@@ -30473,11 +30502,20 @@ function asRecord(value) {
|
|
|
30473
30502
|
|
|
30474
30503
|
// ../media-core/src/videoPrep.ts
|
|
30475
30504
|
var VIDEO_PREP_LIMITS = {
|
|
30476
|
-
maxRawByteCount: 500 * 1024 * 1024,
|
|
30477
|
-
inlineContentMaxDurationSeconds: 60,
|
|
30478
|
-
backgroundVideoMaxDurationSeconds: 30,
|
|
30505
|
+
maxRawByteCount: unsafeAsPositiveByteCount(500 * 1024 * 1024),
|
|
30506
|
+
inlineContentMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(60),
|
|
30507
|
+
backgroundVideoMaxDurationSeconds: unsafeAsPositiveVideoDurationSeconds(30),
|
|
30479
30508
|
targetMaxDimensionPixels: 1080
|
|
30480
30509
|
};
|
|
30510
|
+
function unsafeAsPositiveVideoDurationSeconds(value) {
|
|
30511
|
+
return value;
|
|
30512
|
+
}
|
|
30513
|
+
function asPositiveVideoDurationSeconds(value) {
|
|
30514
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
30515
|
+
return err("not-positive-video-duration-seconds");
|
|
30516
|
+
}
|
|
30517
|
+
return ok(unsafeAsPositiveVideoDurationSeconds(value));
|
|
30518
|
+
}
|
|
30481
30519
|
function deriveVideoPrepPolicy(intent) {
|
|
30482
30520
|
switch (intent.tag) {
|
|
30483
30521
|
case "files-and-media":
|
|
@@ -30528,14 +30566,16 @@ function evaluateVideoSlotAssetPolicy(asset, policy) {
|
|
|
30528
30566
|
if (!isVideoMimeType(asset.mimeType)) {
|
|
30529
30567
|
return { tag: "not-video" };
|
|
30530
30568
|
}
|
|
30531
|
-
const durationSeconds =
|
|
30532
|
-
|
|
30569
|
+
const durationSeconds = asPositiveVideoDurationSeconds(
|
|
30570
|
+
asset.durationSeconds ?? Number.NaN
|
|
30571
|
+
);
|
|
30572
|
+
if (!durationSeconds.ok) {
|
|
30533
30573
|
return { tag: "duration-unknown", maxSeconds: policy.maxDurationSeconds };
|
|
30534
30574
|
}
|
|
30535
|
-
if (durationSeconds > policy.maxDurationSeconds) {
|
|
30575
|
+
if (durationSeconds.value > policy.maxDurationSeconds) {
|
|
30536
30576
|
return {
|
|
30537
30577
|
tag: "duration-too-long",
|
|
30538
|
-
actualSeconds: durationSeconds,
|
|
30578
|
+
actualSeconds: durationSeconds.value,
|
|
30539
30579
|
maxSeconds: policy.maxDurationSeconds
|
|
30540
30580
|
};
|
|
30541
30581
|
}
|
|
@@ -30591,10 +30631,10 @@ var RELATIVE_STORAGE_PATH_PREFIXES = [
|
|
|
30591
30631
|
"imports/"
|
|
30592
30632
|
];
|
|
30593
30633
|
function isRelativeDirectImageStoragePath(storagePath) {
|
|
30594
|
-
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix));
|
|
30634
|
+
return RELATIVE_STORAGE_PATH_PREFIXES.some((prefix) => storagePath.startsWith(prefix)) && parseStoragePath(storagePath).ok;
|
|
30595
30635
|
}
|
|
30596
30636
|
function isSiteScopedDirectImageStoragePath(storagePath) {
|
|
30597
|
-
return storagePath.startsWith("sites/");
|
|
30637
|
+
return storagePath.startsWith("sites/") && parseStoragePath(storagePath).ok;
|
|
30598
30638
|
}
|
|
30599
30639
|
function encodeStoragePath(storagePath) {
|
|
30600
30640
|
return storagePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
@@ -33403,6 +33443,21 @@ function fieldPlanToZod(plan, options = {}) {
|
|
|
33403
33443
|
}
|
|
33404
33444
|
});
|
|
33405
33445
|
}
|
|
33446
|
+
function fieldPresenceForPlan(plan) {
|
|
33447
|
+
return plan.required ? { kind: "required" } : { kind: "optional" };
|
|
33448
|
+
}
|
|
33449
|
+
function fieldPlanToObjectPropertyZod(plan, options = {}) {
|
|
33450
|
+
const schema = fieldPlanToZod(plan, options);
|
|
33451
|
+
const presence = fieldPresenceForPlan(plan);
|
|
33452
|
+
switch (presence.kind) {
|
|
33453
|
+
case "required":
|
|
33454
|
+
return schema;
|
|
33455
|
+
case "optional":
|
|
33456
|
+
return schema.optional();
|
|
33457
|
+
default:
|
|
33458
|
+
return assertNever4(presence);
|
|
33459
|
+
}
|
|
33460
|
+
}
|
|
33406
33461
|
function addFieldIssueToZodContext(zodCtx, validationIssue, rootPath) {
|
|
33407
33462
|
const message2 = fieldIssueToMessage(validationIssue);
|
|
33408
33463
|
const path = relativeZodIssuePath(validationIssue.path, rootPath);
|
|
@@ -33669,7 +33724,7 @@ function createManifestValidator(manifestOrFields, options = {}) {
|
|
|
33669
33724
|
function deriveContentZodFromPlans(plans, options) {
|
|
33670
33725
|
const shape = {};
|
|
33671
33726
|
for (const plan of plans) {
|
|
33672
|
-
shape[plan.fieldId] =
|
|
33727
|
+
shape[plan.fieldId] = fieldPlanToObjectPropertyZod(plan, options);
|
|
33673
33728
|
}
|
|
33674
33729
|
return z.object(shape).catchall(z.unknown()).passthrough();
|
|
33675
33730
|
}
|
|
@@ -60130,9 +60185,12 @@ var coursePricingOptionSchema = z.object({
|
|
|
60130
60185
|
});
|
|
60131
60186
|
var coursePricingSchema = z.object({
|
|
60132
60187
|
bookingRequirement: z.enum(["none", "required"]),
|
|
60133
|
-
pricingStrategy: z.enum(["free", "single", "tiered"]),
|
|
60188
|
+
pricingStrategy: z.enum(["free", "single", "tiered", "sliding_scale"]),
|
|
60134
60189
|
currency: z.string(),
|
|
60135
60190
|
singlePriceAmount: z.number().nullable(),
|
|
60191
|
+
slidingMinAmount: z.number().nullable().optional(),
|
|
60192
|
+
slidingMaxAmount: z.number().nullable().optional(),
|
|
60193
|
+
slidingSuggestedAmount: z.number().nullable().optional(),
|
|
60136
60194
|
paymentTerms: blockBookingPaymentTermsSchema,
|
|
60137
60195
|
options: z.array(coursePricingOptionSchema)
|
|
60138
60196
|
});
|
|
@@ -60286,6 +60344,19 @@ var publicEventPricingSchema = z.discriminatedUnion("kind", [
|
|
|
60286
60344
|
ticketTypes: z.array(publicEventTicketTypeSchema),
|
|
60287
60345
|
display: publicEventTicketTypePriceDisplaySchema
|
|
60288
60346
|
}),
|
|
60347
|
+
z.object({
|
|
60348
|
+
kind: z.literal("sliding_scale"),
|
|
60349
|
+
minAmount: z.number(),
|
|
60350
|
+
maxAmount: z.number(),
|
|
60351
|
+
suggestedAmount: z.number().nullable(),
|
|
60352
|
+
currency: z.string(),
|
|
60353
|
+
display: z.object({
|
|
60354
|
+
kind: z.literal("range"),
|
|
60355
|
+
minAmount: z.number(),
|
|
60356
|
+
maxAmount: z.number(),
|
|
60357
|
+
currency: z.string()
|
|
60358
|
+
})
|
|
60359
|
+
}),
|
|
60289
60360
|
z.object({
|
|
60290
60361
|
kind: z.literal("course"),
|
|
60291
60362
|
display: z.object({ kind: z.literal("course"), display: publicCoursePriceDisplaySchema })
|
|
@@ -60694,7 +60765,7 @@ function isRecord7(value) {
|
|
|
60694
60765
|
}
|
|
60695
60766
|
function isPublicEventPricing(value) {
|
|
60696
60767
|
if (!isRecord7(value) || typeof value.kind !== "string") return false;
|
|
60697
|
-
return value.kind === "drop_in" || value.kind === "free_registration" || value.kind === "single_paid" || value.kind === "ticket_types" || value.kind === "course" || value.kind === "external";
|
|
60768
|
+
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";
|
|
60698
60769
|
}
|
|
60699
60770
|
function isPublicEventTicketType(value) {
|
|
60700
60771
|
return isRecord7(value) && typeof value.id === "string";
|
|
@@ -61335,7 +61406,9 @@ function getSelectableCoursePricingOptionsForNow(course, now) {
|
|
|
61335
61406
|
return left.name.localeCompare(right.name);
|
|
61336
61407
|
});
|
|
61337
61408
|
}
|
|
61338
|
-
function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {}) {
|
|
61409
|
+
function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
|
|
61410
|
+
const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
|
|
61411
|
+
const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
|
|
61339
61412
|
const currency = course.pricing?.currency ?? course.currency;
|
|
61340
61413
|
if (!course.pricing) {
|
|
61341
61414
|
const legacyAmount = course.priceCents ?? 0;
|
|
@@ -61345,6 +61418,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
61345
61418
|
selectableOptions: [],
|
|
61346
61419
|
requiresSelection: false,
|
|
61347
61420
|
selectedOption: null,
|
|
61421
|
+
slidingScale: null,
|
|
61422
|
+
selectedSlidingAmount: null,
|
|
61348
61423
|
selectedPriceAmount: legacyAmount,
|
|
61349
61424
|
selectedRequiresPayment: legacyAmount > 0,
|
|
61350
61425
|
hasPaidSelection: legacyAmount > 0,
|
|
@@ -61359,6 +61434,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
61359
61434
|
selectableOptions: [],
|
|
61360
61435
|
requiresSelection: false,
|
|
61361
61436
|
selectedOption: null,
|
|
61437
|
+
slidingScale: null,
|
|
61438
|
+
selectedSlidingAmount: null,
|
|
61362
61439
|
selectedPriceAmount: 0,
|
|
61363
61440
|
selectedRequiresPayment: false,
|
|
61364
61441
|
hasPaidSelection: false,
|
|
@@ -61372,6 +61449,8 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
61372
61449
|
selectableOptions: [],
|
|
61373
61450
|
requiresSelection: false,
|
|
61374
61451
|
selectedOption: null,
|
|
61452
|
+
slidingScale: null,
|
|
61453
|
+
selectedSlidingAmount: null,
|
|
61375
61454
|
selectedPriceAmount: amount,
|
|
61376
61455
|
selectedRequiresPayment: amount > 0,
|
|
61377
61456
|
hasPaidSelection: amount > 0,
|
|
@@ -61381,7 +61460,7 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
61381
61460
|
case "tiered": {
|
|
61382
61461
|
const selectableOptions = getSelectableCoursePricingOptionsForNow(
|
|
61383
61462
|
course,
|
|
61384
|
-
resolvePlanningDateInput(
|
|
61463
|
+
resolvePlanningDateInput(effectiveNowInput)
|
|
61385
61464
|
);
|
|
61386
61465
|
const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
|
|
61387
61466
|
const lowestAmount = selectableOptions.reduce((lowest, option) => {
|
|
@@ -61397,12 +61476,51 @@ function resolveCoursePricingState(course, selectedPricingOptionId, nowInput = {
|
|
|
61397
61476
|
selectableOptions,
|
|
61398
61477
|
requiresSelection: selectableOptions.length > 1,
|
|
61399
61478
|
selectedOption,
|
|
61479
|
+
slidingScale: null,
|
|
61480
|
+
selectedSlidingAmount: null,
|
|
61400
61481
|
selectedPriceAmount: selectedOption?.priceAmount ?? null,
|
|
61401
61482
|
selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
|
|
61402
61483
|
hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
|
|
61403
61484
|
hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
|
|
61404
61485
|
};
|
|
61405
61486
|
}
|
|
61487
|
+
case "sliding_scale": {
|
|
61488
|
+
const minAmount = course.pricing.slidingMinAmount ?? null;
|
|
61489
|
+
const maxAmount = course.pricing.slidingMaxAmount ?? null;
|
|
61490
|
+
if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) {
|
|
61491
|
+
return {
|
|
61492
|
+
currency,
|
|
61493
|
+
display: { kind: "unavailable", currency },
|
|
61494
|
+
selectableOptions: [],
|
|
61495
|
+
requiresSelection: true,
|
|
61496
|
+
selectedOption: null,
|
|
61497
|
+
slidingScale: null,
|
|
61498
|
+
selectedSlidingAmount: null,
|
|
61499
|
+
selectedPriceAmount: null,
|
|
61500
|
+
selectedRequiresPayment: false,
|
|
61501
|
+
hasPaidSelection: false,
|
|
61502
|
+
hasFreeSelection: false
|
|
61503
|
+
};
|
|
61504
|
+
}
|
|
61505
|
+
const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
|
|
61506
|
+
return {
|
|
61507
|
+
currency,
|
|
61508
|
+
display: { kind: "range", minAmount, maxAmount, currency },
|
|
61509
|
+
selectableOptions: [],
|
|
61510
|
+
requiresSelection: normalizedSelectedAmount === null,
|
|
61511
|
+
selectedOption: null,
|
|
61512
|
+
slidingScale: {
|
|
61513
|
+
minAmount,
|
|
61514
|
+
maxAmount,
|
|
61515
|
+
suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
|
|
61516
|
+
},
|
|
61517
|
+
selectedSlidingAmount: normalizedSelectedAmount,
|
|
61518
|
+
selectedPriceAmount: normalizedSelectedAmount,
|
|
61519
|
+
selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
|
|
61520
|
+
hasPaidSelection: maxAmount > 0,
|
|
61521
|
+
hasFreeSelection: minAmount === 0
|
|
61522
|
+
};
|
|
61523
|
+
}
|
|
61406
61524
|
}
|
|
61407
61525
|
}
|
|
61408
61526
|
function formatCoursePriceDisplay(display, locale) {
|
|
@@ -73711,6 +73829,7 @@ var BOOKING_FORM_DATA_RESERVED_KEY_VALUES = [
|
|
|
73711
73829
|
"selectedDate",
|
|
73712
73830
|
"selectedSlot",
|
|
73713
73831
|
"discountCode",
|
|
73832
|
+
"selectedSlidingAmountInput",
|
|
73714
73833
|
"selectedCollectionOptionKind",
|
|
73715
73834
|
"selectedAppointmentPackageId"
|
|
73716
73835
|
];
|
|
@@ -73994,6 +74113,32 @@ function readOptionalString(value) {
|
|
|
73994
74113
|
function readOptionalNumber(value) {
|
|
73995
74114
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
73996
74115
|
}
|
|
74116
|
+
function getBookingServiceSlidingScale(service) {
|
|
74117
|
+
const pricing = service?.pricing;
|
|
74118
|
+
if (!pricing || pricing.pricingStrategy !== "sliding_scale" || pricing.slidingMinAmount === null || pricing.slidingMinAmount === void 0 || pricing.slidingMaxAmount === null || pricing.slidingMaxAmount === void 0) {
|
|
74119
|
+
return null;
|
|
74120
|
+
}
|
|
74121
|
+
return {
|
|
74122
|
+
minAmount: pricing.slidingMinAmount,
|
|
74123
|
+
maxAmount: pricing.slidingMaxAmount,
|
|
74124
|
+
suggestedAmount: pricing.slidingSuggestedAmount ?? null,
|
|
74125
|
+
currency: pricing.currency
|
|
74126
|
+
};
|
|
74127
|
+
}
|
|
74128
|
+
function parseBookingCurrencyInputToCents(value) {
|
|
74129
|
+
const trimmed = value?.trim() ?? "";
|
|
74130
|
+
if (!trimmed) return null;
|
|
74131
|
+
if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(trimmed)) return null;
|
|
74132
|
+
const parsed = Number(trimmed);
|
|
74133
|
+
if (!Number.isFinite(parsed) || parsed < 0) return null;
|
|
74134
|
+
return Math.round(parsed * 100);
|
|
74135
|
+
}
|
|
74136
|
+
function formatBookingCentsAsCurrencyInput(amount) {
|
|
74137
|
+
return amount % 100 === 0 ? String(amount / 100) : (amount / 100).toFixed(2);
|
|
74138
|
+
}
|
|
74139
|
+
function isBookingServiceSlidingAmountInRange(slidingScale, selectedAmount) {
|
|
74140
|
+
return selectedAmount !== null && selectedAmount >= slidingScale.minAmount && selectedAmount <= slidingScale.maxAmount;
|
|
74141
|
+
}
|
|
73997
74142
|
function readStringArray(value) {
|
|
73998
74143
|
if (!Array.isArray(value)) return void 0;
|
|
73999
74144
|
const strings = value.filter((item) => typeof item === "string");
|
|
@@ -74182,6 +74327,20 @@ function prepareBookingSubmission(input) {
|
|
|
74182
74327
|
};
|
|
74183
74328
|
}
|
|
74184
74329
|
const paymentSelectionMode = getBookingServicePaymentSelectionMode(selectedService);
|
|
74330
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
74331
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
74332
|
+
input.data.selectedSlidingAmountInput
|
|
74333
|
+
);
|
|
74334
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(slidingScale, selectedSlidingAmount)) {
|
|
74335
|
+
return {
|
|
74336
|
+
ok: false,
|
|
74337
|
+
error: {
|
|
74338
|
+
tag: selectedSlidingAmount === null ? "sliding-amount-required" : "sliding-amount-out-of-range",
|
|
74339
|
+
serviceId,
|
|
74340
|
+
serviceTitle: selectedService.title || serviceId
|
|
74341
|
+
}
|
|
74342
|
+
};
|
|
74343
|
+
}
|
|
74185
74344
|
if (paymentSelectionMode === "choice_required" && !toSelectedCollectionOptionKind(input.data.selectedCollectionOptionKind)) {
|
|
74186
74345
|
return {
|
|
74187
74346
|
ok: false,
|
|
@@ -74209,6 +74368,7 @@ function prepareBookingSubmission(input) {
|
|
|
74209
74368
|
...common,
|
|
74210
74369
|
kind: "standard",
|
|
74211
74370
|
...discountCode ? { discountCode } : {},
|
|
74371
|
+
...slidingScale && selectedSlidingAmount !== null ? { selectedSlidingAmount } : {},
|
|
74212
74372
|
...selectedCollectionOptionKind ? { selectedCollectionOptionKind } : {},
|
|
74213
74373
|
altchaSolution: input.altchaSolution ?? null
|
|
74214
74374
|
}
|
|
@@ -74222,6 +74382,10 @@ function formatBookingSubmissionPreparationError(error) {
|
|
|
74222
74382
|
return `Service not found: ${error.serviceId}`;
|
|
74223
74383
|
case "payment-option-required":
|
|
74224
74384
|
return `Please choose how you want to pay for "${error.serviceTitle}".`;
|
|
74385
|
+
case "sliding-amount-required":
|
|
74386
|
+
return `Please choose an amount for "${error.serviceTitle}".`;
|
|
74387
|
+
case "sliding-amount-out-of-range":
|
|
74388
|
+
return `Please choose an amount within the sliding scale for "${error.serviceTitle}".`;
|
|
74225
74389
|
case "payment-option-unsupported":
|
|
74226
74390
|
return `Service "${error.serviceTitle}" has a payment option that is not supported yet.`;
|
|
74227
74391
|
case "service-missing-duration":
|
|
@@ -74318,6 +74482,7 @@ var bookingServiceSchema = z.object({
|
|
|
74318
74482
|
title: z.string(),
|
|
74319
74483
|
description: z.string().nullable().optional().transform((value) => value ?? void 0),
|
|
74320
74484
|
durationMinutes: z.number().optional(),
|
|
74485
|
+
pricing: z.custom().optional(),
|
|
74321
74486
|
priceAmount: z.number().nullable().optional(),
|
|
74322
74487
|
priceCurrency: z.string().nullable().optional(),
|
|
74323
74488
|
paymentTerms: blockBookingPaymentTermsSchema.optional(),
|
|
@@ -126535,6 +126700,7 @@ function createBlockApi(config) {
|
|
|
126535
126700
|
body: {
|
|
126536
126701
|
courseId: data.courseId,
|
|
126537
126702
|
...data.pricingOptionId ? { pricingOptionId: data.pricingOptionId } : {},
|
|
126703
|
+
...data.selectedSlidingAmount !== void 0 ? { selectedSlidingAmount: data.selectedSlidingAmount } : {},
|
|
126538
126704
|
email: data.email,
|
|
126539
126705
|
name: data.name,
|
|
126540
126706
|
phone: data.phone,
|
|
@@ -127477,6 +127643,7 @@ function useBookingSubmission(_siteId) {
|
|
|
127477
127643
|
customFields: data.customFields,
|
|
127478
127644
|
timezone: data.timezone,
|
|
127479
127645
|
discountCode: data.discountCode,
|
|
127646
|
+
selectedSlidingAmount: data.selectedSlidingAmount,
|
|
127480
127647
|
selectedCollectionOptionKind: data.selectedCollectionOptionKind,
|
|
127481
127648
|
altchaSolution: data.altchaSolution ?? null,
|
|
127482
127649
|
successUrl: data.successUrl,
|
|
@@ -127956,6 +128123,9 @@ function createInitialBookingFlowReducerState(input) {
|
|
|
127956
128123
|
fieldValues: collectInitialFieldValues(initialData),
|
|
127957
128124
|
touchedFields: {},
|
|
127958
128125
|
discountCode: toOptionalString(initialData.discountCode) ?? "",
|
|
128126
|
+
selectedSlidingAmountInput: toOptionalString(
|
|
128127
|
+
initialData.selectedSlidingAmountInput
|
|
128128
|
+
) ?? "",
|
|
127959
128129
|
selectedCollectionOptionKind: toSelectedCollectionOptionKind(
|
|
127960
128130
|
initialData.selectedCollectionOptionKind
|
|
127961
128131
|
),
|
|
@@ -128008,6 +128178,7 @@ function bookingFlowReducer(state, event) {
|
|
|
128008
128178
|
selectedDate: void 0,
|
|
128009
128179
|
selectedSlot: null,
|
|
128010
128180
|
selectedAppointmentPackageId: void 0,
|
|
128181
|
+
selectedSlidingAmountInput: "",
|
|
128011
128182
|
selectedCollectionOptionKind: void 0,
|
|
128012
128183
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
128013
128184
|
};
|
|
@@ -128061,6 +128232,13 @@ function bookingFlowReducer(state, event) {
|
|
|
128061
128232
|
selectedAppointmentPackageId: void 0,
|
|
128062
128233
|
validationErrors: clearBookingFormError(state.validationErrors)
|
|
128063
128234
|
};
|
|
128235
|
+
case "sliding-amount-changed":
|
|
128236
|
+
return {
|
|
128237
|
+
...state,
|
|
128238
|
+
selectedSlidingAmountInput: event.value,
|
|
128239
|
+
selectedAppointmentPackageId: void 0,
|
|
128240
|
+
validationErrors: clearBookingFormError(state.validationErrors)
|
|
128241
|
+
};
|
|
128064
128242
|
case "appointment-package-selected":
|
|
128065
128243
|
return {
|
|
128066
128244
|
...state,
|
|
@@ -128163,6 +128341,7 @@ function toBookingFormData(state) {
|
|
|
128163
128341
|
selectedDate: state.selectedDate,
|
|
128164
128342
|
selectedSlot: state.selectedSlot?.startAt,
|
|
128165
128343
|
discountCode: state.discountCode || void 0,
|
|
128344
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput || void 0,
|
|
128166
128345
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
128167
128346
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId
|
|
128168
128347
|
};
|
|
@@ -128180,7 +128359,8 @@ function buildBookingStepResolution(input) {
|
|
|
128180
128359
|
input.form.settings?.serviceIds && input.form.settings.serviceIds.length > 1
|
|
128181
128360
|
);
|
|
128182
128361
|
const selectedService = paymentResolution.service;
|
|
128183
|
-
const
|
|
128362
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
128363
|
+
const needsPayment = Boolean(selectedServiceSlidingScale) || paymentResolution.mode !== "hidden" || Boolean(
|
|
128184
128364
|
input.enableAppointmentPackages && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
128185
128365
|
);
|
|
128186
128366
|
const hasFields = Boolean(input.form.schema?.fields.length);
|
|
@@ -128224,6 +128404,18 @@ function validateBookingStep(input) {
|
|
|
128224
128404
|
services: input.services,
|
|
128225
128405
|
defaultServiceId: input.defaultServiceId
|
|
128226
128406
|
});
|
|
128407
|
+
const slidingScale = getBookingServiceSlidingScale(resolution.service);
|
|
128408
|
+
if (slidingScale && !isBookingServiceSlidingAmountInRange(
|
|
128409
|
+
slidingScale,
|
|
128410
|
+
parseBookingCurrencyInputToCents(input.data.selectedSlidingAmountInput)
|
|
128411
|
+
)) {
|
|
128412
|
+
return {
|
|
128413
|
+
ok: false,
|
|
128414
|
+
errors: createFormBookingValidationError(
|
|
128415
|
+
"Please choose an amount within the sliding scale"
|
|
128416
|
+
)
|
|
128417
|
+
};
|
|
128418
|
+
}
|
|
128227
128419
|
if (resolution.mode === "hidden" || resolution.mode === "disclosure_only") {
|
|
128228
128420
|
return { ok: true };
|
|
128229
128421
|
}
|
|
@@ -128633,11 +128825,27 @@ function useHeadlessBookingFlow(options) {
|
|
|
128633
128825
|
const selectedServiceId = state.selectedServiceId ?? defaultServiceId;
|
|
128634
128826
|
const selectedResourceId = state.selectedResourceId ?? defaultResourceId;
|
|
128635
128827
|
const selectedService = options.services.find((service) => service.id === selectedServiceId) ?? null;
|
|
128828
|
+
const lastSlidingServiceIdRef = useRef(null);
|
|
128829
|
+
useEffect(() => {
|
|
128830
|
+
const selectedId = selectedService?.id ?? null;
|
|
128831
|
+
if (lastSlidingServiceIdRef.current === selectedId) return;
|
|
128832
|
+
lastSlidingServiceIdRef.current = selectedId;
|
|
128833
|
+
const slidingScale = getBookingServiceSlidingScale(selectedService);
|
|
128834
|
+
dispatch({
|
|
128835
|
+
type: "sliding-amount-changed",
|
|
128836
|
+
value: slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatBookingCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
128837
|
+
});
|
|
128838
|
+
}, [selectedService]);
|
|
128636
128839
|
const hasPortalBearerAuth = (api.config.authOverrides?.portal ?? api.config.auth).type === "bearer";
|
|
128840
|
+
const selectedServiceSlidingScale = getBookingServiceSlidingScale(selectedService);
|
|
128841
|
+
const selectedSlidingAmount = parseBookingCurrencyInputToCents(
|
|
128842
|
+
state.selectedSlidingAmountInput
|
|
128843
|
+
);
|
|
128844
|
+
const selectedAppointmentPriceAmount = selectedServiceSlidingScale && selectedSlidingAmount !== null ? selectedSlidingAmount : selectedService?.priceAmount ?? 0;
|
|
128637
128845
|
const canLoadAppointmentPackages = Boolean(
|
|
128638
|
-
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && (selectedService.priceAmount ?? 0) > 0
|
|
128846
|
+
options.enableAppointmentPackages && hasPortalBearerAuth && selectedService && !selectedServiceSlidingScale && (selectedService.priceAmount ?? 0) > 0
|
|
128639
128847
|
);
|
|
128640
|
-
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
128848
|
+
const appointmentPackagesUnavailableReason = !options.enableAppointmentPackages ? "disabled" : !selectedService || selectedServiceSlidingScale || (selectedService.priceAmount ?? 0) <= 0 ? "missing-priced-service" : !hasPortalBearerAuth ? "missing-portal-auth" : null;
|
|
128641
128849
|
const data = useMemo(() => toBookingFormData(state), [state]);
|
|
128642
128850
|
const availabilityDatesQuery = useMemo(
|
|
128643
128851
|
() => buildBookingAvailabilityQuery({
|
|
@@ -128867,13 +129075,13 @@ function useHeadlessBookingFlow(options) {
|
|
|
128867
129075
|
state.selectedSlot
|
|
128868
129076
|
]);
|
|
128869
129077
|
const appointmentDiscountContext = useMemo(
|
|
128870
|
-
() => selectedService &&
|
|
128871
|
-
[
|
|
129078
|
+
() => selectedService && selectedAppointmentPriceAmount > 0 ? { type: "appointment", serviceId: selectedService.id } : null,
|
|
129079
|
+
[selectedAppointmentPriceAmount, selectedService?.id]
|
|
128872
129080
|
);
|
|
128873
129081
|
const discountUi = useDiscountCodeUi({
|
|
128874
129082
|
api,
|
|
128875
129083
|
discountContext: appointmentDiscountContext,
|
|
128876
|
-
subtotalCents:
|
|
129084
|
+
subtotalCents: selectedAppointmentPriceAmount
|
|
128877
129085
|
});
|
|
128878
129086
|
const { submit, clearFeedback } = useBookingSubmission(options.siteId);
|
|
128879
129087
|
const submittingRef = useRef(false);
|
|
@@ -129016,6 +129224,7 @@ function useHeadlessBookingFlow(options) {
|
|
|
129016
129224
|
type: "appointment-package-selected",
|
|
129017
129225
|
packageId: packageId ? unsafeAsCustomerPassId(packageId) : null
|
|
129018
129226
|
}),
|
|
129227
|
+
setSlidingAmountInput: (value) => dispatch({ type: "sliding-amount-changed", value }),
|
|
129019
129228
|
setDiscountCode: (code) => {
|
|
129020
129229
|
dispatch({ type: "discount-code-changed", code });
|
|
129021
129230
|
latestRef.current.setDiscountCode(code);
|
|
@@ -129086,11 +129295,11 @@ function useHeadlessBookingFlow(options) {
|
|
|
129086
129295
|
() => selectedService && paymentResolution.mode !== "unsupported" ? buildBookingPaymentSelectionViewModel({
|
|
129087
129296
|
serviceTitle: selectedService.title,
|
|
129088
129297
|
paymentTerms: selectedService.paymentTerms,
|
|
129089
|
-
priceAmount:
|
|
129298
|
+
priceAmount: selectedAppointmentPriceAmount,
|
|
129090
129299
|
priceCurrency: selectedService.priceCurrency,
|
|
129091
129300
|
bookingStartAt: state.selectedSlot?.startAt
|
|
129092
129301
|
}) : null,
|
|
129093
|
-
[paymentResolution.mode, selectedService, state.selectedSlot?.startAt]
|
|
129302
|
+
[paymentResolution.mode, selectedAppointmentPriceAmount, selectedService, state.selectedSlot?.startAt]
|
|
129094
129303
|
);
|
|
129095
129304
|
const appointmentPackageItems = appointmentPackages.tag === "loaded" ? appointmentPackages.value : [];
|
|
129096
129305
|
const selectedAppointmentPackage = appointmentPackageItems.find(
|
|
@@ -129119,6 +129328,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
129119
129328
|
selection: null,
|
|
129120
129329
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
129121
129330
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
129331
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
129332
|
+
selectedSlidingAmount,
|
|
129333
|
+
slidingScale: selectedServiceSlidingScale,
|
|
129122
129334
|
appointmentPackages: appointmentPackagesModel,
|
|
129123
129335
|
errorMessage: paymentResolution.errorMessage ?? "This service cannot be booked right now."
|
|
129124
129336
|
} : {
|
|
@@ -129127,6 +129339,9 @@ function useHeadlessBookingFlow(options) {
|
|
|
129127
129339
|
selection: paymentSelection,
|
|
129128
129340
|
selectedCollectionOptionKind: state.selectedCollectionOptionKind,
|
|
129129
129341
|
selectedAppointmentPackageId: state.selectedAppointmentPackageId,
|
|
129342
|
+
selectedSlidingAmountInput: state.selectedSlidingAmountInput,
|
|
129343
|
+
selectedSlidingAmount,
|
|
129344
|
+
slidingScale: selectedServiceSlidingScale,
|
|
129130
129345
|
appointmentPackages: appointmentPackagesModel
|
|
129131
129346
|
};
|
|
129132
129347
|
return {
|
|
@@ -129667,6 +129882,9 @@ var paymentOptionLayoutStyle = {
|
|
|
129667
129882
|
var summaryStackStyle = {
|
|
129668
129883
|
gap: "0.125rem"
|
|
129669
129884
|
};
|
|
129885
|
+
function formatBookingAmount(amount, currency) {
|
|
129886
|
+
return formatCurrencyAmount(amount, currency, { decimals: "auto" });
|
|
129887
|
+
}
|
|
129670
129888
|
function HeadlessBookingDefaultForm({
|
|
129671
129889
|
booking,
|
|
129672
129890
|
onSubmit
|
|
@@ -129943,6 +130161,7 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
129943
130161
|
}
|
|
129944
130162
|
const packageOptions = booking.payment.appointmentPackages.items;
|
|
129945
130163
|
const hasPackageOptions = packageOptions.length > 0;
|
|
130164
|
+
const slidingScale = booking.payment.slidingScale;
|
|
129946
130165
|
return /* @__PURE__ */ jsxs("div", { className: "ab-stack", children: [
|
|
129947
130166
|
/* @__PURE__ */ jsxs("div", { className: "ab-info-box", children: [
|
|
129948
130167
|
/* @__PURE__ */ jsx("h3", { className: "ab-subtitle", children: viewModel.sectionTitle }),
|
|
@@ -129953,6 +130172,28 @@ function HeadlessBookingPaymentSelectionStep({
|
|
|
129953
130172
|
booking.payment.appointmentPackages.state.message,
|
|
129954
130173
|
" You can continue with the normal payment option."
|
|
129955
130174
|
] }) : null,
|
|
130175
|
+
slidingScale ? /* @__PURE__ */ jsxs("div", { className: "rb-space-y-2", children: [
|
|
130176
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "appointment-sliding-amount", className: "form-label", children: "Choose your price" }),
|
|
130177
|
+
/* @__PURE__ */ jsxs("p", { className: "rb-caption status-muted", children: [
|
|
130178
|
+
formatBookingAmount(slidingScale.minAmount, slidingScale.currency),
|
|
130179
|
+
" to ",
|
|
130180
|
+
formatBookingAmount(slidingScale.maxAmount, slidingScale.currency),
|
|
130181
|
+
slidingScale.suggestedAmount !== null ? `, suggested ${formatBookingAmount(slidingScale.suggestedAmount, slidingScale.currency)}` : ""
|
|
130182
|
+
] }),
|
|
130183
|
+
/* @__PURE__ */ jsx(
|
|
130184
|
+
"input",
|
|
130185
|
+
{
|
|
130186
|
+
id: "appointment-sliding-amount",
|
|
130187
|
+
type: "number",
|
|
130188
|
+
className: "form-input",
|
|
130189
|
+
min: slidingScale.minAmount / 100,
|
|
130190
|
+
max: slidingScale.maxAmount / 100,
|
|
130191
|
+
step: "0.01",
|
|
130192
|
+
value: booking.payment.selectedSlidingAmountInput,
|
|
130193
|
+
onChange: (event) => booking.actions.setSlidingAmountInput(event.target.value)
|
|
130194
|
+
}
|
|
130195
|
+
)
|
|
130196
|
+
] }) : null,
|
|
129956
130197
|
/* @__PURE__ */ jsxs("div", { className: "ab-stack", role: "list", "aria-label": "Payment options", children: [
|
|
129957
130198
|
packageOptions.map((appointmentPackage) => {
|
|
129958
130199
|
const isSelected = booking.payment.selectedAppointmentPackageId === appointmentPackage.customerPassId;
|
|
@@ -131590,6 +131831,7 @@ function useEligibility(params) {
|
|
|
131590
131831
|
occurrenceId: params.occurrenceId,
|
|
131591
131832
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
131592
131833
|
ticketTypeId: params.ticketTypeId ?? void 0,
|
|
131834
|
+
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
131593
131835
|
email: params.email.trim().toLowerCase(),
|
|
131594
131836
|
ticketsCount: params.ticketsCount
|
|
131595
131837
|
});
|
|
@@ -131610,7 +131852,7 @@ function useEligibility(params) {
|
|
|
131610
131852
|
return () => {
|
|
131611
131853
|
cancelled = true;
|
|
131612
131854
|
};
|
|
131613
|
-
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.email, params.ticketsCount]);
|
|
131855
|
+
}, [api, params.enabled, params.occurrenceId, params.attendanceMode, params.ticketTypeId, params.selectedSlidingAmount, params.email, params.ticketsCount]);
|
|
131614
131856
|
return {
|
|
131615
131857
|
state,
|
|
131616
131858
|
eligibility: state.eligibility,
|
|
@@ -131933,6 +132175,41 @@ function TicketCounterLimit(props2) {
|
|
|
131933
132175
|
] }) : null
|
|
131934
132176
|
] });
|
|
131935
132177
|
}
|
|
132178
|
+
function formatCurrencyInputAmount(amount) {
|
|
132179
|
+
const major = amount / 100;
|
|
132180
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
132181
|
+
}
|
|
132182
|
+
function SlidingScaleAmountField(props2) {
|
|
132183
|
+
const minLabel = formatPrice(props2.slidingScale.minAmount, props2.currency);
|
|
132184
|
+
const maxLabel = formatPrice(props2.slidingScale.maxAmount, props2.currency);
|
|
132185
|
+
const suggestedLabel = props2.slidingScale.suggestedAmount !== null ? formatPrice(props2.slidingScale.suggestedAmount, props2.currency) : null;
|
|
132186
|
+
return /* @__PURE__ */ jsxs("div", { className: "er-field", children: [
|
|
132187
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "er-sliding-amount", className: "er-label", children: "Amount" }),
|
|
132188
|
+
/* @__PURE__ */ jsx(
|
|
132189
|
+
"input",
|
|
132190
|
+
{
|
|
132191
|
+
id: "er-sliding-amount",
|
|
132192
|
+
type: "number",
|
|
132193
|
+
min: formatCurrencyInputAmount(props2.slidingScale.minAmount),
|
|
132194
|
+
max: formatCurrencyInputAmount(props2.slidingScale.maxAmount),
|
|
132195
|
+
step: "0.01",
|
|
132196
|
+
inputMode: "decimal",
|
|
132197
|
+
className: "er-input",
|
|
132198
|
+
value: props2.value,
|
|
132199
|
+
onChange: (event) => props2.onChange?.(event.target.value)
|
|
132200
|
+
}
|
|
132201
|
+
),
|
|
132202
|
+
/* @__PURE__ */ jsxs("p", { className: "er-text er-text--muted", children: [
|
|
132203
|
+
"Choose between ",
|
|
132204
|
+
minLabel,
|
|
132205
|
+
" and ",
|
|
132206
|
+
maxLabel,
|
|
132207
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
132208
|
+
"."
|
|
132209
|
+
] }),
|
|
132210
|
+
props2.message ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: props2.message }) : null
|
|
132211
|
+
] });
|
|
132212
|
+
}
|
|
131936
132213
|
function getTicketTypeCounterAvailabilityLabel(input) {
|
|
131937
132214
|
if (input.selectedRemainingCapacity !== null) {
|
|
131938
132215
|
return `${input.selectedRemainingCapacity} remaining for this ticket type`;
|
|
@@ -131996,6 +132273,10 @@ var TicketSelectionStep = ({
|
|
|
131996
132273
|
maxTickets,
|
|
131997
132274
|
selectedTicketTypeId = null,
|
|
131998
132275
|
onTicketTypeChange,
|
|
132276
|
+
slidingScale = null,
|
|
132277
|
+
selectedSlidingAmountInput = "",
|
|
132278
|
+
slidingScaleSelectionMessage = null,
|
|
132279
|
+
onSlidingAmountChange,
|
|
131999
132280
|
onTicketsChange
|
|
132000
132281
|
}) => {
|
|
132001
132282
|
const deliveryMode = event?.deliveryMode ?? "in_person";
|
|
@@ -132111,6 +132392,16 @@ var TicketSelectionStep = ({
|
|
|
132111
132392
|
] })
|
|
132112
132393
|
] })
|
|
132113
132394
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132395
|
+
slidingScale ? /* @__PURE__ */ jsx(
|
|
132396
|
+
SlidingScaleAmountField,
|
|
132397
|
+
{
|
|
132398
|
+
slidingScale,
|
|
132399
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY2,
|
|
132400
|
+
value: selectedSlidingAmountInput,
|
|
132401
|
+
message: slidingScaleSelectionMessage,
|
|
132402
|
+
onChange: onSlidingAmountChange
|
|
132403
|
+
}
|
|
132404
|
+
) : null,
|
|
132114
132405
|
/* @__PURE__ */ jsx("h3", { className: "er-title", children: canJoinWaitlist ? "How many waitlist spots?" : "How many tickets?" }),
|
|
132115
132406
|
/* @__PURE__ */ jsxs("div", { className: "er-ticket-counter-group", children: [
|
|
132116
132407
|
/* @__PURE__ */ jsx(
|
|
@@ -132963,6 +133254,10 @@ function EventRegistrationWizardContent(props2) {
|
|
|
132963
133254
|
maxTickets: wizard.maxTicketsNum,
|
|
132964
133255
|
selectedTicketTypeId: wizard.selectedTicketTypeId,
|
|
132965
133256
|
onTicketTypeChange: wizard.setSelectedTicketTypeId,
|
|
133257
|
+
slidingScale: wizard.selectedEventSlidingScale,
|
|
133258
|
+
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
133259
|
+
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
133260
|
+
onSlidingAmountChange: wizard.setSelectedSlidingAmountInput,
|
|
132966
133261
|
onTicketsChange: wizard.setTicketsCount
|
|
132967
133262
|
}
|
|
132968
133263
|
)
|
|
@@ -133156,7 +133451,7 @@ function EventRegistrationSummaryBar(props2) {
|
|
|
133156
133451
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
133157
133452
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
133158
133453
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
133159
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
133454
|
+
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
133160
133455
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY2;
|
|
133161
133456
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
133162
133457
|
const subtotalCents = Math.max(0, summaryPrice * wizard.ticketsCount);
|
|
@@ -133556,6 +133851,7 @@ function useEventRegistrationSubmit(options) {
|
|
|
133556
133851
|
occurrenceId: submitOccurrenceId,
|
|
133557
133852
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
133558
133853
|
ticketTypeId: options.selectedTicketTypeId ?? void 0,
|
|
133854
|
+
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
133559
133855
|
email: options.formData.email.trim().toLowerCase(),
|
|
133560
133856
|
name: options.formData.name.trim(),
|
|
133561
133857
|
ticketsCount: options.ticketsCount,
|
|
@@ -133657,6 +133953,35 @@ function useEventRegistrationSubmit(options) {
|
|
|
133657
133953
|
}
|
|
133658
133954
|
|
|
133659
133955
|
// ../blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.ts
|
|
133956
|
+
function parseCurrencyInputToCents(value) {
|
|
133957
|
+
const trimmed = value.trim();
|
|
133958
|
+
if (!trimmed) return null;
|
|
133959
|
+
const amount = Number(trimmed);
|
|
133960
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
133961
|
+
return Math.round(amount * 100);
|
|
133962
|
+
}
|
|
133963
|
+
function formatCentsAsCurrencyInput(amount) {
|
|
133964
|
+
const major = amount / 100;
|
|
133965
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
133966
|
+
}
|
|
133967
|
+
function getSlidingScaleForEvent(event) {
|
|
133968
|
+
const pricing = event ? resolveRuntimeEventPricing(event) : null;
|
|
133969
|
+
return pricing?.kind === "sliding_scale" ? {
|
|
133970
|
+
minAmount: pricing.minAmount,
|
|
133971
|
+
maxAmount: pricing.maxAmount,
|
|
133972
|
+
suggestedAmount: pricing.suggestedAmount
|
|
133973
|
+
} : null;
|
|
133974
|
+
}
|
|
133975
|
+
function getSlidingScaleSelectionMessage(input) {
|
|
133976
|
+
if (!input.slidingScale) return null;
|
|
133977
|
+
if (input.selectedAmount === null) {
|
|
133978
|
+
return "Choose an amount to continue.";
|
|
133979
|
+
}
|
|
133980
|
+
if (input.selectedAmount < input.slidingScale.minAmount || input.selectedAmount > input.slidingScale.maxAmount) {
|
|
133981
|
+
return "Choose an amount within the sliding scale.";
|
|
133982
|
+
}
|
|
133983
|
+
return null;
|
|
133984
|
+
}
|
|
133660
133985
|
function useEventRegistrationWizard(options) {
|
|
133661
133986
|
const api = useBlockApi();
|
|
133662
133987
|
const registrationEvents = useMemo(
|
|
@@ -133701,6 +134026,10 @@ function useEventRegistrationWizard(options) {
|
|
|
133701
134026
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
133702
134027
|
);
|
|
133703
134028
|
const [selectedTicketTypeId, setSelectedTicketTypeId] = useState(null);
|
|
134029
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState(() => {
|
|
134030
|
+
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
134031
|
+
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
134032
|
+
});
|
|
133704
134033
|
const [registrationResult, setRegistrationResult] = useState(null);
|
|
133705
134034
|
const [errorMessage, setErrorMessage] = useState("");
|
|
133706
134035
|
const [altchaSolution, setAltchaSolution] = useState(null);
|
|
@@ -133737,6 +134066,7 @@ function useEventRegistrationWizard(options) {
|
|
|
133737
134066
|
occurrenceId,
|
|
133738
134067
|
attendanceMode: selectedAttendanceMode,
|
|
133739
134068
|
ticketTypeId: selectedTicketTypeId,
|
|
134069
|
+
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
133740
134070
|
email: formData.email,
|
|
133741
134071
|
ticketsCount
|
|
133742
134072
|
});
|
|
@@ -133872,6 +134202,18 @@ function useEventRegistrationWizard(options) {
|
|
|
133872
134202
|
}),
|
|
133873
134203
|
[selectedAttendanceMode, selectedEvent, preSelectedEvent, eligibility, selectedTicketTypeId]
|
|
133874
134204
|
);
|
|
134205
|
+
const selectedSlidingAmount = useMemo(
|
|
134206
|
+
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
134207
|
+
[selectedSlidingAmountInput]
|
|
134208
|
+
);
|
|
134209
|
+
const selectedEventSlidingScale = useMemo(
|
|
134210
|
+
() => getSlidingScaleForEvent(selectedEvent ?? preSelectedEvent),
|
|
134211
|
+
[selectedEvent, preSelectedEvent]
|
|
134212
|
+
);
|
|
134213
|
+
const slidingScaleSelectionMessage = getSlidingScaleSelectionMessage({
|
|
134214
|
+
slidingScale: selectedEventSlidingScale,
|
|
134215
|
+
selectedAmount: selectedSlidingAmount
|
|
134216
|
+
});
|
|
133875
134217
|
const ticketTypeSelectionRequired = useMemo(() => {
|
|
133876
134218
|
const event = selectedEvent ?? preSelectedEvent;
|
|
133877
134219
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
@@ -133940,12 +134282,24 @@ function useEventRegistrationWizard(options) {
|
|
|
133940
134282
|
setGuestSectionShake(false);
|
|
133941
134283
|
};
|
|
133942
134284
|
const eventRequiresPayment = useMemo(
|
|
133943
|
-
() =>
|
|
134285
|
+
() => {
|
|
134286
|
+
if (selectedEventSlidingScale) {
|
|
134287
|
+
return (selectedSlidingAmount ?? 0) > 0;
|
|
134288
|
+
}
|
|
134289
|
+
return resolveEventRequiresPayment({
|
|
134290
|
+
eligibility,
|
|
134291
|
+
selectedTicketType,
|
|
134292
|
+
event: selectedEvent ?? preSelectedEvent
|
|
134293
|
+
});
|
|
134294
|
+
},
|
|
134295
|
+
[
|
|
133944
134296
|
eligibility,
|
|
133945
134297
|
selectedTicketType,
|
|
133946
|
-
|
|
133947
|
-
|
|
133948
|
-
|
|
134298
|
+
selectedEvent,
|
|
134299
|
+
preSelectedEvent,
|
|
134300
|
+
selectedEventSlidingScale,
|
|
134301
|
+
selectedSlidingAmount
|
|
134302
|
+
]
|
|
133949
134303
|
);
|
|
133950
134304
|
const handleDetailsComplete = async () => {
|
|
133951
134305
|
if (ticketTypeSelectionRequired && !hasValidSelectedTicketType) {
|
|
@@ -133954,6 +134308,11 @@ function useEventRegistrationWizard(options) {
|
|
|
133954
134308
|
setStep("error");
|
|
133955
134309
|
return { ok: false, reason: "blocked", message: message2 };
|
|
133956
134310
|
}
|
|
134311
|
+
if (slidingScaleSelectionMessage) {
|
|
134312
|
+
setErrorMessage(slidingScaleSelectionMessage);
|
|
134313
|
+
setStep("error");
|
|
134314
|
+
return { ok: false, reason: "blocked", message: slidingScaleSelectionMessage };
|
|
134315
|
+
}
|
|
133957
134316
|
if (!validateForm()) {
|
|
133958
134317
|
setGuestSectionShake(true);
|
|
133959
134318
|
return {
|
|
@@ -134038,9 +134397,18 @@ function useEventRegistrationWizard(options) {
|
|
|
134038
134397
|
const discountSubtotalCents = useMemo(() => {
|
|
134039
134398
|
if (discountContext?.type !== "event") return void 0;
|
|
134040
134399
|
const event = selectedEvent ?? preSelectedEvent;
|
|
134041
|
-
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
134400
|
+
const eventPriceCents = selectedTicketType?.priceAmount ?? eligibility?.price ?? (selectedEventSlidingScale ? selectedSlidingAmount : null) ?? (event ? publicEventScalarPrice(resolveRuntimeEventPricing(event)) : null) ?? 0;
|
|
134042
134401
|
return Math.max(0, eventPriceCents * ticketsCount);
|
|
134043
|
-
}, [
|
|
134402
|
+
}, [
|
|
134403
|
+
discountContext,
|
|
134404
|
+
selectedTicketType,
|
|
134405
|
+
eligibility,
|
|
134406
|
+
selectedEvent,
|
|
134407
|
+
preSelectedEvent,
|
|
134408
|
+
selectedEventSlidingScale,
|
|
134409
|
+
selectedSlidingAmount,
|
|
134410
|
+
ticketsCount
|
|
134411
|
+
]);
|
|
134044
134412
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
134045
134413
|
const selectionMethod = paymentSelection.method;
|
|
134046
134414
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -134049,6 +134417,7 @@ function useEventRegistrationWizard(options) {
|
|
|
134049
134417
|
registrationTarget,
|
|
134050
134418
|
selectedAttendanceMode,
|
|
134051
134419
|
selectedTicketTypeId,
|
|
134420
|
+
selectedSlidingAmount,
|
|
134052
134421
|
ticketsCount,
|
|
134053
134422
|
formData,
|
|
134054
134423
|
altchaSolution,
|
|
@@ -134063,6 +134432,10 @@ function useEventRegistrationWizard(options) {
|
|
|
134063
134432
|
});
|
|
134064
134433
|
const handleEventSelect = (event) => {
|
|
134065
134434
|
setSelectedEvent(event);
|
|
134435
|
+
const slidingScale = getSlidingScaleForEvent(event);
|
|
134436
|
+
setSelectedSlidingAmountInput(
|
|
134437
|
+
slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : ""
|
|
134438
|
+
);
|
|
134066
134439
|
setSelectedAttendanceMode(
|
|
134067
134440
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
134068
134441
|
);
|
|
@@ -134072,6 +134445,7 @@ function useEventRegistrationWizard(options) {
|
|
|
134072
134445
|
const handleRetry = () => {
|
|
134073
134446
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
134074
134447
|
setSelectedTicketTypeId(null);
|
|
134448
|
+
setSelectedSlidingAmountInput("");
|
|
134075
134449
|
setSelectedAttendanceMode(
|
|
134076
134450
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
134077
134451
|
);
|
|
@@ -134108,6 +134482,11 @@ function useEventRegistrationWizard(options) {
|
|
|
134108
134482
|
setSelectedAttendanceMode,
|
|
134109
134483
|
selectedTicketTypeId,
|
|
134110
134484
|
setSelectedTicketTypeId,
|
|
134485
|
+
selectedSlidingAmountInput,
|
|
134486
|
+
setSelectedSlidingAmountInput,
|
|
134487
|
+
selectedSlidingAmount,
|
|
134488
|
+
selectedEventSlidingScale,
|
|
134489
|
+
slidingScaleSelectionMessage,
|
|
134111
134490
|
selectedTicketType,
|
|
134112
134491
|
visibleTicketTypes,
|
|
134113
134492
|
ticketTypeSelectionRequired,
|
|
@@ -135188,6 +135567,44 @@ function CoursePricingSelector({
|
|
|
135188
135567
|
)
|
|
135189
135568
|
] });
|
|
135190
135569
|
}
|
|
135570
|
+
function CourseSlidingScaleInput({
|
|
135571
|
+
pricing,
|
|
135572
|
+
value,
|
|
135573
|
+
onChange
|
|
135574
|
+
}) {
|
|
135575
|
+
const slidingScale = pricing.slidingScale;
|
|
135576
|
+
if (!slidingScale) {
|
|
135577
|
+
return null;
|
|
135578
|
+
}
|
|
135579
|
+
const minLabel = formatCoursePriceAmount(slidingScale.minAmount, pricing.currency);
|
|
135580
|
+
const maxLabel = formatCoursePriceAmount(slidingScale.maxAmount, pricing.currency);
|
|
135581
|
+
const suggestedLabel = slidingScale.suggestedAmount !== null ? formatCoursePriceAmount(slidingScale.suggestedAmount, pricing.currency) : null;
|
|
135582
|
+
return /* @__PURE__ */ jsxs("div", { className: "cr-form__field", children: [
|
|
135583
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "cr-sliding-amount", className: "cr-form__label", children: "Amount" }),
|
|
135584
|
+
/* @__PURE__ */ jsx(
|
|
135585
|
+
"input",
|
|
135586
|
+
{
|
|
135587
|
+
id: "cr-sliding-amount",
|
|
135588
|
+
type: "number",
|
|
135589
|
+
min: slidingScale.minAmount / 100,
|
|
135590
|
+
max: slidingScale.maxAmount / 100,
|
|
135591
|
+
step: "0.01",
|
|
135592
|
+
inputMode: "decimal",
|
|
135593
|
+
className: "cr-form__input",
|
|
135594
|
+
value,
|
|
135595
|
+
onChange: (event) => onChange(event.target.value)
|
|
135596
|
+
}
|
|
135597
|
+
),
|
|
135598
|
+
/* @__PURE__ */ jsxs("p", { className: "cr-text cr-text--muted", children: [
|
|
135599
|
+
"Choose between ",
|
|
135600
|
+
minLabel,
|
|
135601
|
+
" and ",
|
|
135602
|
+
maxLabel,
|
|
135603
|
+
suggestedLabel ? `; suggested ${suggestedLabel}` : "",
|
|
135604
|
+
"."
|
|
135605
|
+
] })
|
|
135606
|
+
] });
|
|
135607
|
+
}
|
|
135191
135608
|
function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading, onLogout }) {
|
|
135192
135609
|
const nameErrorId = "cr-name-error";
|
|
135193
135610
|
const emailErrorId = "cr-email-error";
|
|
@@ -135270,6 +135687,17 @@ function EnrollmentForm({ formData, errors, onChange, isEmailLocked, isLoading,
|
|
|
135270
135687
|
] })
|
|
135271
135688
|
] });
|
|
135272
135689
|
}
|
|
135690
|
+
function parseCurrencyInputToCents2(value) {
|
|
135691
|
+
const trimmed = value.trim();
|
|
135692
|
+
if (!trimmed) return null;
|
|
135693
|
+
const amount = Number(trimmed);
|
|
135694
|
+
if (!Number.isFinite(amount) || amount < 0) return null;
|
|
135695
|
+
return Math.round(amount * 100);
|
|
135696
|
+
}
|
|
135697
|
+
function formatCentsAsCurrencyInput2(amount) {
|
|
135698
|
+
const major = amount / 100;
|
|
135699
|
+
return Number.isInteger(major) ? String(major) : major.toFixed(2);
|
|
135700
|
+
}
|
|
135273
135701
|
function shouldFetchCourseEligibility(course, hasPaidSelection, portalAuthState, hasWaitlistClaimToken) {
|
|
135274
135702
|
if (!course || portalAuthState === "checking") return false;
|
|
135275
135703
|
if (hasWaitlistClaimToken) return false;
|
|
@@ -135287,12 +135715,27 @@ function getSessionIdFromUrl() {
|
|
|
135287
135715
|
}
|
|
135288
135716
|
function getMissingCoursePricingSelectionMessage(pricing) {
|
|
135289
135717
|
if (pricing?.requiresSelection && !pricing.selectedOption) {
|
|
135718
|
+
if (pricing.slidingScale) {
|
|
135719
|
+
return "Choose an amount to continue.";
|
|
135720
|
+
}
|
|
135290
135721
|
return "Choose a pricing option to continue.";
|
|
135291
135722
|
}
|
|
135723
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount < pricing.slidingScale.minAmount) {
|
|
135724
|
+
return "Choose an amount within the sliding scale.";
|
|
135725
|
+
}
|
|
135726
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null && pricing.selectedSlidingAmount > pricing.slidingScale.maxAmount) {
|
|
135727
|
+
return "Choose an amount within the sliding scale.";
|
|
135728
|
+
}
|
|
135292
135729
|
return null;
|
|
135293
135730
|
}
|
|
135294
135731
|
function buildCoursePricingOptionPayload(pricing) {
|
|
135295
|
-
|
|
135732
|
+
if (pricing?.selectedOption) {
|
|
135733
|
+
return { pricingOptionId: pricing.selectedOption.id };
|
|
135734
|
+
}
|
|
135735
|
+
if (pricing?.slidingScale && pricing.selectedSlidingAmount !== null) {
|
|
135736
|
+
return { selectedSlidingAmount: pricing.selectedSlidingAmount };
|
|
135737
|
+
}
|
|
135738
|
+
return {};
|
|
135296
135739
|
}
|
|
135297
135740
|
function resolveHasCoursePayment(pricing) {
|
|
135298
135741
|
if (!pricing) {
|
|
@@ -135333,6 +135776,7 @@ function useCourseRegistrationWizard(props2) {
|
|
|
135333
135776
|
scopedCourses.length === 1 ? scopedCourses[0] ?? null : null
|
|
135334
135777
|
);
|
|
135335
135778
|
const [selectedPricingOptionId, setSelectedPricingOptionId] = useState(null);
|
|
135779
|
+
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState("");
|
|
135336
135780
|
const [formData, setFormData] = useState({
|
|
135337
135781
|
name: "",
|
|
135338
135782
|
email: "",
|
|
@@ -135354,8 +135798,12 @@ function useCourseRegistrationWizard(props2) {
|
|
|
135354
135798
|
const [bookingMode, setBookingMode] = useState(null);
|
|
135355
135799
|
const waitlistClaim = useWaitlistClaim();
|
|
135356
135800
|
const selectedCoursePricing = useMemo(
|
|
135357
|
-
() => selectedCourse ? resolveCoursePricingState(
|
|
135358
|
-
|
|
135801
|
+
() => selectedCourse ? resolveCoursePricingState(
|
|
135802
|
+
selectedCourse,
|
|
135803
|
+
selectedPricingOptionId,
|
|
135804
|
+
parseCurrencyInputToCents2(selectedSlidingAmountInput)
|
|
135805
|
+
) : null,
|
|
135806
|
+
[selectedCourse, selectedPricingOptionId, selectedSlidingAmountInput]
|
|
135359
135807
|
);
|
|
135360
135808
|
const missingPricingSelectionMessage = getMissingCoursePricingSelectionMessage(
|
|
135361
135809
|
selectedCoursePricing
|
|
@@ -135428,9 +135876,13 @@ function useCourseRegistrationWizard(props2) {
|
|
|
135428
135876
|
useEffect(() => {
|
|
135429
135877
|
if (!selectedCourse) {
|
|
135430
135878
|
setSelectedPricingOptionId(null);
|
|
135879
|
+
setSelectedSlidingAmountInput("");
|
|
135431
135880
|
return;
|
|
135432
135881
|
}
|
|
135433
135882
|
const defaultPricing = resolveCoursePricingState(selectedCourse, null);
|
|
135883
|
+
setSelectedSlidingAmountInput(
|
|
135884
|
+
defaultPricing.slidingScale?.suggestedAmount !== null && defaultPricing.slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput2(defaultPricing.slidingScale.suggestedAmount) : ""
|
|
135885
|
+
);
|
|
135434
135886
|
setSelectedPricingOptionId((previous) => {
|
|
135435
135887
|
if (previous && defaultPricing.selectableOptions.some((option) => option.id === previous)) {
|
|
135436
135888
|
return previous;
|
|
@@ -135805,6 +136257,8 @@ function useCourseRegistrationWizard(props2) {
|
|
|
135805
136257
|
selectedCourse,
|
|
135806
136258
|
selectedPricingOptionId,
|
|
135807
136259
|
setSelectedPricingOptionId,
|
|
136260
|
+
selectedSlidingAmountInput,
|
|
136261
|
+
setSelectedSlidingAmountInput,
|
|
135808
136262
|
selectedCoursePricing,
|
|
135809
136263
|
setSelectedCourse,
|
|
135810
136264
|
formData,
|
|
@@ -135852,6 +136306,19 @@ function useCourseRegistrationWizard(props2) {
|
|
|
135852
136306
|
handleBookingModeChange
|
|
135853
136307
|
};
|
|
135854
136308
|
}
|
|
136309
|
+
function getCourseSlidingScaleMessage(pricing) {
|
|
136310
|
+
if (!pricing.slidingScale) {
|
|
136311
|
+
return null;
|
|
136312
|
+
}
|
|
136313
|
+
const selectedAmount = pricing.selectedSlidingAmount;
|
|
136314
|
+
if (selectedAmount === null) {
|
|
136315
|
+
return "Choose an amount to continue.";
|
|
136316
|
+
}
|
|
136317
|
+
if (selectedAmount < pricing.slidingScale.minAmount || selectedAmount > pricing.slidingScale.maxAmount) {
|
|
136318
|
+
return "Choose an amount within the sliding scale.";
|
|
136319
|
+
}
|
|
136320
|
+
return null;
|
|
136321
|
+
}
|
|
135855
136322
|
function CourseRegistrationWizard(props2) {
|
|
135856
136323
|
const {
|
|
135857
136324
|
showSessions = true,
|
|
@@ -135873,6 +136340,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
135873
136340
|
selectedCourse,
|
|
135874
136341
|
selectedPricingOptionId,
|
|
135875
136342
|
setSelectedPricingOptionId,
|
|
136343
|
+
selectedSlidingAmountInput,
|
|
136344
|
+
setSelectedSlidingAmountInput,
|
|
135876
136345
|
selectedCoursePricing,
|
|
135877
136346
|
formData,
|
|
135878
136347
|
setFormData,
|
|
@@ -135943,7 +136412,8 @@ function CourseRegistrationWizard(props2) {
|
|
|
135943
136412
|
const canShowDiscountUi = !discountsAvailableLoading && paymentChoice === "checkout" && discountsAvailable && manualCodeEntryAllowed;
|
|
135944
136413
|
const courseSoldOut = waitlistClaim.claim === null && courseEligibility?.isFull === true && courseEligibility.canJoinWaitlist !== true;
|
|
135945
136414
|
const detailsSubmitLabel = courseEligibility?.canJoinWaitlist ? "Join waitlist" : buttonText;
|
|
135946
|
-
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption;
|
|
136415
|
+
const pricingSelectionMissing = selectedCoursePricing?.requiresSelection === true && !selectedCoursePricing.selectedOption && !selectedCoursePricing.slidingScale;
|
|
136416
|
+
const slidingScaleMessage = selectedCoursePricing ? getCourseSlidingScaleMessage(selectedCoursePricing) : null;
|
|
135947
136417
|
const pricingUnavailable = selectedCoursePricing?.display.kind === "unavailable";
|
|
135948
136418
|
const selectedCourseWithPricing = selectedCourse && selectedCoursePricing ? {
|
|
135949
136419
|
course: selectedCourse,
|
|
@@ -136036,6 +136506,14 @@ function CourseRegistrationWizard(props2) {
|
|
|
136036
136506
|
onSelect: setSelectedPricingOptionId
|
|
136037
136507
|
}
|
|
136038
136508
|
),
|
|
136509
|
+
/* @__PURE__ */ jsx(
|
|
136510
|
+
CourseSlidingScaleInput,
|
|
136511
|
+
{
|
|
136512
|
+
pricing: selectedCourseWithPricing.pricing,
|
|
136513
|
+
value: selectedSlidingAmountInput,
|
|
136514
|
+
onChange: setSelectedSlidingAmountInput
|
|
136515
|
+
}
|
|
136516
|
+
),
|
|
136039
136517
|
showSpamProtection && /* @__PURE__ */ jsx("div", { className: "cr-altcha", children: /* @__PURE__ */ jsx(
|
|
136040
136518
|
AltchaWidget,
|
|
136041
136519
|
{
|
|
@@ -136073,7 +136551,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
136073
136551
|
{
|
|
136074
136552
|
type: "submit",
|
|
136075
136553
|
className: buttonClass,
|
|
136076
|
-
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || pricingUnavailable,
|
|
136554
|
+
disabled: courseSoldOut || eligibilityLoading || pricingSelectionMissing || slidingScaleMessage !== null || pricingUnavailable,
|
|
136077
136555
|
children: eligibilityLoading ? "Checking availability\u2026" : courseSoldOut ? "Sold out" : detailsSubmitLabel
|
|
136078
136556
|
}
|
|
136079
136557
|
)
|
|
@@ -136083,6 +136561,7 @@ function CourseRegistrationWizard(props2) {
|
|
|
136083
136561
|
),
|
|
136084
136562
|
courseSoldOut && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "This course is fully booked and there is no waitlist available right now." }),
|
|
136085
136563
|
pricingSelectionMissing && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "Choose a pricing option to continue." }),
|
|
136564
|
+
slidingScaleMessage && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: slidingScaleMessage }),
|
|
136086
136565
|
pricingUnavailable && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--muted", children: "Pricing is not available for this course right now." }),
|
|
136087
136566
|
eligibilityError && /* @__PURE__ */ jsx("p", { className: "cr-text cr-text--error", children: eligibilityError })
|
|
136088
136567
|
] })
|
|
@@ -137782,12 +138261,13 @@ var CarouselNodeClient = ({
|
|
|
137782
138261
|
]
|
|
137783
138262
|
);
|
|
137784
138263
|
const resolvedSlides = resolveSlidesToShowMobile(normalized.slidesToShow);
|
|
138264
|
+
const canAutoplay = normalized.autoplay && slides.length > 1;
|
|
137785
138265
|
const cssVars = React61__default.useMemo(
|
|
137786
138266
|
() => getCarouselSlidesToShowCssVars(normalized.slidesToShow),
|
|
137787
138267
|
[normalized.slidesToShow]
|
|
137788
138268
|
);
|
|
137789
138269
|
const plugins = React61__default.useMemo(() => {
|
|
137790
|
-
if (!
|
|
138270
|
+
if (!canAutoplay) return void 0;
|
|
137791
138271
|
return [
|
|
137792
138272
|
Autoplay({
|
|
137793
138273
|
delay: normalized.autoplayDelay,
|
|
@@ -137797,7 +138277,7 @@ var CarouselNodeClient = ({
|
|
|
137797
138277
|
// Continue after manual navigation
|
|
137798
138278
|
})
|
|
137799
138279
|
];
|
|
137800
|
-
}, [
|
|
138280
|
+
}, [canAutoplay, normalized.autoplayDelay]);
|
|
137801
138281
|
const [viewportRef, api] = useEmblaCarousel(
|
|
137802
138282
|
{
|
|
137803
138283
|
align: "start",
|
|
@@ -137836,7 +138316,7 @@ var CarouselNodeClient = ({
|
|
|
137836
138316
|
};
|
|
137837
138317
|
}, [api]);
|
|
137838
138318
|
React61__default.useEffect(() => {
|
|
137839
|
-
if (!api || !
|
|
138319
|
+
if (!api || !canAutoplay) return;
|
|
137840
138320
|
const autoplayPlugin = api.plugins()?.autoplay;
|
|
137841
138321
|
if (!autoplayPlugin) return;
|
|
137842
138322
|
const handleVisibility = () => {
|
|
@@ -137845,7 +138325,7 @@ var CarouselNodeClient = ({
|
|
|
137845
138325
|
};
|
|
137846
138326
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
137847
138327
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
137848
|
-
}, [api,
|
|
138328
|
+
}, [api, canAutoplay]);
|
|
137849
138329
|
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
137850
138330
|
/* @__PURE__ */ jsx("div", { className: "carousel-frame rb-overflow-hidden rb-w-full", children: /* @__PURE__ */ jsx(
|
|
137851
138331
|
"div",
|
|
@@ -137896,7 +138376,7 @@ var CarouselNodeClient = ({
|
|
|
137896
138376
|
"data-show-controls": normalized.showControls ? "true" : "false",
|
|
137897
138377
|
"data-show-dots": normalized.showDots ? "true" : "false",
|
|
137898
138378
|
"data-arrow-visibility": normalized.arrowVisibility,
|
|
137899
|
-
"data-autoplay":
|
|
138379
|
+
"data-autoplay": canAutoplay ? "true" : "false",
|
|
137900
138380
|
"data-loop": normalized.loop ? "true" : "false",
|
|
137901
138381
|
children: inner
|
|
137902
138382
|
}
|