@bigz-app/booking-widget 1.5.1 → 1.5.2

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.
Files changed (38) hide show
  1. package/dist/booking-widget.js +88 -41
  2. package/dist/booking-widget.js.map +1 -1
  3. package/dist/components/UniversalBookingWidget.d.ts +3 -105
  4. package/dist/components/UniversalBookingWidget.d.ts.map +1 -1
  5. package/dist/components/events/EventInstanceSelection.d.ts +3 -1
  6. package/dist/components/events/EventInstanceSelection.d.ts.map +1 -1
  7. package/dist/components/events/EventTypeSelection.d.ts +2 -1
  8. package/dist/components/events/EventTypeSelection.d.ts.map +1 -1
  9. package/dist/components/events/NextEventsPreview.d.ts +1 -1
  10. package/dist/components/events/NextEventsPreview.d.ts.map +1 -1
  11. package/dist/components/events/SpecialsView.d.ts +1 -1
  12. package/dist/components/events/SpecialsView.d.ts.map +1 -1
  13. package/dist/components/events/types.d.ts +42 -0
  14. package/dist/components/events/types.d.ts.map +1 -0
  15. package/dist/components/upsells/UpsellCard.d.ts +1 -1
  16. package/dist/components/upsells/UpsellCard.d.ts.map +1 -1
  17. package/dist/components/upsells/UpsellsStep.d.ts +2 -44
  18. package/dist/components/upsells/UpsellsStep.d.ts.map +1 -1
  19. package/dist/components/upsells/types.d.ts +44 -0
  20. package/dist/components/upsells/types.d.ts.map +1 -0
  21. package/dist/components/voucher/VoucherPurchaseForm.d.ts +2 -15
  22. package/dist/components/voucher/VoucherPurchaseForm.d.ts.map +1 -1
  23. package/dist/components/voucher/types.d.ts +15 -0
  24. package/dist/components/voucher/types.d.ts.map +1 -0
  25. package/dist/config.d.ts +66 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/i18n/locales/es.d.ts.map +1 -1
  28. package/dist/i18n/locales/pt.d.ts.map +1 -1
  29. package/dist/i18n/locales/sv.d.ts.map +1 -1
  30. package/dist/index.cjs +88 -41
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.esm.js +88 -41
  33. package/dist/index.esm.js.map +1 -1
  34. package/dist/styles/StyleProvider.d.ts +1 -1
  35. package/dist/styles/StyleProvider.d.ts.map +1 -1
  36. package/dist/utils.d.ts +1 -1
  37. package/dist/utils.d.ts.map +1 -1
  38. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -741,6 +741,21 @@ const es = {
741
741
  "instances.bestPrice": "¡¡¡mejor precio!!!",
742
742
  "instances.goodPrice": "buen precio",
743
743
  "instances.oclock": "",
744
+ // Lista de espera
745
+ "waitlist.joinCta": "Lista de espera",
746
+ "waitlist.title": "Apuntarse a la lista de espera",
747
+ "waitlist.subtitle": "{{name}} está agotado. Deja tus datos y te contactaremos si se libera un lugar.",
748
+ "waitlist.name": "Nombre",
749
+ "waitlist.email": "Correo electrónico",
750
+ "waitlist.phone": "Teléfono (opcional)",
751
+ "waitlist.requiredFields": "Por favor, introduce tu nombre y correo electrónico.",
752
+ "waitlist.join": "Apuntarse",
753
+ "waitlist.submitting": "Apuntando...",
754
+ "waitlist.cancel": "Cancelar",
755
+ "waitlist.submitError": "Algo salió mal. Por favor, inténtalo de nuevo.",
756
+ "waitlist.successTitle": "¡Estás en la lista!",
757
+ "waitlist.successMessage": "Eres el número {{position}} en la lista de espera. Te contactaremos si se libera un lugar.",
758
+ "waitlist.done": "Listo",
744
759
  // Next events preview
745
760
  "nextEvents.title": "Próximas fechas disponibles",
746
761
  "nextEvents.subtitle": "Selecciona una fecha o consulta todas las fechas disponibles",
@@ -1038,6 +1053,21 @@ const pt = {
1038
1053
  "instances.bestPrice": "melhor preço !!!",
1039
1054
  "instances.goodPrice": "bom preço",
1040
1055
  "instances.oclock": "",
1056
+ // Lista de espera
1057
+ "waitlist.joinCta": "Lista de espera",
1058
+ "waitlist.title": "Entrar na lista de espera",
1059
+ "waitlist.subtitle": "{{name}} está esgotado. Deixe os seus dados e entraremos em contacto se surgir uma vaga.",
1060
+ "waitlist.name": "Nome",
1061
+ "waitlist.email": "E-mail",
1062
+ "waitlist.phone": "Telefone (opcional)",
1063
+ "waitlist.requiredFields": "Por favor, introduza o seu nome e e-mail.",
1064
+ "waitlist.join": "Inscrever-se",
1065
+ "waitlist.submitting": "A inscrever...",
1066
+ "waitlist.cancel": "Cancelar",
1067
+ "waitlist.submitError": "Algo correu mal. Por favor, tente novamente.",
1068
+ "waitlist.successTitle": "Está na lista!",
1069
+ "waitlist.successMessage": "É o número {{position}} na lista de espera. Entraremos em contacto se surgir uma vaga.",
1070
+ "waitlist.done": "Concluído",
1041
1071
  // Next events preview
1042
1072
  "nextEvents.title": "Próximas datas disponíveis",
1043
1073
  "nextEvents.subtitle": "Selecione uma data ou veja todas as datas disponíveis",
@@ -1335,6 +1365,21 @@ const sv = {
1335
1365
  "instances.bestPrice": "bästa pris !!!",
1336
1366
  "instances.goodPrice": "bra pris",
1337
1367
  "instances.oclock": "",
1368
+ // Väntelista
1369
+ "waitlist.joinCta": "Ställ dig i kö",
1370
+ "waitlist.title": "Ställ dig i kö",
1371
+ "waitlist.subtitle": "{{name}} är fullbokat. Lämna dina uppgifter så kontaktar vi dig om en plats blir ledig.",
1372
+ "waitlist.name": "Namn",
1373
+ "waitlist.email": "E-post",
1374
+ "waitlist.phone": "Telefon (valfritt)",
1375
+ "waitlist.requiredFields": "Ange ditt namn och din e-postadress.",
1376
+ "waitlist.join": "Ställ dig i kö",
1377
+ "waitlist.submitting": "Anmäler...",
1378
+ "waitlist.cancel": "Avbryt",
1379
+ "waitlist.submitError": "Något gick fel. Försök igen.",
1380
+ "waitlist.successTitle": "Du står i kön!",
1381
+ "waitlist.successMessage": "Du är nummer {{position}} på väntelistan. Vi hör av oss om en plats blir ledig.",
1382
+ "waitlist.done": "Klar",
1338
1383
  // Next events preview
1339
1384
  "nextEvents.title": "Nästa tillgängliga datum",
1340
1385
  "nextEvents.subtitle": "Välj ett datum eller visa alla tillgängliga datum",
@@ -14412,7 +14457,7 @@ function InfoBadge({ text }) {
14412
14457
  pointerEvents: "none",
14413
14458
  }, children: text }))] }));
