@riverbankcms/sdk 0.94.0 → 0.95.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/README.md +3 -0
- package/dist/{PreviewEditorSidebar-D3PAF7NW.mjs → PreviewEditorSidebar-6FQYKOSB.mjs} +3 -3
- package/dist/{PreviewEditorUI-G5JVJEIJ.mjs → PreviewEditorUI-NPO2XMFB.mjs} +3 -3
- package/dist/SdkPreviewModeRuntime-PBEFH5AL.mjs +8 -0
- package/dist/_dts/api/src/bookingOperations.d.ts +7 -0
- package/dist/_dts/api/src/bookingRecords.d.ts +3 -0
- package/dist/_dts/api/src/cache-tags.d.ts +4 -0
- package/dist/_dts/api/src/contentRuntime.d.ts +14 -0
- package/dist/_dts/api/src/endpoints.d.ts +8 -0
- package/dist/_dts/api/src/event-presentation.d.ts +15 -0
- package/dist/_dts/api/src/index.d.ts +1 -1
- package/dist/_dts/api/src/public/endpoints.d.ts +1 -1
- package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +17 -4
- package/dist/_dts/api/src/shared-contracts.d.ts +19 -9
- package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
- package/dist/_dts/blocks/src/portal/types.d.ts +7 -0
- package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
- package/dist/_dts/blocks/src/system/runtime/api/types.d.ts +21 -6
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +5 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +5 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/sessionStorage.d.ts +9 -6
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.d.ts +36 -0
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +7 -1
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +2 -2
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +2 -3
- package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +19 -4
- package/dist/_dts/content-model/src/entry-slots/types.d.ts +6 -0
- package/dist/_dts/db/src/generated/supabase/database.types.d.ts +163 -2
- package/dist/_dts/media-core/src/assetsInUseSummary.d.ts +7 -0
- package/dist/_dts/media-core/src/mediaUsageProjection.d.ts +29 -1
- package/dist/_dts/sdk/src/client/types.d.ts +7 -2
- package/dist/_dts/sdk/src/next/middleware.d.ts +1 -0
- package/dist/_dts/sdk/src/next/redirect-destination.d.ts +3 -0
- package/dist/_dts/sdk/src/next/route-outcome-proxy.d.ts +22 -0
- package/dist/_dts/sdk/src/public-api/contracts.d.ts +20 -1
- package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
- package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +9 -1
- package/dist/_dts/sdk/src/version.d.ts +1 -1
- package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
- package/dist/{chunk-XIK2HYI3.mjs → chunk-4A6NWO3X.mjs} +7 -7
- package/dist/{chunk-NT76QGIJ.mjs → chunk-7ED5UNHL.mjs} +14 -0
- package/dist/{chunk-AQ6RT6LZ.mjs → chunk-K2SJTZMX.mjs} +2 -2
- package/dist/{chunk-A63UXN3P.mjs → chunk-PJPFTVZG.mjs} +2 -2
- package/dist/{chunk-AJZGT6YG.mjs → chunk-VTPPVAOL.mjs} +1 -1
- package/dist/{chunk-PCNCETBI.mjs → chunk-VZBSD4AJ.mjs} +449 -183
- package/dist/cli/index.mjs +176 -73
- package/dist/client/{accordion-RNQIPG55.mjs → accordion-LGO4IO5U.mjs} +1 -1
- package/dist/client/{bookingForm-HYEEVRLP.mjs → bookingForm-MWLS4LGU.mjs} +3 -3
- package/dist/client/bookings.mjs +211 -105
- package/dist/client/{carousel-W7DQ3YPU.mjs → carousel-6AHNP5HA.mjs} +1 -1
- package/dist/client/{cart-PXJ3SXXO.mjs → cart-CIXGYAZB.mjs} +4 -4
- package/dist/client/{checkout-X3JYSOXI.mjs → checkout-OTX6O3DN.mjs} +4 -4
- package/dist/client/{chunk-Q47XGAGS.mjs → chunk-AVBQSUIS.mjs} +1 -1
- package/dist/client/{chunk-WERRJXNJ.mjs → chunk-HOP7MKAZ.mjs} +1 -1
- package/dist/client/{chunk-IXDSXF2D.mjs → chunk-INRIT6DP.mjs} +353 -187
- package/dist/client/{chunk-DUOHLWLF.mjs → chunk-MYCXAKWP.mjs} +2 -2
- package/dist/client/{chunk-J6TMMMXW.mjs → chunk-R3NQTBWE.mjs} +1 -1
- package/dist/client/{chunk-YYVGSYBO.mjs → chunk-TREIML53.mjs} +3 -3
- package/dist/client/{chunk-6SYGVVWA.mjs → chunk-V67AT7ZW.mjs} +3 -0
- package/dist/client/{chunk-PICR3NTQ.mjs → chunk-Y2PMKCXO.mjs} +1 -1
- package/dist/client/client.mjs +503 -183
- package/dist/client/{courseRegistration-QZ67PVHO.mjs → courseRegistration-2LU6C3JL.mjs} +3 -3
- package/dist/client/{eventCalendar-V3BDHQNT.mjs → eventCalendar-OKUSISBZ.mjs} +6 -6
- package/dist/client/{eventCombined-XYFRN2RG.mjs → eventCombined-CMF6CD4S.mjs} +6 -6
- package/dist/client/{eventDetails-TFE5TWKV.mjs → eventDetails-XYWH7WXI.mjs} +6 -6
- package/dist/client/{eventListing-IQ6AGWZ6.mjs → eventListing-EK5DJTAH.mjs} +6 -6
- package/dist/client/{eventRegistration-WGJVFKQJ.mjs → eventRegistration-XDOSICV6.mjs} +6 -6
- package/dist/client/{form-6UZY6RUA.mjs → form-J6GOHKYG.mjs} +1 -1
- package/dist/client/{headerSection-RSFXY6V3.mjs → headerSection-C5SYJTRW.mjs} +2 -2
- package/dist/client/hooks.mjs +14 -0
- package/dist/client/{locationMap-24FH67I4.mjs → locationMap-QSQIFVVT.mjs} +2 -2
- package/dist/client/{newsletterForm-QVL3MLTN.mjs → newsletterForm-47VXJRWK.mjs} +1 -1
- package/dist/client/{productDetail-ZDYN3G4T.mjs → productDetail-5U6ISCC2.mjs} +4 -4
- package/dist/client/{productList-4BMJLQHZ.mjs → productList-XDZUMR3P.mjs} +4 -4
- package/dist/client/rendering/client.mjs +362 -182
- package/dist/client/rendering/islands.mjs +18 -18
- package/dist/client/rendering.mjs +489 -182
- package/dist/client/{shop-U5C634FF.mjs → shop-ZSZKIY3R.mjs} +4 -4
- package/dist/preview-next/before-render.mjs +14 -0
- package/dist/preview-next/client/runtime.mjs +5 -5
- package/dist/preview-next/middleware.mjs +14 -0
- package/dist/{sdk-runtime-VGV46WVB.mjs → sdk-runtime-PHNM7MRD.mjs} +6 -6
- package/dist/server/components.mjs +111 -0
- package/dist/server/config-validation.mjs +14 -0
- package/dist/server/config.mjs +14 -0
- package/dist/server/data.mjs +14 -0
- package/dist/server/index.mjs +44 -1
- package/dist/server/next/middleware.mjs +120 -0
- package/dist/server/next.mjs +225 -2
- package/dist/server/prebuild.mjs +1 -1
- package/dist/server/rendering/server.mjs +111 -0
- package/dist/server/rendering.mjs +127 -0
- package/dist/server/routing.mjs +14 -0
- package/dist/server/server.mjs +60 -1
- package/dist/server/theme-bridge.mjs +97 -0
- package/dist/styles/index.css +95 -0
- package/package.json +5 -1
- package/dist/SdkPreviewModeRuntime-NHTLRNQD.mjs +0 -8
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { LeafletStaticMap } from './chunk-
|
|
3
|
-
import { resolveCoursePricingState, useWaitlistClaim, MagicLinkForm, formatCoursePriceAmount, formatCoursePriceDisplay } from './chunk-
|
|
2
|
+
import { LeafletStaticMap } from './chunk-HOP7MKAZ.mjs';
|
|
3
|
+
import { resolveCoursePricingState, useWaitlistClaim, MagicLinkForm, formatCoursePriceAmount, formatCoursePriceDisplay } from './chunk-Y2PMKCXO.mjs';
|
|
4
4
|
import { CreditCard, Ticket, Star, Sparkles } from './chunk-6N7YRNYU.mjs';
|
|
5
|
-
import { usePolling, buildBookingPaymentSelectionViewModel } from './chunk-
|
|
5
|
+
import { usePolling, buildBookingPaymentSelectionViewModel } from './chunk-MYCXAKWP.mjs';
|
|
6
6
|
import { SpinnerNode } from './chunk-OLAOAZEO.mjs';
|
|
7
|
-
import { createBodyThemePortalRoot, TabBarFragment, useDiscountCodeUi, logoutPortal, consumeSearchParam, StepIndicator, DiscountCodeDisclosure, TerminalPanel, StateIcon, formatPrice, CrossIcon, ClockIcon, LoggedInAsUser, CheckIcon } from './chunk-
|
|
7
|
+
import { createBodyThemePortalRoot, TabBarFragment, useDiscountCodeUi, logoutPortal, consumeSearchParam, StepIndicator, DiscountCodeDisclosure, TerminalPanel, StateIcon, formatPrice, CrossIcon, ClockIcon, LoggedInAsUser, CheckIcon } from './chunk-R3NQTBWE.mjs';
|
|
8
8
|
import { getFieldValidationControlProps, FieldValidationMessage } from './chunk-3DCJ45Z2.mjs';
|
|
9
9
|
import { ModalShell } from './chunk-WBQG7VJA.mjs';
|
|
10
10
|
import { isSpamProtectionEnabled, AltchaWidget, getChallengeUrl } from './chunk-LJCX6V7Q.mjs';
|
|
11
11
|
import { useBlockApi, FeedbackMessage } from './chunk-TNGL2WJF.mjs';
|
|
12
|
-
import { buildEventRuntimeFilters, buildEventCalendarListingRender, groupEventsByDate, getOrderedDayNames, formatDateKey, getEventRuntimeFiltersKey, themeButtonClassName, normalizeCsvIds, normalizeOptionalId, normalizeEventBlockKind, normalizeCsvString, EventCompactRow, EmptyState, getContainerClass, getCardOrientation, isToday, MAX_EVENTS_PER_DAY, formatTime, WIZARD_STEPS, getWizardStepsForContext, getStepNumber, formatEventPriceDisplay, resolveRuntimeEventPricing, formatEventPrice, formatEventDateParts, resolveEventLinkProps, DateTimeTile, assertNever, EventCard, buildCalendarViewport, shiftCalendarAnchorDate, addMonths, getThreeMonthRange, buildTimetableModel, formatDate, MONTH_NAMES, getEventAvailability, formatEventTeacherLine, toRegistrationEvents, isEventContentType, findPreSelectedEvent, resolveRegistrationTarget, findEventByOccurrenceId, resolveEventRequiresPayment, resolveDiscountContext } from './chunk-
|
|
12
|
+
import { buildEventRuntimeFilters, buildEventCalendarListingRender, groupEventsByDate, getOrderedDayNames, formatDateKey, getEventRuntimeFiltersKey, themeButtonClassName, normalizeCsvIds, normalizeOptionalId, normalizeEventBlockKind, normalizeCsvString, EventCompactRow, EmptyState, getContainerClass, getCardOrientation, isToday, MAX_EVENTS_PER_DAY, formatTime, WIZARD_STEPS, getWizardStepsForContext, getStepNumber, formatEventPriceDisplay, resolveRuntimeEventPricing, formatEventPrice, formatEventDateParts, resolveEventLinkProps, DateTimeTile, assertNever, EventCard, buildCalendarViewport, shiftCalendarAnchorDate, addMonths, getThreeMonthRange, buildTimetableModel, formatDate, MONTH_NAMES, getEventAvailability, formatEventTeacherLine, toRegistrationEvents, isEventContentType, findPreSelectedEvent, resolveRegistrationTarget, findEventByOccurrenceId, resolveEventRequiresPayment, resolveDiscountContext } from './chunk-V67AT7ZW.mjs';
|
|
13
13
|
import { publicEventPricingType, getBookingLocalDateKey, toScheduledBookingDateTime, toBookingTimeZone, publicEventPricingCurrency, formatBookingDateTime, publicEventPricingMode, publicEventScalarPrice, publicEventTicketTypes, formatCurrencyAmount, formatBookingDate, formatBookingTime } from './chunk-PCHACQEB.mjs';
|
|
14
14
|
import React9, { createContext, useId, useMemo, useReducer, useState, useRef, useEffect, useCallback, useContext } from 'react';
|
|
15
15
|
import { createPortal } from 'react-dom';
|
|
@@ -337,6 +337,7 @@ function transformEligibilityResponse(response) {
|
|
|
337
337
|
requiresPayment: eligibility.requiresPayment,
|
|
338
338
|
pricingMode: eligibility.pricingMode,
|
|
339
339
|
selectedTicketTypeId: eligibility.selectedTicketTypeId ?? null,
|
|
340
|
+
ticketLines: eligibility.ticketLines ?? [],
|
|
340
341
|
ticketTypes: eligibility.ticketTypes ?? [],
|
|
341
342
|
isFull: eligibility.isFull,
|
|
342
343
|
waitlistEnabled: eligibility.waitlistEnabled,
|
|
@@ -393,6 +394,72 @@ function findSelectedTicketType(input) {
|
|
|
393
394
|
}).find((ticketType) => ticketType.id === input.selectedTicketTypeId) ?? null;
|
|
394
395
|
}
|
|
395
396
|
|
|
397
|
+
// ../blocks/src/system/runtime/nodes/event-registration/ticketSelectionLines.ts
|
|
398
|
+
function normalizeTicketSelectionLines(lines) {
|
|
399
|
+
const quantitiesByTicketType = /* @__PURE__ */ new Map();
|
|
400
|
+
for (const line of lines) {
|
|
401
|
+
const quantity = Math.floor(line.quantity);
|
|
402
|
+
if (quantity <= 0) continue;
|
|
403
|
+
const key = line.ticketTypeId ?? null;
|
|
404
|
+
quantitiesByTicketType.set(key, (quantitiesByTicketType.get(key) ?? 0) + quantity);
|
|
405
|
+
}
|
|
406
|
+
return [...quantitiesByTicketType.entries()].map(([ticketTypeId, quantity]) => ({
|
|
407
|
+
ticketTypeId,
|
|
408
|
+
quantity
|
|
409
|
+
}));
|
|
410
|
+
}
|
|
411
|
+
function getTicketSelectionTotal(lines) {
|
|
412
|
+
return normalizeTicketSelectionLines(lines).reduce((total, line) => total + line.quantity, 0);
|
|
413
|
+
}
|
|
414
|
+
function getTicketLineQuantity(lines, ticketTypeId) {
|
|
415
|
+
return normalizeTicketSelectionLines(lines).find((line) => line.ticketTypeId === ticketTypeId)?.quantity ?? 0;
|
|
416
|
+
}
|
|
417
|
+
function getSingleSelectedTicketTypeId(lines) {
|
|
418
|
+
const normalized = normalizeTicketSelectionLines(lines);
|
|
419
|
+
return normalized.length === 1 ? normalized[0]?.ticketTypeId ?? null : null;
|
|
420
|
+
}
|
|
421
|
+
function setTicketLineQuantity(input) {
|
|
422
|
+
const nextQuantity = Math.max(0, Math.floor(input.quantity));
|
|
423
|
+
const normalized = normalizeTicketSelectionLines(input.lines).filter((line) => line.ticketTypeId !== input.ticketTypeId);
|
|
424
|
+
if (nextQuantity <= 0) {
|
|
425
|
+
return normalized;
|
|
426
|
+
}
|
|
427
|
+
return [
|
|
428
|
+
...normalized,
|
|
429
|
+
{
|
|
430
|
+
ticketTypeId: input.ticketTypeId,
|
|
431
|
+
quantity: nextQuantity
|
|
432
|
+
}
|
|
433
|
+
];
|
|
434
|
+
}
|
|
435
|
+
function getTicketTypeLineMax(input) {
|
|
436
|
+
const otherSelectedQuantity = input.totalSelectedQuantity - input.currentQuantity;
|
|
437
|
+
const maxByBlock = input.maxTickets - otherSelectedQuantity;
|
|
438
|
+
const maxByEvent = input.availableSpots == null ? input.maxTickets : input.availableSpots - otherSelectedQuantity;
|
|
439
|
+
const maxByTicketType = input.ticketTypeRemainingCapacity ?? input.maxTickets;
|
|
440
|
+
return Math.max(0, Math.min(maxByBlock, maxByEvent, maxByTicketType));
|
|
441
|
+
}
|
|
442
|
+
function calculateTicketSelectionSubtotal(input) {
|
|
443
|
+
return normalizeTicketSelectionLines(input.lines).reduce((subtotal, line) => {
|
|
444
|
+
const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
|
|
445
|
+
const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
|
|
446
|
+
return subtotal + Math.max(0, unitPriceCents) * line.quantity;
|
|
447
|
+
}, 0);
|
|
448
|
+
}
|
|
449
|
+
function buildTicketSelectionSummaryLines(input) {
|
|
450
|
+
return normalizeTicketSelectionLines(input.lines).map((line) => {
|
|
451
|
+
const ticketType = line.ticketTypeId ? input.ticketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null : null;
|
|
452
|
+
const unitPriceCents = ticketType?.priceAmount ?? input.fallbackUnitPriceCents;
|
|
453
|
+
return {
|
|
454
|
+
ticketTypeId: line.ticketTypeId,
|
|
455
|
+
label: ticketType?.name ?? input.fallbackLabel,
|
|
456
|
+
quantity: line.quantity,
|
|
457
|
+
unitPriceCents,
|
|
458
|
+
subtotalCents: Math.max(0, unitPriceCents) * line.quantity
|
|
459
|
+
};
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
396
463
|
// ../blocks/src/system/runtime/nodes/event-registration/hooks.state.ts
|
|
397
464
|
var initialEligibilityLookupState = {
|
|
398
465
|
tag: "idle",
|
|
@@ -499,6 +566,7 @@ function usePortalAuth() {
|
|
|
499
566
|
}
|
|
500
567
|
function useEligibility(params) {
|
|
501
568
|
const api = useBlockApi();
|
|
569
|
+
const ticketSelectionsKey = JSON.stringify(normalizeTicketSelectionLines(params.ticketSelections));
|
|
502
570
|
const [state, dispatch] = useReducer(
|
|
503
571
|
eligibilityLookupReducer,
|
|
504
572
|
initialEligibilityLookupState
|
|
@@ -512,7 +580,8 @@ function useEligibility(params) {
|
|
|
512
580
|
dispatch({ type: "reset" });
|
|
513
581
|
return;
|
|
514
582
|
}
|
|
515
|
-
|
|
583
|
+
const ticketSelections = JSON.parse(ticketSelectionsKey);
|
|
584
|
+
if (!params.occurrenceId || !params.email.trim() || ticketSelections.length === 0) {
|
|
516
585
|
requestIdRef.current += 1;
|
|
517
586
|
dispatch({ type: "reset" });
|
|
518
587
|
return;
|
|
@@ -524,10 +593,9 @@ function useEligibility(params) {
|
|
|
524
593
|
const result = await api.checkEligibility({
|
|
525
594
|
occurrenceId: params.occurrenceId,
|
|
526
595
|
attendanceMode: params.attendanceMode ?? void 0,
|
|
527
|
-
|
|
596
|
+
ticketSelections,
|
|
528
597
|
selectedSlidingAmount: params.selectedSlidingAmount ?? void 0,
|
|
529
|
-
email: params.email.trim().toLowerCase()
|
|
530
|
-
ticketsCount: params.ticketsCount
|
|
598
|
+
email: params.email.trim().toLowerCase()
|
|
531
599
|
});
|
|
532
600
|
if (cancelled || requestIdRef.current !== requestId) return;
|
|
533
601
|
dispatch({
|
|
@@ -546,7 +614,15 @@ function useEligibility(params) {
|
|
|
546
614
|
return () => {
|
|
547
615
|
cancelled = true;
|
|
548
616
|
};
|
|
549
|
-
}, [
|
|
617
|
+
}, [
|
|
618
|
+
api,
|
|
619
|
+
params.enabled,
|
|
620
|
+
params.occurrenceId,
|
|
621
|
+
params.attendanceMode,
|
|
622
|
+
ticketSelectionsKey,
|
|
623
|
+
params.selectedSlidingAmount,
|
|
624
|
+
params.email
|
|
625
|
+
]);
|
|
550
626
|
return {
|
|
551
627
|
state,
|
|
552
628
|
eligibility: state.eligibility,
|
|
@@ -622,9 +698,15 @@ function savePendingRegistration(siteId, occurrenceId, data) {
|
|
|
622
698
|
}
|
|
623
699
|
try {
|
|
624
700
|
const key = getStorageKey(siteId, occurrenceId);
|
|
701
|
+
const ticketSelections = normalizeTicketSelectionLines(data.ticketSelections);
|
|
702
|
+
if (ticketSelections.length === 0) {
|
|
703
|
+
console.warn("[sessionStorage] No ticket selections to save, skipping registration state");
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
625
706
|
const entry = {
|
|
626
707
|
...data,
|
|
627
|
-
|
|
708
|
+
ticketSelections,
|
|
709
|
+
version: 4,
|
|
628
710
|
timestamp: Date.now()
|
|
629
711
|
};
|
|
630
712
|
sessionStorage.setItem(key, JSON.stringify(entry));
|
|
@@ -670,8 +752,8 @@ function parseAndValidateEntry(stored, key) {
|
|
|
670
752
|
return null;
|
|
671
753
|
}
|
|
672
754
|
const version = raw.version;
|
|
673
|
-
if (version !==
|
|
674
|
-
console.warn("[sessionStorage]
|
|
755
|
+
if (version !== 4) {
|
|
756
|
+
console.warn("[sessionStorage] Outdated version, ignoring entry");
|
|
675
757
|
sessionStorage.removeItem(key);
|
|
676
758
|
return null;
|
|
677
759
|
}
|
|
@@ -687,34 +769,12 @@ function parseAndValidateEntry(stored, key) {
|
|
|
687
769
|
sessionStorage.removeItem(key);
|
|
688
770
|
return null;
|
|
689
771
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
attendeeId: legacy.attendeeId,
|
|
695
|
-
formData: legacy.formData,
|
|
696
|
-
ticketsCount: legacy.ticketsCount,
|
|
697
|
-
selectedEventId: legacy.selectedEventId,
|
|
698
|
-
selectedAttendanceMode: null,
|
|
699
|
-
selectedTicketTypeId: null,
|
|
700
|
-
paymentSelection: { method: legacy.paymentMethod },
|
|
701
|
-
timestamp: legacy.timestamp
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
if (entry.version === 2) {
|
|
705
|
-
return {
|
|
706
|
-
version: 3,
|
|
707
|
-
attendeeId: entry.attendeeId,
|
|
708
|
-
formData: entry.formData,
|
|
709
|
-
ticketsCount: entry.ticketsCount,
|
|
710
|
-
selectedEventId: entry.selectedEventId,
|
|
711
|
-
selectedAttendanceMode: null,
|
|
712
|
-
selectedTicketTypeId: null,
|
|
713
|
-
paymentSelection: entry.paymentSelection,
|
|
714
|
-
timestamp: entry.timestamp
|
|
715
|
-
};
|
|
772
|
+
const ticketSelections = normalizeTicketSelectionLines(entry.ticketSelections);
|
|
773
|
+
if (ticketSelections.length === 0 || getTicketSelectionTotal(ticketSelections) <= 0) {
|
|
774
|
+
sessionStorage.removeItem(key);
|
|
775
|
+
return null;
|
|
716
776
|
}
|
|
717
|
-
return entry;
|
|
777
|
+
return { ...entry, ticketSelections };
|
|
718
778
|
} catch {
|
|
719
779
|
console.warn("[sessionStorage] Failed to parse entry, removing");
|
|
720
780
|
sessionStorage.removeItem(key);
|
|
@@ -746,8 +806,9 @@ function cleanupStaleRegistrations() {
|
|
|
746
806
|
const stored = sessionStorage.getItem(key);
|
|
747
807
|
if (!stored) continue;
|
|
748
808
|
const entry = JSON.parse(stored);
|
|
749
|
-
const
|
|
750
|
-
|
|
809
|
+
const timestamp = typeof entry.timestamp === "number" ? entry.timestamp : NaN;
|
|
810
|
+
const age = Date.now() - timestamp;
|
|
811
|
+
if (!Number.isFinite(timestamp) || age > STALE_THRESHOLD_MS) {
|
|
751
812
|
keysToRemove.push(key);
|
|
752
813
|
}
|
|
753
814
|
} catch {
|
|
@@ -835,14 +896,16 @@ function getEventAttendanceModeLabel(mode) {
|
|
|
835
896
|
}
|
|
836
897
|
}
|
|
837
898
|
function TicketCounter(props) {
|
|
838
|
-
const { ticketsCount, maxAllowed, onTicketsChange } = props;
|
|
899
|
+
const { ticketsCount, maxAllowed, label, onTicketsChange } = props;
|
|
900
|
+
const minAllowed = props.minAllowed ?? 1;
|
|
839
901
|
return /* @__PURE__ */ jsxs("div", { className: "er-row er-counter", children: [
|
|
840
902
|
/* @__PURE__ */ jsx(
|
|
841
903
|
"button",
|
|
842
904
|
{
|
|
843
905
|
type: "button",
|
|
844
|
-
|
|
845
|
-
|
|
906
|
+
"aria-label": `Decrease ${label}`,
|
|
907
|
+
onClick: () => onTicketsChange(Math.max(minAllowed, ticketsCount - 1)),
|
|
908
|
+
disabled: ticketsCount <= minAllowed,
|
|
846
909
|
className: "er-counter-btn",
|
|
847
910
|
children: "-"
|
|
848
911
|
}
|
|
@@ -852,6 +915,7 @@ function TicketCounter(props) {
|
|
|
852
915
|
"button",
|
|
853
916
|
{
|
|
854
917
|
type: "button",
|
|
918
|
+
"aria-label": `Increase ${label}`,
|
|
855
919
|
onClick: () => onTicketsChange(Math.min(maxAllowed, ticketsCount + 1)),
|
|
856
920
|
disabled: ticketsCount >= maxAllowed,
|
|
857
921
|
className: "er-counter-btn",
|
|
@@ -904,14 +968,86 @@ function SlidingScaleAmountField(props) {
|
|
|
904
968
|
props.message ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: props.message }) : null
|
|
905
969
|
] });
|
|
906
970
|
}
|
|
907
|
-
function
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
971
|
+
function TicketTypeQuantityRows(props) {
|
|
972
|
+
const totalSelectedQuantity = getTicketSelectionTotal(props.ticketSelections);
|
|
973
|
+
const selectedTicketTypes = props.ticketTypes.filter(
|
|
974
|
+
(ticketType) => getTicketLineQuantity(props.ticketSelections, ticketType.id) > 0
|
|
975
|
+
);
|
|
976
|
+
return /* @__PURE__ */ jsxs("div", { className: "er-ticket-lines", children: [
|
|
977
|
+
/* @__PURE__ */ jsx("div", { className: "er-ticket-line-list", role: "list", "aria-label": "Tickets", children: props.ticketTypes.map((ticketType) => {
|
|
978
|
+
const quantity = getTicketLineQuantity(props.ticketSelections, ticketType.id);
|
|
979
|
+
const disabled = ticketType.availability.kind === "unavailable";
|
|
980
|
+
const availabilityLabel = getTicketTypeAvailabilityLabel(ticketType);
|
|
981
|
+
const priceLabel = ticketType.priceAmount > 0 ? formatPrice(ticketType.priceAmount, props.currency) : "Free";
|
|
982
|
+
const maxAllowed = disabled ? 0 : getTicketTypeLineMax({
|
|
983
|
+
currentQuantity: quantity,
|
|
984
|
+
totalSelectedQuantity,
|
|
985
|
+
maxTickets: props.maxTickets,
|
|
986
|
+
availableSpots: props.availableSpots,
|
|
987
|
+
ticketTypeRemainingCapacity: ticketType.availability.remainingCapacity
|
|
988
|
+
});
|
|
989
|
+
return /* @__PURE__ */ jsxs(
|
|
990
|
+
"div",
|
|
991
|
+
{
|
|
992
|
+
className: `er-ticket-line${disabled ? " er-ticket-line--disabled" : ""}`,
|
|
993
|
+
role: "listitem",
|
|
994
|
+
children: [
|
|
995
|
+
/* @__PURE__ */ jsxs("div", { className: "er-ticket-line-main", children: [
|
|
996
|
+
/* @__PURE__ */ jsxs("div", { className: "er-ticket-line-heading", children: [
|
|
997
|
+
/* @__PURE__ */ jsx("span", { className: "er-ticket-line-name", children: ticketType.name }),
|
|
998
|
+
/* @__PURE__ */ jsx("span", { className: "er-ticket-line-price", children: priceLabel })
|
|
999
|
+
] }),
|
|
1000
|
+
ticketType.description ? /* @__PURE__ */ jsx("p", { className: "er-ticket-line-detail", children: ticketType.description }) : null,
|
|
1001
|
+
availabilityLabel ? /* @__PURE__ */ jsx("p", { className: "er-ticket-line-detail", children: availabilityLabel }) : ticketType.availability.remainingCapacity !== null ? /* @__PURE__ */ jsxs("p", { className: "er-ticket-line-detail", children: [
|
|
1002
|
+
ticketType.availability.remainingCapacity,
|
|
1003
|
+
" remaining for this ticket type"
|
|
1004
|
+
] }) : null
|
|
1005
|
+
] }),
|
|
1006
|
+
/* @__PURE__ */ jsx(
|
|
1007
|
+
TicketCounter,
|
|
1008
|
+
{
|
|
1009
|
+
ticketsCount: quantity,
|
|
1010
|
+
minAllowed: 0,
|
|
1011
|
+
maxAllowed,
|
|
1012
|
+
label: ticketType.name,
|
|
1013
|
+
onTicketsChange: (nextQuantity) => {
|
|
1014
|
+
props.onTicketSelectionsChange?.(setTicketLineQuantity({
|
|
1015
|
+
lines: props.ticketSelections,
|
|
1016
|
+
ticketTypeId: ticketType.id,
|
|
1017
|
+
quantity: nextQuantity
|
|
1018
|
+
}));
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
)
|
|
1022
|
+
]
|
|
1023
|
+
},
|
|
1024
|
+
ticketType.id
|
|
1025
|
+
);
|
|
1026
|
+
}) }),
|
|
1027
|
+
/* @__PURE__ */ jsx(
|
|
1028
|
+
TicketCounterLimit,
|
|
1029
|
+
{
|
|
1030
|
+
maximumLabel: `${props.maxTickets} tickets maximum`,
|
|
1031
|
+
availabilityLabel: props.availableSpots != null ? `${props.availableSpots} spots available` : null
|
|
1032
|
+
}
|
|
1033
|
+
),
|
|
1034
|
+
selectedTicketTypes.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "er-ticket-line-summary", "aria-live": "polite", children: [
|
|
1035
|
+
/* @__PURE__ */ jsxs("div", { className: "er-ticket-line-summary-title", children: [
|
|
1036
|
+
totalSelectedQuantity,
|
|
1037
|
+
" ticket",
|
|
1038
|
+
totalSelectedQuantity === 1 ? "" : "s",
|
|
1039
|
+
" selected"
|
|
1040
|
+
] }),
|
|
1041
|
+
/* @__PURE__ */ jsx("ul", { className: "er-ticket-line-summary-list", children: selectedTicketTypes.map((ticketType) => {
|
|
1042
|
+
const quantity = getTicketLineQuantity(props.ticketSelections, ticketType.id);
|
|
1043
|
+
return /* @__PURE__ */ jsxs("li", { children: [
|
|
1044
|
+
quantity,
|
|
1045
|
+
" x ",
|
|
1046
|
+
ticketType.name
|
|
1047
|
+
] }, ticketType.id);
|
|
1048
|
+
}) })
|
|
1049
|
+
] }) : props.hasAvailableTicketTypes ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "Choose at least one ticket to continue." }) : /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." })
|
|
1050
|
+
] });
|
|
915
1051
|
}
|
|
916
1052
|
function getAttendanceModeDetail(attendanceMode) {
|
|
917
1053
|
if (attendanceMode.availableSpots === null) {
|
|
@@ -929,6 +1065,7 @@ function AttendanceModeTiles(props) {
|
|
|
929
1065
|
"button",
|
|
930
1066
|
{
|
|
931
1067
|
type: "button",
|
|
1068
|
+
"aria-pressed": isSelected,
|
|
932
1069
|
className: `er-payment-tile${isSelected ? " er-payment-tile--selected" : ""}`,
|
|
933
1070
|
onClick: () => props.onAttendanceModeChange?.(attendanceMode.mode),
|
|
934
1071
|
children: [
|
|
@@ -965,8 +1102,9 @@ var TicketSelectionStep = ({
|
|
|
965
1102
|
onAttendanceModeChange,
|
|
966
1103
|
ticketsCount,
|
|
967
1104
|
maxTickets,
|
|
968
|
-
|
|
969
|
-
|
|
1105
|
+
visibleTicketTypes: visibleTicketTypesOverride,
|
|
1106
|
+
ticketSelections = [],
|
|
1107
|
+
onTicketSelectionsChange,
|
|
970
1108
|
slidingScale = null,
|
|
971
1109
|
selectedSlidingAmountInput = "",
|
|
972
1110
|
slidingScaleSelectionMessage = null,
|
|
@@ -984,28 +1122,22 @@ var TicketSelectionStep = ({
|
|
|
984
1122
|
const eventPricingMode = eventPricing ? publicEventPricingMode(eventPricing) : void 0;
|
|
985
1123
|
const eventPricingCurrency = eventPricing ? publicEventPricingCurrency(eventPricing) : null;
|
|
986
1124
|
const usesTicketTypes = eventPricingMode === "ticket_types" && !canJoinWaitlist;
|
|
987
|
-
const visibleTicketTypes = usesTicketTypes ? getVisibleTicketTypes({
|
|
1125
|
+
const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
|
|
988
1126
|
event,
|
|
989
1127
|
eligibility: null,
|
|
990
1128
|
selectedAttendanceMode
|
|
991
1129
|
}) : [];
|
|
992
|
-
const selectedTicketType = usesTicketTypes ? visibleTicketTypes.find((ticketType) => ticketType.id === selectedTicketTypeId) ?? null : null;
|
|
993
1130
|
const implicitTicketType = usesTicketTypes ? getImplicitSingleAvailableTicketType(visibleTicketTypes) : null;
|
|
994
|
-
const
|
|
995
|
-
const
|
|
996
|
-
const
|
|
997
|
-
const noSellableTicketTypes = usesTicketTypes && (visibleTicketTypes.length === 0 || visibleTicketTypes.every((ticketType) => ticketType.availability.kind === "unavailable"));
|
|
1131
|
+
const noVisibleTicketTypes = usesTicketTypes && visibleTicketTypes.length === 0;
|
|
1132
|
+
const hasAvailableTicketTypes = usesTicketTypes && visibleTicketTypes.some((ticketType) => ticketType.availability.kind === "available");
|
|
1133
|
+
const aggregateRemainingCapacity = implicitTicketType?.availability.remainingCapacity ?? null;
|
|
998
1134
|
const maxAllowed = getMaxAllowedTicketCount({
|
|
999
1135
|
canJoinWaitlist,
|
|
1000
1136
|
usesTicketTypes,
|
|
1001
1137
|
maxTickets,
|
|
1002
1138
|
availableSpots,
|
|
1003
|
-
selectedTicketTypeRemainingCapacity:
|
|
1004
|
-
hasSelectedTicketType:
|
|
1005
|
-
});
|
|
1006
|
-
const selectedTicketTypeAvailabilityLabel = getTicketTypeCounterAvailabilityLabel({
|
|
1007
|
-
selectedRemainingCapacity,
|
|
1008
|
-
eventAvailableSpots: event?.availableSpots
|
|
1139
|
+
selectedTicketTypeRemainingCapacity: aggregateRemainingCapacity,
|
|
1140
|
+
hasSelectedTicketType: implicitTicketType !== null
|
|
1009
1141
|
});
|
|
1010
1142
|
const eventAvailabilityLabel = !canJoinWaitlist && event?.availableSpots != null ? `${event.availableSpots} spots available` : null;
|
|
1011
1143
|
if (deliveryMode === "hybrid" && !selectedAttendanceMode) {
|
|
@@ -1022,7 +1154,7 @@ var TicketSelectionStep = ({
|
|
|
1022
1154
|
/* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "Choose whether you want to attend in person or online." })
|
|
1023
1155
|
] });
|
|
1024
1156
|
}
|
|
1025
|
-
if (isSoldOut && !canJoinWaitlist
|
|
1157
|
+
if (isSoldOut && !canJoinWaitlist) {
|
|
1026
1158
|
return /* @__PURE__ */ jsxs("div", { className: "er-stack", children: [
|
|
1027
1159
|
/* @__PURE__ */ jsx("h3", { className: "er-title", children: "Sold Out" }),
|
|
1028
1160
|
/* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "Sorry you missed out! This event is fully booked." })
|
|
@@ -1040,52 +1172,21 @@ var TicketSelectionStep = ({
|
|
|
1040
1172
|
}
|
|
1041
1173
|
)
|
|
1042
1174
|
] }) : null,
|
|
1043
|
-
usesTicketTypes ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
children: [
|
|
1059
|
-
/* @__PURE__ */ jsx("div", { className: "er-payment-tile-label", children: ticketType.name }),
|
|
1060
|
-
/* @__PURE__ */ jsx("div", { className: "er-payment-tile-detail", children: priceLabel }),
|
|
1061
|
-
ticketType.description ? /* @__PURE__ */ jsx("div", { className: "er-payment-tile-detail", children: ticketType.description }) : null,
|
|
1062
|
-
availabilityLabel ? /* @__PURE__ */ jsx("div", { className: "er-payment-tile-detail", children: availabilityLabel }) : null
|
|
1063
|
-
]
|
|
1064
|
-
}
|
|
1065
|
-
) }, ticketType.id);
|
|
1066
|
-
}) })
|
|
1067
|
-
] }) : null,
|
|
1068
|
-
noSellableTicketTypes ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : !effectiveSelectedTicketType ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "Select one ticket type to continue." }) : effectiveSelectedTicketType.availability.kind === "unavailable" ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: getTicketTypeAvailabilityLabel(effectiveSelectedTicketType) ?? "This ticket type is unavailable." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1069
|
-
/* @__PURE__ */ jsx("h3", { className: "er-title", children: "How many tickets?" }),
|
|
1070
|
-
/* @__PURE__ */ jsxs("div", { className: "er-ticket-counter-group", children: [
|
|
1071
|
-
/* @__PURE__ */ jsx(
|
|
1072
|
-
TicketCounter,
|
|
1073
|
-
{
|
|
1074
|
-
ticketsCount,
|
|
1075
|
-
maxAllowed,
|
|
1076
|
-
onTicketsChange
|
|
1077
|
-
}
|
|
1078
|
-
),
|
|
1079
|
-
/* @__PURE__ */ jsx(
|
|
1080
|
-
TicketCounterLimit,
|
|
1081
|
-
{
|
|
1082
|
-
maximumLabel: `${maxAllowed} tickets maximum`,
|
|
1083
|
-
availabilityLabel: selectedTicketTypeAvailabilityLabel
|
|
1084
|
-
}
|
|
1085
|
-
)
|
|
1086
|
-
] })
|
|
1087
|
-
] })
|
|
1088
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1175
|
+
usesTicketTypes ? /* @__PURE__ */ jsx(Fragment, { children: noVisibleTicketTypes ? /* @__PURE__ */ jsx("p", { className: "er-text er-text--muted", children: "No ticket types are currently available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1176
|
+
/* @__PURE__ */ jsx("h3", { className: "er-title", children: "Choose tickets" }),
|
|
1177
|
+
/* @__PURE__ */ jsx(
|
|
1178
|
+
TicketTypeQuantityRows,
|
|
1179
|
+
{
|
|
1180
|
+
ticketTypes: visibleTicketTypes,
|
|
1181
|
+
ticketSelections,
|
|
1182
|
+
maxTickets,
|
|
1183
|
+
availableSpots,
|
|
1184
|
+
currency: eventPricingCurrency ?? DEFAULT_EVENT_CURRENCY,
|
|
1185
|
+
hasAvailableTicketTypes,
|
|
1186
|
+
onTicketSelectionsChange
|
|
1187
|
+
}
|
|
1188
|
+
)
|
|
1189
|
+
] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1089
1190
|
slidingScale ? /* @__PURE__ */ jsx(
|
|
1090
1191
|
SlidingScaleAmountField,
|
|
1091
1192
|
{
|
|
@@ -1103,6 +1204,7 @@ var TicketSelectionStep = ({
|
|
|
1103
1204
|
{
|
|
1104
1205
|
ticketsCount,
|
|
1105
1206
|
maxAllowed,
|
|
1207
|
+
label: canJoinWaitlist ? "waitlist spots" : "tickets",
|
|
1106
1208
|
onTicketsChange
|
|
1107
1209
|
}
|
|
1108
1210
|
),
|
|
@@ -1546,7 +1648,7 @@ var PaymentSelectionStep = ({
|
|
|
1546
1648
|
}) => {
|
|
1547
1649
|
const occurrenceId = occurrenceContext?.id ?? event?.registrationOccurrenceId;
|
|
1548
1650
|
const selectedMethod = selectedSelection.method;
|
|
1549
|
-
const totalPrice = eligibility?.price
|
|
1651
|
+
const totalPrice = eligibility?.price ?? 0;
|
|
1550
1652
|
const canShowDirectPaymentOptions = Boolean(
|
|
1551
1653
|
eligibility?.eligible && eligibility.canPayDirectly && eligibility.price
|
|
1552
1654
|
);
|
|
@@ -1946,8 +2048,9 @@ function EventRegistrationWizardContent(props) {
|
|
|
1946
2048
|
onAttendanceModeChange: wizard.setSelectedAttendanceMode,
|
|
1947
2049
|
ticketsCount: wizard.ticketsCount,
|
|
1948
2050
|
maxTickets: wizard.maxTicketsNum,
|
|
1949
|
-
|
|
1950
|
-
|
|
2051
|
+
visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
|
|
2052
|
+
ticketSelections: wizard.selectedTicketLines,
|
|
2053
|
+
onTicketSelectionsChange: wizard.setSelectedTicketLines,
|
|
1951
2054
|
slidingScale: wizard.selectedEventSlidingScale,
|
|
1952
2055
|
selectedSlidingAmountInput: wizard.selectedSlidingAmountInput,
|
|
1953
2056
|
slidingScaleSelectionMessage: wizard.slidingScaleSelectionMessage,
|
|
@@ -2055,9 +2158,9 @@ function EventRegistrationWizardActions(props) {
|
|
|
2055
2158
|
const isWaitingForEligibility = wizard.portalAuthState === "authenticated" && wizard.eligibilityLoading;
|
|
2056
2159
|
const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
|
|
2057
2160
|
const hasExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistration !== null;
|
|
2058
|
-
const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.
|
|
2161
|
+
const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
|
|
2059
2162
|
const isContinueDisabled = isWaitingForEligibility || isCheckingExistingRegistration || hasExistingRegistration || isSoldOutWithoutWaitlist || ticketTypeSelectionBlocked;
|
|
2060
|
-
const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket
|
|
2163
|
+
const continueLabel = isCheckingExistingRegistration ? "Checking registration..." : hasExistingRegistration ? "Already registered" : isSoldOutWithoutWaitlist ? "Sold out" : ticketTypeSelectionBlocked ? "Choose a ticket" : "Continue";
|
|
2061
2164
|
return /* @__PURE__ */ jsxs("div", { className: "er-actions", children: [
|
|
2062
2165
|
!wizard.hasPreSelectedContext && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => wizard.setStep("select-event"), className: "er-back-btn", children: "\u2190 Back" }),
|
|
2063
2166
|
/* @__PURE__ */ jsx(
|
|
@@ -2145,13 +2248,17 @@ function EventRegistrationSummaryBar(props) {
|
|
|
2145
2248
|
const summaryTimeZone = wizard.occurrenceContext?.timeZone ?? summaryEvent?.timeZone ?? null;
|
|
2146
2249
|
const occurrenceOverrideTitle = wizard.occurrenceContext?.overrides?.title;
|
|
2147
2250
|
const summaryTitle = occurrenceOverrideTitle ?? summaryEvent?.title ?? "";
|
|
2148
|
-
const summaryPrice = wizard.selectedTicketType?.priceAmount ?? wizard.eligibility?.price ?? (wizard.selectedEventSlidingScale ? wizard.selectedSlidingAmount : null) ?? (summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0;
|
|
2149
2251
|
const summaryCurrency = (summaryEvent ? publicEventPricingCurrency(summaryEvent.pricing) : null) ?? DEFAULT_EVENT_CURRENCY;
|
|
2150
2252
|
const teamMemberNames = (summaryEvent?.teamMembers ?? []).map((teamMember) => teamMember.name).filter(Boolean);
|
|
2151
|
-
const
|
|
2253
|
+
const fallbackSubtotalCents = Math.max(
|
|
2254
|
+
0,
|
|
2255
|
+
((summaryEvent ? publicEventScalarPrice(summaryEvent.pricing) : null) ?? 0) * wizard.ticketsCount
|
|
2256
|
+
);
|
|
2257
|
+
const subtotalCents = Math.max(0, wizard.ticketSelectionSubtotalCents ?? fallbackSubtotalCents);
|
|
2152
2258
|
const autoAppliedDiscount = wizard.discountCode.trim().length > 0 ? null : wizard.autoAppliedDiscount;
|
|
2153
2259
|
const autoAppliedDiscountCents = Math.max(0, autoAppliedDiscount?.computedAmountCents ?? 0);
|
|
2154
2260
|
const discountedTotalCents = Math.max(0, subtotalCents - autoAppliedDiscountCents);
|
|
2261
|
+
const selectedLineSummary = (wizard.ticketSelectionSummaryLines ?? []).filter((line) => line.ticketTypeId !== null).map((line) => `${line.quantity} x ${line.label}`).join(", ");
|
|
2155
2262
|
const selectedDirectPaymentOption = getSelectedDirectPaymentOption({
|
|
2156
2263
|
wizard,
|
|
2157
2264
|
totalCents: discountedTotalCents,
|
|
@@ -2188,9 +2295,9 @@ function EventRegistrationSummaryBar(props) {
|
|
|
2188
2295
|
/* @__PURE__ */ jsx("h4", { className: "er-summary-bar-event", children: summaryTitle }),
|
|
2189
2296
|
/* @__PURE__ */ jsxs("span", { className: "er-summary-bar-meta", children: [
|
|
2190
2297
|
summaryDate && formatEventDateTime(summaryDate, { timeZone: summaryTimeZone }),
|
|
2191
|
-
|
|
2298
|
+
selectedLineSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2192
2299
|
" \xB7 ",
|
|
2193
|
-
|
|
2300
|
+
selectedLineSummary
|
|
2194
2301
|
] }) : null,
|
|
2195
2302
|
wizard.step !== "select-event" && wizard.step !== "select-tickets" && wizard.ticketsCount > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2196
2303
|
" \xB7 ",
|
|
@@ -2204,8 +2311,8 @@ function EventRegistrationSummaryBar(props) {
|
|
|
2204
2311
|
teamMemberNames.join(", ")
|
|
2205
2312
|
] })
|
|
2206
2313
|
] }),
|
|
2207
|
-
|
|
2208
|
-
/* @__PURE__ */ jsx("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(
|
|
2314
|
+
subtotalCents > 0 && /* @__PURE__ */ jsx("div", { className: "er-summary-bar-pricing", children: productMethod ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2315
|
+
/* @__PURE__ */ jsx("span", { className: "er-summary-bar-price er-summary-bar-price--struck", children: formatPrice(subtotalCents, summaryCurrency) }),
|
|
2209
2316
|
/* @__PURE__ */ jsx("div", { className: "er-summary-bar-included", children: wizard.paymentSelection.method === "pass" || wizard.paymentSelection.method === "pass_bundle" ? "1 pass credit" : "Included in membership" })
|
|
2210
2317
|
] }) : flexibleBalanceSummary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2211
2318
|
flexibleBalanceSummary.total ? /* @__PURE__ */ jsxs("div", { className: "er-summary-bar-product-detail", children: [
|
|
@@ -2295,7 +2402,7 @@ function useEventRegistrationStripeReturn(options) {
|
|
|
2295
2402
|
setRegistrationResult,
|
|
2296
2403
|
setSelectedEvent,
|
|
2297
2404
|
setSelectedAttendanceMode,
|
|
2298
|
-
|
|
2405
|
+
setTicketSelections,
|
|
2299
2406
|
setStep,
|
|
2300
2407
|
setTicketsCount,
|
|
2301
2408
|
step
|
|
@@ -2314,13 +2421,13 @@ function useEventRegistrationStripeReturn(options) {
|
|
|
2314
2421
|
const pending = getPendingRegistration(siteId, occurrenceId || void 0);
|
|
2315
2422
|
if (!pending) return;
|
|
2316
2423
|
setFormData(pending.formData);
|
|
2317
|
-
|
|
2424
|
+
setTicketSelections(pending.ticketSelections);
|
|
2425
|
+
setTicketsCount(getTicketSelectionTotal(pending.ticketSelections));
|
|
2318
2426
|
if (pending.selectedEventId) {
|
|
2319
2427
|
const event = events.find((e) => e.publicEventId === pending.selectedEventId) ?? null;
|
|
2320
2428
|
if (event) setSelectedEvent(event);
|
|
2321
2429
|
}
|
|
2322
2430
|
setSelectedAttendanceMode(pending.selectedAttendanceMode ?? null);
|
|
2323
|
-
setSelectedTicketTypeId(pending.selectedTicketTypeId ?? null);
|
|
2324
2431
|
setPaymentSelection(pending.paymentSelection);
|
|
2325
2432
|
if (registrationStatus === "cancelled") {
|
|
2326
2433
|
setStep("select-payment");
|
|
@@ -2372,6 +2479,10 @@ function useEventRegistrationSubmit(options) {
|
|
|
2372
2479
|
}
|
|
2373
2480
|
options.setStep("submitting");
|
|
2374
2481
|
try {
|
|
2482
|
+
const ticketSelections = normalizeTicketSelectionLines(options.ticketSelections);
|
|
2483
|
+
if (ticketSelections.length === 0) {
|
|
2484
|
+
throw new Error("Choose at least one ticket to continue.");
|
|
2485
|
+
}
|
|
2375
2486
|
const isBundle = method === "pass_bundle" || method === "membership_bundle";
|
|
2376
2487
|
const bundleProductId = isBundle ? passId || membershipId : void 0;
|
|
2377
2488
|
const selectionSnapshot = (() => {
|
|
@@ -2400,11 +2511,10 @@ function useEventRegistrationSubmit(options) {
|
|
|
2400
2511
|
const result = await options.api.registerForEvent({
|
|
2401
2512
|
occurrenceId: submitOccurrenceId,
|
|
2402
2513
|
attendanceMode: options.selectedAttendanceMode ?? void 0,
|
|
2403
|
-
|
|
2514
|
+
ticketSelections,
|
|
2404
2515
|
selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
|
|
2405
2516
|
email: options.formData.email.trim().toLowerCase(),
|
|
2406
2517
|
name: options.formData.name.trim(),
|
|
2407
|
-
ticketsCount: options.ticketsCount,
|
|
2408
2518
|
phone: options.formData.phone.trim() || void 0,
|
|
2409
2519
|
notes: options.formData.notes.trim() || void 0,
|
|
2410
2520
|
altchaSolution: options.altchaSolution,
|
|
@@ -2449,10 +2559,9 @@ function useEventRegistrationSubmit(options) {
|
|
|
2449
2559
|
savePendingRegistration(siteId, submitOccurrenceId, {
|
|
2450
2560
|
attendeeId: result.attendeeId,
|
|
2451
2561
|
formData: options.formData,
|
|
2452
|
-
|
|
2562
|
+
ticketSelections,
|
|
2453
2563
|
selectedEventId: options.registrationTarget?.selectedEventId ?? null,
|
|
2454
2564
|
selectedAttendanceMode: options.selectedAttendanceMode,
|
|
2455
|
-
selectedTicketTypeId: options.selectedTicketTypeId ?? null,
|
|
2456
2565
|
paymentSelection: selectionSnapshot
|
|
2457
2566
|
});
|
|
2458
2567
|
}
|
|
@@ -2564,7 +2673,6 @@ function useEventRegistrationWizard(options) {
|
|
|
2564
2673
|
createInitialRegistrationFlowState
|
|
2565
2674
|
);
|
|
2566
2675
|
const step = flowState.step;
|
|
2567
|
-
const ticketsCount = flowState.ticketsCount;
|
|
2568
2676
|
const paymentSelection = flowState.paymentSelection;
|
|
2569
2677
|
const [selectedEvent, setSelectedEvent] = useState(preSelectedEvent ?? null);
|
|
2570
2678
|
const [formData, setFormData] = useState({ name: "", email: "", phone: "", notes: "" });
|
|
@@ -2575,7 +2683,7 @@ function useEventRegistrationWizard(options) {
|
|
|
2575
2683
|
const [selectedAttendanceMode, setSelectedAttendanceMode] = useState(
|
|
2576
2684
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
2577
2685
|
);
|
|
2578
|
-
const [
|
|
2686
|
+
const [selectedTicketLines, setSelectedTicketLines] = useState([]);
|
|
2579
2687
|
const [selectedSlidingAmountInput, setSelectedSlidingAmountInput] = useState(() => {
|
|
2580
2688
|
const slidingScale = getSlidingScaleForEvent(preSelectedEvent ?? null);
|
|
2581
2689
|
return slidingScale?.suggestedAmount !== null && slidingScale?.suggestedAmount !== void 0 ? formatCentsAsCurrencyInput(slidingScale.suggestedAmount) : "";
|
|
@@ -2611,14 +2719,51 @@ function useEventRegistrationWizard(options) {
|
|
|
2611
2719
|
[options.occurrenceContext, selectedEvent]
|
|
2612
2720
|
);
|
|
2613
2721
|
const occurrenceId = registrationTarget?.occurrenceId ?? "";
|
|
2722
|
+
const currentEvent = selectedEvent ?? preSelectedEvent;
|
|
2723
|
+
const currentEventPricing = currentEvent ? resolveRuntimeEventPricing(currentEvent) : null;
|
|
2724
|
+
const currentEventUsesTicketTypes = currentEventPricing !== null && publicEventPricingMode(currentEventPricing) === "ticket_types";
|
|
2725
|
+
const selectedModeAvailability = selectedAttendanceMode ? (currentEvent?.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
|
|
2726
|
+
const currentAvailableSpots = selectedModeAvailability?.availableSpots ?? currentEvent?.availableSpots;
|
|
2727
|
+
const currentWaitlistEnabled = selectedModeAvailability?.waitlistEnabled ?? currentEvent?.waitlistEnabled ?? false;
|
|
2728
|
+
const currentCanJoinWaitlist = currentAvailableSpots === 0 && currentWaitlistEnabled === true;
|
|
2729
|
+
const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
|
|
2730
|
+
const eventTicketTypesForSelection = useMemo(
|
|
2731
|
+
() => getVisibleTicketTypes({
|
|
2732
|
+
event: currentEvent,
|
|
2733
|
+
eligibility: null,
|
|
2734
|
+
selectedAttendanceMode
|
|
2735
|
+
}),
|
|
2736
|
+
[currentEvent, selectedAttendanceMode]
|
|
2737
|
+
);
|
|
2738
|
+
const normalizedSelectedTicketLines = useMemo(
|
|
2739
|
+
() => normalizeTicketSelectionLines(selectedTicketLines),
|
|
2740
|
+
[selectedTicketLines]
|
|
2741
|
+
);
|
|
2742
|
+
const ticketTypeSelectionTotal = useMemo(
|
|
2743
|
+
() => getTicketSelectionTotal(normalizedSelectedTicketLines),
|
|
2744
|
+
[normalizedSelectedTicketLines]
|
|
2745
|
+
);
|
|
2746
|
+
const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
|
|
2747
|
+
const ticketSelections = useMemo(() => {
|
|
2748
|
+
if (waitlistClaim.claim) {
|
|
2749
|
+
return [{ ticketTypeId: null, quantity: 1 }];
|
|
2750
|
+
}
|
|
2751
|
+
if (usesTicketTypeSelections) {
|
|
2752
|
+
return normalizedSelectedTicketLines;
|
|
2753
|
+
}
|
|
2754
|
+
return [{ ticketTypeId: null, quantity: ticketsCount }];
|
|
2755
|
+
}, [normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, waitlistClaim.claim]);
|
|
2756
|
+
useEffect(() => {
|
|
2757
|
+
if (flowState.ticketsCount === ticketsCount) return;
|
|
2758
|
+
dispatchFlow({ type: "set-tickets-count", ticketsCount });
|
|
2759
|
+
}, [flowState.ticketsCount, ticketsCount]);
|
|
2614
2760
|
const eligibilityResult = useEligibility({
|
|
2615
2761
|
enabled: portalAuthState === "authenticated" || step === "enter-details" || step === "select-payment",
|
|
2616
2762
|
occurrenceId,
|
|
2617
2763
|
attendanceMode: selectedAttendanceMode,
|
|
2618
|
-
|
|
2764
|
+
ticketSelections,
|
|
2619
2765
|
selectedSlidingAmount: parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
2620
|
-
email: formData.email
|
|
2621
|
-
ticketsCount
|
|
2766
|
+
email: formData.email
|
|
2622
2767
|
});
|
|
2623
2768
|
const existingRegistrationResult = useExistingEventRegistration({
|
|
2624
2769
|
isAuthenticated: portalAuthState === "authenticated",
|
|
@@ -2724,7 +2869,7 @@ function useEventRegistrationWizard(options) {
|
|
|
2724
2869
|
setTicketsCount,
|
|
2725
2870
|
setSelectedEvent,
|
|
2726
2871
|
setSelectedAttendanceMode,
|
|
2727
|
-
|
|
2872
|
+
setTicketSelections: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
|
|
2728
2873
|
setPaymentSelection: (selection) => dispatchFlow({ type: "set-manual-payment-selection", selection }),
|
|
2729
2874
|
setPendingAttendeeId,
|
|
2730
2875
|
setStep,
|
|
@@ -2737,20 +2882,21 @@ function useEventRegistrationWizard(options) {
|
|
|
2737
2882
|
}, [selectedEvent, preSelectedEvent]);
|
|
2738
2883
|
const visibleTicketTypes = useMemo(
|
|
2739
2884
|
() => getVisibleTicketTypes({
|
|
2740
|
-
event:
|
|
2885
|
+
event: currentEvent,
|
|
2741
2886
|
eligibility,
|
|
2742
2887
|
selectedAttendanceMode
|
|
2743
2888
|
}),
|
|
2744
|
-
[
|
|
2889
|
+
[currentEvent, selectedAttendanceMode, eligibility]
|
|
2745
2890
|
);
|
|
2891
|
+
const singleSelectedTicketTypeId = getSingleSelectedTicketTypeId(normalizedSelectedTicketLines);
|
|
2746
2892
|
const selectedTicketType = useMemo(
|
|
2747
2893
|
() => findSelectedTicketType({
|
|
2748
|
-
event:
|
|
2894
|
+
event: currentEvent,
|
|
2749
2895
|
eligibility,
|
|
2750
|
-
selectedTicketTypeId,
|
|
2896
|
+
selectedTicketTypeId: singleSelectedTicketTypeId,
|
|
2751
2897
|
selectedAttendanceMode
|
|
2752
2898
|
}),
|
|
2753
|
-
[
|
|
2899
|
+
[currentEvent, eligibility, selectedAttendanceMode, singleSelectedTicketTypeId]
|
|
2754
2900
|
);
|
|
2755
2901
|
const selectedSlidingAmount = useMemo(
|
|
2756
2902
|
() => parseCurrencyInputToCents(selectedSlidingAmountInput),
|
|
@@ -2765,37 +2911,44 @@ function useEventRegistrationWizard(options) {
|
|
|
2765
2911
|
selectedAmount: selectedSlidingAmount
|
|
2766
2912
|
});
|
|
2767
2913
|
const ticketTypeSelectionRequired = useMemo(() => {
|
|
2768
|
-
const event =
|
|
2914
|
+
const event = currentEvent;
|
|
2769
2915
|
if (!event || publicEventPricingMode(resolveRuntimeEventPricing(event)) !== "ticket_types") {
|
|
2770
2916
|
return false;
|
|
2771
2917
|
}
|
|
2772
2918
|
if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) {
|
|
2773
2919
|
return false;
|
|
2774
2920
|
}
|
|
2775
|
-
const
|
|
2776
|
-
const canJoinWaitlist = (
|
|
2921
|
+
const selectedModeAvailability2 = selectedAttendanceMode ? (event.attendanceModes ?? []).find((mode) => mode.mode === selectedAttendanceMode) ?? null : null;
|
|
2922
|
+
const canJoinWaitlist = (selectedModeAvailability2?.availableSpots ?? event.availableSpots) === 0 && (selectedModeAvailability2?.waitlistEnabled ?? event.waitlistEnabled) === true;
|
|
2777
2923
|
return !canJoinWaitlist;
|
|
2778
|
-
}, [
|
|
2779
|
-
const
|
|
2780
|
-
|
|
2781
|
-
|
|
2924
|
+
}, [currentEvent, selectedAttendanceMode]);
|
|
2925
|
+
const hasValidTicketSelection = !ticketTypeSelectionRequired || normalizedSelectedTicketLines.length > 0 && normalizedSelectedTicketLines.every((line) => {
|
|
2926
|
+
if (!line.ticketTypeId) return false;
|
|
2927
|
+
const ticketType = visibleTicketTypes.find((candidate) => candidate.id === line.ticketTypeId) ?? null;
|
|
2928
|
+
return ticketType?.availability.kind === "available";
|
|
2929
|
+
});
|
|
2782
2930
|
useEffect(() => {
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
setSelectedTicketTypeId(null);
|
|
2931
|
+
if (!usesTicketTypeSelections) {
|
|
2932
|
+
if (selectedTicketLines.length > 0) {
|
|
2933
|
+
setSelectedTicketLines([]);
|
|
2787
2934
|
}
|
|
2788
2935
|
return;
|
|
2789
2936
|
}
|
|
2790
|
-
const
|
|
2791
|
-
|
|
2792
|
-
|
|
2937
|
+
const availableTicketTypes = eventTicketTypesForSelection.filter(
|
|
2938
|
+
(ticketType) => ticketType.availability.kind === "available"
|
|
2939
|
+
);
|
|
2940
|
+
const implicitTicketType = getImplicitSingleAvailableTicketType(eventTicketTypesForSelection);
|
|
2941
|
+
if (implicitTicketType && normalizedSelectedTicketLines.length === 0) {
|
|
2942
|
+
setSelectedTicketLines([{ ticketTypeId: implicitTicketType.id, quantity: 1 }]);
|
|
2793
2943
|
return;
|
|
2794
2944
|
}
|
|
2795
|
-
|
|
2796
|
-
|
|
2945
|
+
const filteredLines = normalizedSelectedTicketLines.filter(
|
|
2946
|
+
(line) => line.ticketTypeId && availableTicketTypes.some((ticketType) => ticketType.id === line.ticketTypeId)
|
|
2947
|
+
);
|
|
2948
|
+
if (filteredLines.length !== normalizedSelectedTicketLines.length) {
|
|
2949
|
+
setSelectedTicketLines(filteredLines);
|
|
2797
2950
|
}
|
|
2798
|
-
}, [
|
|
2951
|
+
}, [eventTicketTypesForSelection, normalizedSelectedTicketLines, selectedTicketLines.length, usesTicketTypeSelections]);
|
|
2799
2952
|
useEffect(() => {
|
|
2800
2953
|
if (!requireGuestDetails) {
|
|
2801
2954
|
if (guests.length > 0) setGuests([]);
|
|
@@ -2839,21 +2992,20 @@ function useEventRegistrationWizard(options) {
|
|
|
2839
2992
|
return resolveEventRequiresPayment({
|
|
2840
2993
|
eligibility,
|
|
2841
2994
|
selectedTicketType,
|
|
2842
|
-
event:
|
|
2995
|
+
event: currentEvent
|
|
2843
2996
|
});
|
|
2844
2997
|
},
|
|
2845
2998
|
[
|
|
2846
2999
|
eligibility,
|
|
2847
3000
|
selectedTicketType,
|
|
2848
|
-
|
|
2849
|
-
preSelectedEvent,
|
|
3001
|
+
currentEvent,
|
|
2850
3002
|
selectedEventSlidingScale,
|
|
2851
3003
|
selectedSlidingAmount
|
|
2852
3004
|
]
|
|
2853
3005
|
);
|
|
2854
3006
|
const handleDetailsComplete = async () => {
|
|
2855
|
-
if (ticketTypeSelectionRequired && !
|
|
2856
|
-
const message = "
|
|
3007
|
+
if (ticketTypeSelectionRequired && !hasValidTicketSelection) {
|
|
3008
|
+
const message = "Choose at least one available ticket to continue.";
|
|
2857
3009
|
setErrorMessage(message);
|
|
2858
3010
|
setStep("error");
|
|
2859
3011
|
return { ok: false, reason: "blocked", message };
|
|
@@ -2938,27 +3090,39 @@ function useEventRegistrationWizard(options) {
|
|
|
2938
3090
|
const discountContext = useMemo(
|
|
2939
3091
|
() => resolveDiscountContext({
|
|
2940
3092
|
paymentSelection,
|
|
2941
|
-
event:
|
|
3093
|
+
event: currentEvent,
|
|
2942
3094
|
eventRequiresPayment,
|
|
2943
3095
|
ticketsCount
|
|
2944
3096
|
}),
|
|
2945
|
-
[eventRequiresPayment, paymentSelection,
|
|
3097
|
+
[currentEvent, eventRequiresPayment, paymentSelection, ticketsCount]
|
|
3098
|
+
);
|
|
3099
|
+
const fallbackUnitPriceCents = useMemo(
|
|
3100
|
+
() => currentEvent ? publicEventScalarPrice(resolveRuntimeEventPricing(currentEvent)) ?? 0 : 0,
|
|
3101
|
+
[currentEvent]
|
|
3102
|
+
);
|
|
3103
|
+
const ticketSelectionSubtotalCents = useMemo(() => {
|
|
3104
|
+
if (!usesTicketTypeSelections) {
|
|
3105
|
+
return Math.max(0, eligibility?.price ?? fallbackUnitPriceCents * ticketsCount);
|
|
3106
|
+
}
|
|
3107
|
+
return calculateTicketSelectionSubtotal({
|
|
3108
|
+
lines: normalizedSelectedTicketLines,
|
|
3109
|
+
ticketTypes: visibleTicketTypes,
|
|
3110
|
+
fallbackUnitPriceCents
|
|
3111
|
+
});
|
|
3112
|
+
}, [eligibility, fallbackUnitPriceCents, normalizedSelectedTicketLines, ticketsCount, usesTicketTypeSelections, visibleTicketTypes]);
|
|
3113
|
+
const ticketSelectionSummaryLines = useMemo(
|
|
3114
|
+
() => buildTicketSelectionSummaryLines({
|
|
3115
|
+
lines: ticketSelections,
|
|
3116
|
+
ticketTypes: visibleTicketTypes,
|
|
3117
|
+
fallbackLabel: "Ticket",
|
|
3118
|
+
fallbackUnitPriceCents
|
|
3119
|
+
}),
|
|
3120
|
+
[fallbackUnitPriceCents, ticketSelections, visibleTicketTypes]
|
|
2946
3121
|
);
|
|
2947
3122
|
const discountSubtotalCents = useMemo(() => {
|
|
2948
3123
|
if (discountContext?.type !== "event") return void 0;
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
return Math.max(0, eventPriceCents * ticketsCount);
|
|
2952
|
-
}, [
|
|
2953
|
-
discountContext,
|
|
2954
|
-
selectedTicketType,
|
|
2955
|
-
eligibility,
|
|
2956
|
-
selectedEvent,
|
|
2957
|
-
preSelectedEvent,
|
|
2958
|
-
selectedEventSlidingScale,
|
|
2959
|
-
selectedSlidingAmount,
|
|
2960
|
-
ticketsCount
|
|
2961
|
-
]);
|
|
3124
|
+
return ticketSelectionSubtotalCents;
|
|
3125
|
+
}, [discountContext, ticketSelectionSubtotalCents]);
|
|
2962
3126
|
const discountUi = useDiscountCodeUi({ api, discountContext, subtotalCents: discountSubtotalCents });
|
|
2963
3127
|
const selectionMethod = paymentSelection.method;
|
|
2964
3128
|
const shouldShowDiscountToggle = discountContext !== null && discountUi.manualCodeEntryAllowed && (selectionMethod === "stripe" || selectionMethod === "pass_bundle" || selectionMethod === "membership_bundle");
|
|
@@ -2966,9 +3130,8 @@ function useEventRegistrationWizard(options) {
|
|
|
2966
3130
|
api,
|
|
2967
3131
|
registrationTarget,
|
|
2968
3132
|
selectedAttendanceMode,
|
|
2969
|
-
|
|
3133
|
+
ticketSelections,
|
|
2970
3134
|
selectedSlidingAmount,
|
|
2971
|
-
ticketsCount,
|
|
2972
3135
|
formData,
|
|
2973
3136
|
altchaSolution,
|
|
2974
3137
|
requireGuestDetails,
|
|
@@ -2989,12 +3152,12 @@ function useEventRegistrationWizard(options) {
|
|
|
2989
3152
|
setSelectedAttendanceMode(
|
|
2990
3153
|
(event.deliveryMode ?? "in_person") === "hybrid" ? null : (event.deliveryMode ?? "in_person") === "online" ? "online" : "in_person"
|
|
2991
3154
|
);
|
|
2992
|
-
|
|
3155
|
+
setSelectedTicketLines([]);
|
|
2993
3156
|
dispatchFlow({ type: "event-changed", hasPreSelectedContext: true });
|
|
2994
3157
|
};
|
|
2995
3158
|
const handleRetry = () => {
|
|
2996
3159
|
dispatchFlow({ type: "reset", hasPreSelectedContext });
|
|
2997
|
-
|
|
3160
|
+
setSelectedTicketLines([]);
|
|
2998
3161
|
setSelectedSlidingAmountInput("");
|
|
2999
3162
|
setSelectedAttendanceMode(
|
|
3000
3163
|
preSelectedEvent?.deliveryMode === "online" ? "online" : preSelectedEvent?.deliveryMode === "in_person" ? "in_person" : null
|
|
@@ -3030,17 +3193,20 @@ function useEventRegistrationWizard(options) {
|
|
|
3030
3193
|
setTicketsCount,
|
|
3031
3194
|
selectedAttendanceMode,
|
|
3032
3195
|
setSelectedAttendanceMode,
|
|
3033
|
-
|
|
3034
|
-
|
|
3196
|
+
ticketSelections,
|
|
3197
|
+
selectedTicketLines: normalizedSelectedTicketLines,
|
|
3198
|
+
setSelectedTicketLines: (lines) => setSelectedTicketLines(normalizeTicketSelectionLines(lines)),
|
|
3035
3199
|
selectedSlidingAmountInput,
|
|
3036
3200
|
setSelectedSlidingAmountInput,
|
|
3037
3201
|
selectedSlidingAmount,
|
|
3038
3202
|
selectedEventSlidingScale,
|
|
3039
3203
|
slidingScaleSelectionMessage,
|
|
3040
3204
|
selectedTicketType,
|
|
3205
|
+
ticketSelectionSummaryLines,
|
|
3206
|
+
ticketSelectionSubtotalCents,
|
|
3041
3207
|
visibleTicketTypes,
|
|
3042
3208
|
ticketTypeSelectionRequired,
|
|
3043
|
-
|
|
3209
|
+
hasValidTicketSelection,
|
|
3044
3210
|
eventRequiresPayment,
|
|
3045
3211
|
formData,
|
|
3046
3212
|
setFormData,
|