14414
14459
  }
14415
- function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, }) {
14460
+ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, showImages = true, }) {
14416
14461
  const t = useTranslations();
14417
14462
  const { locale } = useLocale();
14418
14463
  const timezone = useTimezone();
@@ -14491,6 +14536,18 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview,
14491
14536
  gridAutoRows: "1fr",
14492
14537
  }, children: eventTypes.map((eventType) => {
14493
14538
  const isAvailable = eventType.hasAvailableInstances;
14539
+ const hasImage = showImages && eventType.images && eventType.images.length > 0;
14540
+ const availabilityBadge = (jsxRuntime.jsx("div", { style: {
14541
+ padding: "4px 8px",
14542
+ borderRadius: "var(--bw-border-radius-small)",
14543
+ fontSize: "12px",
14544
+ fontWeight: 600,
14545
+ color: "#ffffff",
14546
+ fontFamily: "var(--bw-font-family)",
14547
+ backgroundColor: isAvailable
14548
+ ? "var(--bw-success-color)"
14549
+ : "var(--bw-error-color)",
14550
+ }, children: isAvailable ? t("events.spotsAvailable") : t("events.soldOut") }));
14494
14551
  return (jsxRuntime.jsxs("div", { className: "event-type-card", style: {
14495
14552
  position: "relative",
14496
14553
  backgroundColor: "var(--bw-surface-color)",
@@ -14502,17 +14559,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview,
14502
14559
  fontFamily: "var(--bw-font-family)",
14503
14560
  cursor: isAvailable ? "pointer" : "not-allowed",
14504
14561
  opacity: isAvailable ? 1 : 0.6,
14505
- }, onClick: () => isAvailable && onEventTypeSelect(eventType), children: [jsxRuntime.jsx("div", { style: { position: "absolute", top: "16px", right: "16px", zIndex: 10 }, children: jsxRuntime.jsx("div", { style: {
14506
- padding: "4px 8px",
14507
- borderRadius: "var(--bw-border-radius-small)",
14508
- fontSize: "12px",
14509
- fontWeight: 600,
14510
- color: "#ffffff",
14511
- fontFamily: "var(--bw-font-family)",
14512
- backgroundColor: isAvailable
14513
- ? "var(--bw-success-color)"
14514
- : "var(--bw-error-color)",
14515
- }, children: isAvailable ? t("events.spotsAvailable") : t("events.soldOut") }) }), eventType.images && eventType.images.length > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { style: { position: "absolute", top: "16px", left: "16px", zIndex: 10 }, children: jsxRuntime.jsx("div", { style: {
14562
+ }, onClick: () => isAvailable && onEventTypeSelect(eventType), children: [hasImage && (jsxRuntime.jsx("div", { style: { position: "absolute", top: "16px", right: "16px", zIndex: 10 }, children: availabilityBadge })), hasImage && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { style: { position: "absolute", top: "16px", left: "16px", zIndex: 10 }, children: jsxRuntime.jsx("div", { style: {
14516
14563
  fontSize: "13px",
14517
14564
  color: "var(--bw-surface-color)",
14518
14565
  fontWeight: 600,
@@ -14526,7 +14573,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview,
14526
14573
  flexDirection: "column",
14527
14574
  justifyContent: "space-between",
14528
14575
  height: "540px",
14529
- }, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("h2", { className: "event-type-title", style: {
14576
+ }, children: [jsxRuntime.jsxs("div", { children: [!hasImage && (jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "flex-end", margin: "0 0 8px 0" }, children: availabilityBadge })), jsxRuntime.jsx("h2", { className: "event-type-title", style: {
14530
14577
  fontSize: "clamp(1.1rem, 2.5vw, 24px)",
14531
14578
  fontWeight: 700,
14532
14579
  color: "var(--bw-text-color)",
@@ -14798,16 +14845,16 @@ function WaitlistDialog({ apiBaseUrl, organizationId, eventInstanceId, eventName
14798
14845
  }
14799
14846
 
14800
14847
  const getAllocationBadgeInfo = (availableSpots, maxParticipants, t) => {
14801
- const availabilityRatio = availableSpots / maxParticipants;
14802
- if (availabilityRatio >= 0.6)
14803
- return null;
14804
- if (availabilityRatio === 0) {
14848
+ if (maxParticipants <= 0 || availableSpots <= 0) {
14805
14849
  return {
14806
14850
  text: t("events.soldOut"),
14807
14851
  backgroundColor: "#7f1d1d",
14808
14852
  textColor: "#fca5a5",
14809
14853
  };
14810
14854
  }
14855
+ const availabilityRatio = availableSpots / maxParticipants;
14856
+ if (availabilityRatio >= 0.6)
14857
+ return null;
14811
14858
  if (availabilityRatio <= 0.3) {
14812
14859
  return {
14813
14860
  text: t("instances.almostSoldOut"),
@@ -14921,7 +14968,7 @@ const PriceDisplay = ({ price, yearPrices, t }) => {
14921
14968
  boxShadow: displayInfo ? "0 2px 4px rgba(0, 0, 0, 0.2)" : "none",
14922
14969
  }, children: formatCurrency(price) }));
14923
14970
  };
14924
- function EventInstanceSelection({ eventInstances, selectedEventType, onEventInstanceSelect, onBackToEventTypes, isOpen, onClose, isLoadingEventInstances = false, isLoadingEventDetails = false, hasUpsellsStep = false, apiBaseUrl, organizationId, }) {
14971
+ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInstanceSelect, onBackToEventTypes, isOpen, onClose, isLoadingEventInstances = false, isLoadingEventDetails = false, hasUpsellsStep = false, apiBaseUrl, organizationId, waitlistEnabled = false, }) {
14925
14972
  const t = useTranslations();
14926
14973
  const { locale } = useLocale();
14927
14974
  const timezone = useTimezone();
@@ -15106,12 +15153,13 @@ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInst
15106
15153
  ? "0 2px 4px rgba(0, 0, 0, 0.2)"
15107
15154
  : undefined,
15108
15155
  }, children: `${t("common.from")} ${formatCurrency(minPrice)}` }), isOpen: openGroups.has(key), onToggle: () => toggleGroup(key), children: jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", paddingTop: "12px" }, children: events.map((event) => {
15109
- const availableSpots = event.maxParticipants - event.participantCount;
15110
- const isFullyBooked = availableSpots === 0;
15156
+ const availableSpots = event.availableSpots;
15111
15157
  const startDate = new Date(event.startTime);
15112
15158
  const isPastEvent = today.toISOString() >= startDate.toISOString();
15113
- const isDisabled = isFullyBooked || isPastEvent || !event.bookingOpen;
15114
- const canWaitlist = isFullyBooked &&
15159
+ const isUnavailable = availableSpots <= 0 || !event.bookingOpen;
15160
+ const isDisabled = isUnavailable || isPastEvent;
15161
+ const canWaitlist = waitlistEnabled &&
15162
+ isUnavailable &&
15115
15163
  !isPastEvent &&
15116
15164
  !!apiBaseUrl &&
15117
15165
  !!organizationId;
@@ -15148,7 +15196,7 @@ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInst
15148
15196
  color: "var(--bw-highlight-color)",
15149
15197
  opacity: 0.8,
15150
15198
  fontSize: "32px",
15151
- }, children: spinner() }) })), jsxRuntime.jsx(SpecialPriceBadge, { price: event.price, yearPrices: yearPrices, t: t }), jsxRuntime.jsx(AllocationBadge, { availableSpots: availableSpots, maxParticipants: event.maxParticipants, t: t }), jsxRuntime.jsxs("div", { style: {
15199
+ }, children: spinner() }) })), jsxRuntime.jsx(SpecialPriceBadge, { price: event.price, yearPrices: yearPrices, t: t }), jsxRuntime.jsx(AllocationBadge, { availableSpots: availableSpots, maxParticipants: event.effectiveMaxParticipants ?? event.maxParticipants, t: t }), jsxRuntime.jsxs("div", { style: {
15152
15200
  display: "flex",
15153
15201
  justifyContent: "space-between",
15154
15202
  width: "100%",
@@ -15325,18 +15373,19 @@ function NextEventsPreview({ events, onEventSelect, onShowAll, showAllButtonText
15325
15373
  margin: "0 auto",
15326
15374
  padding: "12px 16px",
15327
15375
  fontFamily: "var(--bw-font-family)",
15328
- }, children: [jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", marginBottom: "10px" }, children: events.map((event) => {
15329
- const availableSpots = event.maxParticipants - event.participantCount;
15330
- const isFullyBooked = availableSpots === 0;
15376
+ }, children: [jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", marginBottom: "10px" }, children: events
15377
+ .filter((event) => {
15331
15378
  const startDate = new Date(event.startTime);
15332
15379
  const isPastEvent = today.toISOString() >= startDate.toISOString();
15333
- const isDisabled = isFullyBooked || isPastEvent || !event.bookingOpen;
15334
- const availabilityRatio = availableSpots / event.maxParticipants;
15380
+ return !isPastEvent && event.availableSpots > 0 && event.bookingOpen;
15381
+ })
15382
+ .map((event) => {
15383
+ const availableSpots = event.availableSpots;
15384
+ const startDate = new Date(event.startTime);
15335
15385
  const allocationBadge = (() => {
15386
+ const availabilityRatio = availableSpots / event.maxParticipants;
15336
15387
  if (availabilityRatio >= 0.6)
15337
15388
  return null;
15338
- if (availabilityRatio === 0)
15339
- return { text: t("events.soldOut"), backgroundColor: "#7f1d1d", textColor: "#fca5a5" };
15340
15389
  if (availabilityRatio <= 0.3)
15341
15390
  return { text: t("instances.almostSoldOut"), backgroundColor: "#7f1d1d", textColor: "#fca5a5" };
15342
15391
  return { text: t("instances.popularDate"), backgroundColor: "#b45309", textColor: "#fbbf24" };
@@ -15350,13 +15399,9 @@ function NextEventsPreview({ events, onEventSelect, onShowAll, showAllButtonText
15350
15399
  padding: "16px 10px",
15351
15400
  transition: "all 0.2s ease",
15352
15401
  fontFamily: "var(--bw-font-family)",
15353
- opacity: isDisabled ? 0.3 : 1,
15354
- filter: isDisabled ? "grayscale(40%)" : "none",
15355
- cursor: isDisabled ? "not-allowed" : "pointer",
15402
+ cursor: "pointer",
15356
15403
  }, onClick: () => {
15357
- if (!isDisabled) {
15358
- handleEventSelect(event.id);
15359
- }
15404
+ handleEventSelect(event.id);
15360
15405
  }, children: [selectedEventInstanceId === event.id && isLoadingEventDetails && (jsxRuntime.jsx("div", { style: {
15361
15406
  position: "absolute",
15362
15407
  inset: 0,
@@ -15611,7 +15656,7 @@ function SpecialsView({ specials, onEventSelect, isLoading = false, showSavingsA
15611
15656
  alignItems: "center",
15612
15657
  backgroundColor: "var(--bw-background-color)",
15613
15658
  }, children: [jsxRuntime.jsx("span", { style: { fontSize: "12px", color: "var(--bw-text-muted)" }, children: isFullyBooked
15614
- ? t("common.fullyBooked")
15659
+ ? t("events.soldOut")
15615
15660
  : t("specials.spotsLeft").replace("{{count}}", String(special.availableSpots)) }), jsxRuntime.jsxs("span", { style: {
15616
15661
  fontSize: "13px",
15617
15662
  fontWeight: 600,
@@ -16560,6 +16605,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
16560
16605
  const [isSuccess, setIsSuccess] = React.useState(false);
16561
16606
  const [successPaymentId, setSuccessPaymentId] = React.useState(null);
16562
16607
  const [systemConfig, setSystemConfig] = React.useState(null);
16608
+ const [waitlistEnabled, setWaitlistEnabled] = React.useState(false);
16563
16609
  // When true, loadEventInstances skips the single-instance auto-select (used by handleShowAllEvents)
16564
16610
  const skipInstanceAutoSelectRef = React.useRef(false);
16565
16611
  // PERFORMANCE OPTIMIZATION: Lazy component loading
@@ -17053,6 +17099,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
17053
17099
  }
17054
17100
  extractGoogleAdsConfig(data);
17055
17101
  setEventInstances(data.eventInstances);
17102
+ setWaitlistEnabled(data.waitlistEnabled ?? false);
17056
17103
  if (data.paymentProvider) {
17057
17104
  setSystemConfig({
17058
17105
  paymentProvider: data.paymentProvider,
@@ -17621,7 +17668,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
17621
17668
  }, isOpen: currentStep === "eventInstances", onClose: () => {
17622
17669
  setShowingPreview(true);
17623
17670
  setCurrentStep("eventTypes");
17624
- }, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
17671
+ }, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId, waitlistEnabled: waitlistEnabled })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
17625
17672
  setIsSuccess(false);
17626
17673
  setCurrentStep("eventTypes");
17627
17674
  setShowingPreview(true);
@@ -17684,7 +17731,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
17684
17731
  }, children: [isButtonBusy && jsxRuntime.jsx(Spinner, { size: 20, borderColor: "var(--bw-button-text-color, #ffffff)" }), config.buttonText ||
17685
17732
  (isDirectInstanceMode || selectedEventType?.bookingMode === "freeform"
17686
17733
  ? t("button.bookNow")
17687
- : t("button.viewDates"))] }), shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, onSuccess: handleBookingSuccess, onError: handleBookingError, isOpen: currentStep === "booking" && !!eventDetails, onClose: handleBackFromBooking, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells, persistedState: bookingPersistedState, onPersistedStateChange: setBookingPersistedState })), shouldRenderFreeformSelection && selectedEventType?.bookingMode === "freeform" && (jsxRuntime.jsx(FreeformSelection, { config: config, eventType: selectedEventType, isOpen: currentStep === "freeform", onClose: () => {
17734
+ : t("button.viewDates"))] }), shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId, waitlistEnabled: waitlistEnabled })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, onSuccess: handleBookingSuccess, onError: handleBookingError, isOpen: currentStep === "booking" && !!eventDetails, onClose: handleBackFromBooking, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells, persistedState: bookingPersistedState, onPersistedStateChange: setBookingPersistedState })), shouldRenderFreeformSelection && selectedEventType?.bookingMode === "freeform" && (jsxRuntime.jsx(FreeformSelection, { config: config, eventType: selectedEventType, isOpen: currentStep === "freeform", onClose: () => {
17688
17735
  setCurrentStep("eventTypes");
17689
17736
  setSidebarOpen(false);
17690
17737
  setShouldRenderFreeformSelection(false);
@@ -17709,7 +17756,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
17709
17756
  }, config: config, googleAdsConfig: googleAdsConfig, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsxRuntime.jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
17710
17757
  }
17711
17758
  // Cards mode (default) - show event type selection with optional voucher card
17712
- const cardsView = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasEventSelection && (jsxRuntime.jsx(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, onInstancePreview: (instanceId, eventTypeId) => void handleUpcomingEventSelect(instanceId, eventTypeId), isLoading: isLoading, skeletonCount: getSkeletonCount(), showVoucherAttachment: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled && !isStandaloneVoucherMode), onVoucherClick: handleVoucherAttachmentClick })), isStandaloneVoucherMode && (jsxRuntime.jsx(VoucherIntegration, { config: config, voucherConfig: voucherConfig, eventTypes: voucherEventTypes, categories: voucherCategories, systemConfig: systemConfig, isFormOpen: false, isLoadingConfig: isLoadingVoucherConfig, preselectedEventTypeId: null, voucherPurchaseResult: null, isSuccess: false, showStandaloneCard: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled), onCardClick: handleVoucherCardClick, onFormClose: handleVoucherFormClose, onSuccess: handleVoucherSuccess, onError: handleVoucherError, onSuccessModalClose: () => { } })), isStandaloneVoucherMode && isLoading && !voucherConfig && (jsxRuntime.jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsxRuntime.jsx("div", { style: {
17759
+ const cardsView = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasEventSelection && (jsxRuntime.jsx(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, onInstancePreview: (instanceId, eventTypeId) => void handleUpcomingEventSelect(instanceId, eventTypeId), isLoading: isLoading, skeletonCount: getSkeletonCount(), showVoucherAttachment: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled && !isStandaloneVoucherMode), onVoucherClick: handleVoucherAttachmentClick, showImages: config.showEventImages !== false })), isStandaloneVoucherMode && (jsxRuntime.jsx(VoucherIntegration, { config: config, voucherConfig: voucherConfig, eventTypes: voucherEventTypes, categories: voucherCategories, systemConfig: systemConfig, isFormOpen: false, isLoadingConfig: isLoadingVoucherConfig, preselectedEventTypeId: null, voucherPurchaseResult: null, isSuccess: false, showStandaloneCard: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled), onCardClick: handleVoucherCardClick, onFormClose: handleVoucherFormClose, onSuccess: handleVoucherSuccess, onError: handleVoucherError, onSuccessModalClose: () => { } })), isStandaloneVoucherMode && isLoading && !voucherConfig && (jsxRuntime.jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsxRuntime.jsx("div", { style: {
17713
17760
  display: "inline-block",
17714
17761
  width: "32px",
17715
17762
  height: "32px",
@@ -17750,7 +17797,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
17750
17797
  };
17751
17798
  };
17752
17799
  const backHandlers = getBackHandlers();
17753
- return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, onSuccess: handleBookingSuccess, onError: handleBookingError, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells, persistedState: bookingPersistedState, onPersistedStateChange: setBookingPersistedState })), shouldRenderFreeformSelection && selectedEventType?.bookingMode === "freeform" && (jsxRuntime.jsx(FreeformSelection, { config: config, eventType: selectedEventType, isOpen: currentStep === "freeform", onClose: () => {
17800
+ return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails, hasUpsellsStep: hasUpsellsFlowStep, apiBaseUrl: config.apiBaseUrl, organizationId: config.organizationId, waitlistEnabled: waitlistEnabled })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, onSuccess: handleBookingSuccess, onError: handleBookingError, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells, persistedState: bookingPersistedState, onPersistedStateChange: setBookingPersistedState })), shouldRenderFreeformSelection && selectedEventType?.bookingMode === "freeform" && (jsxRuntime.jsx(FreeformSelection, { config: config, eventType: selectedEventType, isOpen: currentStep === "freeform", onClose: () => {
17754
17801
  setCurrentStep("eventTypes");
17755
17802
  setShouldRenderFreeformSelection(false);
17756
17803
  }, onSuccess: handleBookingSuccess, onError: handleBookingError, systemConfig: systemConfig })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess && !voucherPurchaseResult, onClose: () => {