@bigz-app/booking-widget 1.3.0 → 1.3.1
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/booking-widget.js +116 -56
- package/dist/booking-widget.js.map +1 -1
- package/dist/components/UniversalBookingWidget.d.ts.map +1 -1
- package/dist/components/booking/BookingForm.d.ts +3 -0
- package/dist/components/booking/BookingForm.d.ts.map +1 -1
- package/dist/components/booking/BookingSuccessModal.d.ts.map +1 -1
- package/dist/i18n/i18n-context.d.ts.map +1 -1
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/index.cjs +116 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +117 -57
- package/dist/index.esm.js.map +1 -1
- package/dist/styles/StyleProvider.d.ts.map +1 -1
- package/dist/styles/shared-styles.d.ts.map +1 -1
- package/dist/validation/booking-schema.d.ts +54 -13
- package/dist/validation/booking-schema.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/booking-widget.js
CHANGED
|
@@ -338,6 +338,8 @@
|
|
|
338
338
|
"booking.participantName": "Name *",
|
|
339
339
|
"booking.participantNamePlaceholder": "Teilnehmername",
|
|
340
340
|
"booking.participantAge": "Alter",
|
|
341
|
+
"booking.participantLevel": "Level",
|
|
342
|
+
"booking.participantLevelPlaceholder": "Level wählen...",
|
|
341
343
|
"booking.addParticipant": "{{number}}. Teilnehmer hinzufügen",
|
|
342
344
|
"booking.maxParticipants": "Maximale Anzahl an Teilnehmern erreicht. Es sind nur noch {{count}} Plätze verfügbar.",
|
|
343
345
|
"booking.maxSpotsReached": "Maximal {{count}} Plätze verfügbar.",
|
|
@@ -486,7 +488,11 @@
|
|
|
486
488
|
"validation.emailInvalid": "Ungültiges E-Mail-Format",
|
|
487
489
|
"validation.emailDomainInvalid": "Ungültige E-Mail-Domain",
|
|
488
490
|
"validation.participantRequired": "Mindestens ein Teilnehmer erforderlich",
|
|
491
|
+
"validation.ageRequired": "Alter ist erforderlich",
|
|
492
|
+
"validation.levelRequired": "Bitte ein Level auswählen",
|
|
489
493
|
"validation.acceptTerms": "Bitte akzeptiere die Allgemeinen Geschäftsbedingungen",
|
|
494
|
+
"level.beginner": "Anfänger",
|
|
495
|
+
"level.advanced": "Fortgeschritten",
|
|
490
496
|
// Sidebar
|
|
491
497
|
"sidebar.close": "Schließen",
|
|
492
498
|
// Promo
|
|
@@ -608,6 +614,8 @@
|
|
|
608
614
|
"booking.participantName": "Name *",
|
|
609
615
|
"booking.participantNamePlaceholder": "Participant name",
|
|
610
616
|
"booking.participantAge": "Age",
|
|
617
|
+
"booking.participantLevel": "Level",
|
|
618
|
+
"booking.participantLevelPlaceholder": "Select level...",
|
|
611
619
|
"booking.addParticipant": "Add participant {{number}}",
|
|
612
620
|
"booking.maxParticipants": "Maximum number of participants reached. Only {{count}} spots are available.",
|
|
613
621
|
"booking.maxSpotsReached": "Maximum {{count}} spots available.",
|
|
@@ -756,7 +764,11 @@
|
|
|
756
764
|
"validation.emailInvalid": "Invalid email format",
|
|
757
765
|
"validation.emailDomainInvalid": "Invalid email domain",
|
|
758
766
|
"validation.participantRequired": "At least one participant is required",
|
|
767
|
+
"validation.ageRequired": "Age is required",
|
|
768
|
+
"validation.levelRequired": "Please select a level",
|
|
759
769
|
"validation.acceptTerms": "Please accept the terms and conditions",
|
|
770
|
+
"level.beginner": "Beginner",
|
|
771
|
+
"level.advanced": "Advanced",
|
|
760
772
|
// Sidebar
|
|
761
773
|
"sidebar.close": "Close",
|
|
762
774
|
// Promo
|
|
@@ -878,6 +890,8 @@
|
|
|
878
890
|
"booking.participantName": "Nombre *",
|
|
879
891
|
"booking.participantNamePlaceholder": "Nombre del participante",
|
|
880
892
|
"booking.participantAge": "Edad",
|
|
893
|
+
"booking.participantLevel": "Nivel",
|
|
894
|
+
"booking.participantLevelPlaceholder": "Seleccionar nivel...",
|
|
881
895
|
"booking.addParticipant": "Añadir participante {{number}}",
|
|
882
896
|
"booking.maxParticipants": "Número máximo de participantes alcanzado. Solo quedan {{count}} plazas disponibles.",
|
|
883
897
|
"booking.maxSpotsReached": "Máximo {{count}} plazas disponibles.",
|
|
@@ -1026,7 +1040,11 @@
|
|
|
1026
1040
|
"validation.emailInvalid": "Formato de correo electrónico inválido",
|
|
1027
1041
|
"validation.emailDomainInvalid": "Dominio de correo electrónico inválido",
|
|
1028
1042
|
"validation.participantRequired": "Se requiere al menos un participante",
|
|
1043
|
+
"validation.ageRequired": "La edad es obligatoria",
|
|
1044
|
+
"validation.levelRequired": "Selecciona un nivel",
|
|
1029
1045
|
"validation.acceptTerms": "Por favor, acepta los términos y condiciones",
|
|
1046
|
+
"level.beginner": "Principiante",
|
|
1047
|
+
"level.advanced": "Avanzado",
|
|
1030
1048
|
// Sidebar
|
|
1031
1049
|
"sidebar.close": "Cerrar",
|
|
1032
1050
|
// Promo
|
|
@@ -1148,6 +1166,8 @@
|
|
|
1148
1166
|
"booking.participantName": "Nome *",
|
|
1149
1167
|
"booking.participantNamePlaceholder": "Nome do participante",
|
|
1150
1168
|
"booking.participantAge": "Idade",
|
|
1169
|
+
"booking.participantLevel": "Nível",
|
|
1170
|
+
"booking.participantLevelPlaceholder": "Selecionar nível...",
|
|
1151
1171
|
"booking.addParticipant": "Adicionar participante {{number}}",
|
|
1152
1172
|
"booking.maxParticipants": "Número máximo de participantes atingido. Apenas {{count}} lugares disponíveis.",
|
|
1153
1173
|
"booking.maxSpotsReached": "Máximo {{count}} lugares disponíveis.",
|
|
@@ -1296,7 +1316,11 @@
|
|
|
1296
1316
|
"validation.emailInvalid": "Formato de email inválido",
|
|
1297
1317
|
"validation.emailDomainInvalid": "Domínio de email inválido",
|
|
1298
1318
|
"validation.participantRequired": "É necessário pelo menos um participante",
|
|
1319
|
+
"validation.ageRequired": "A idade é obrigatória",
|
|
1320
|
+
"validation.levelRequired": "Por favor selecione um nível",
|
|
1299
1321
|
"validation.acceptTerms": "Por favor, aceite os termos e condições",
|
|
1322
|
+
"level.beginner": "Iniciante",
|
|
1323
|
+
"level.advanced": "Avançado",
|
|
1300
1324
|
// Sidebar
|
|
1301
1325
|
"sidebar.close": "Fechar",
|
|
1302
1326
|
// Promo
|
|
@@ -1418,6 +1442,8 @@
|
|
|
1418
1442
|
"booking.participantName": "Namn *",
|
|
1419
1443
|
"booking.participantNamePlaceholder": "Deltagarens namn",
|
|
1420
1444
|
"booking.participantAge": "Ålder",
|
|
1445
|
+
"booking.participantLevel": "Nivå",
|
|
1446
|
+
"booking.participantLevelPlaceholder": "Välj nivå...",
|
|
1421
1447
|
"booking.addParticipant": "Lägg till deltagare {{number}}",
|
|
1422
1448
|
"booking.maxParticipants": "Maximalt antal deltagare uppnått. Bara {{count}} platser är tillgängliga.",
|
|
1423
1449
|
"booking.maxSpotsReached": "Maximalt {{count}} platser tillgängliga.",
|
|
@@ -1566,7 +1592,11 @@
|
|
|
1566
1592
|
"validation.emailInvalid": "Ogiltigt e-postformat",
|
|
1567
1593
|
"validation.emailDomainInvalid": "Ogiltig e-postdomän",
|
|
1568
1594
|
"validation.participantRequired": "Minst en deltagare krävs",
|
|
1595
|
+
"validation.ageRequired": "Ålder krävs",
|
|
1596
|
+
"validation.levelRequired": "Välj en nivå",
|
|
1569
1597
|
"validation.acceptTerms": "Acceptera villkoren",
|
|
1598
|
+
"level.beginner": "Nybörjare",
|
|
1599
|
+
"level.advanced": "Avancerad",
|
|
1570
1600
|
// Sidebar
|
|
1571
1601
|
"sidebar.close": "Stäng",
|
|
1572
1602
|
// Promo
|
|
@@ -1659,18 +1689,9 @@
|
|
|
1659
1689
|
}
|
|
1660
1690
|
const I18nContext = R$2(null);
|
|
1661
1691
|
function I18nProvider({ configLocale, children }) {
|
|
1662
|
-
// Priority:
|
|
1663
|
-
//
|
|
1664
|
-
const [overrideLocale, setOverrideLocale] = d$1(() =>
|
|
1665
|
-
if (configLocale)
|
|
1666
|
-
return null;
|
|
1667
|
-
return readPersistedLocale();
|
|
1668
|
-
});
|
|
1669
|
-
y$1(() => {
|
|
1670
|
-
if (configLocale) {
|
|
1671
|
-
setOverrideLocale(null);
|
|
1672
|
-
}
|
|
1673
|
-
}, [configLocale]);
|
|
1692
|
+
// Priority: persisted user choice > configLocale (org default) > browser language > "de"
|
|
1693
|
+
// This keeps org locale as default, but remembers explicit user overrides across reloads.
|
|
1694
|
+
const [overrideLocale, setOverrideLocale] = d$1(() => readPersistedLocale());
|
|
1674
1695
|
const locale = overrideLocale ?? resolveLocale(configLocale);
|
|
1675
1696
|
const handleSetLocale = q$2((next) => {
|
|
1676
1697
|
persistLocale(next);
|
|
@@ -1802,6 +1823,16 @@
|
|
|
1802
1823
|
// If semantic resolution fails, use fallback or return the original value
|
|
1803
1824
|
return fallbackValue || colorValue;
|
|
1804
1825
|
};
|
|
1826
|
+
// Legacy theme name redirects (old name → new name)
|
|
1827
|
+
const legacyThemeRedirects = {
|
|
1828
|
+
"light-fresh": "teal-minimal",
|
|
1829
|
+
"light-elegant": "blue-business",
|
|
1830
|
+
"light-vibrant": "orange-raw",
|
|
1831
|
+
"light-professional": "blue-business",
|
|
1832
|
+
"dark-night": "navy-night",
|
|
1833
|
+
"dark-modern": "navy-night",
|
|
1834
|
+
"dark-forest": "green-deep",
|
|
1835
|
+
};
|
|
1805
1836
|
// Predefined themes
|
|
1806
1837
|
const themes = {
|
|
1807
1838
|
// --- Light Themes ---
|
|
@@ -1948,7 +1979,9 @@
|
|
|
1948
1979
|
}, []);
|
|
1949
1980
|
// PERFORMANCE OPTIMIZATION: Memoize style calculations
|
|
1950
1981
|
const themedStyles = T$2(() => {
|
|
1951
|
-
const
|
|
1982
|
+
const rawThemeName = config.theme || "teal-minimal";
|
|
1983
|
+
// Redirect legacy theme names to new names
|
|
1984
|
+
const themeName = legacyThemeRedirects[rawThemeName] || rawThemeName;
|
|
1952
1985
|
const themeDefaults = themes[themeName] || themes["teal-minimal"];
|
|
1953
1986
|
const getCSSValue = (value, fallback) => {
|
|
1954
1987
|
if (!value)
|
|
@@ -11309,16 +11342,37 @@
|
|
|
11309
11342
|
ZodUnion.create;
|
|
11310
11343
|
ZodIntersection.create;
|
|
11311
11344
|
ZodTuple.create;
|
|
11312
|
-
ZodEnum.create;
|
|
11345
|
+
const enumType = ZodEnum.create;
|
|
11313
11346
|
ZodPromise.create;
|
|
11314
11347
|
ZodOptional.create;
|
|
11315
11348
|
ZodNullable.create;
|
|
11349
|
+
const preprocessType = ZodEffects.createWithPreprocess;
|
|
11316
11350
|
|
|
11317
|
-
const
|
|
11318
|
-
name:
|
|
11351
|
+
const DEFAULT_PARTICIPANT_FIELDS_CONFIG = {
|
|
11352
|
+
name: { enabled: true, required: true },
|
|
11353
|
+
age: { enabled: true, required: false },
|
|
11354
|
+
level: { enabled: false, required: false },
|
|
11355
|
+
};
|
|
11356
|
+
const participantSchema = (t, fieldsConfig) => objectType({
|
|
11357
|
+
name: stringType().trim().optional(),
|
|
11319
11358
|
age: numberType().min(0).max(120).optional(),
|
|
11359
|
+
level: preprocessType((value) => (value === "" ? undefined : value), enumType(["beginner", "advanced"]).optional()),
|
|
11360
|
+
})
|
|
11361
|
+
.superRefine((value, ctx) => {
|
|
11362
|
+
if (fieldsConfig.name.required && (!value.name || value.name.trim().length < 1)) {
|
|
11363
|
+
ctx.addIssue({ code: ZodIssueCode.custom, message: t("validation.nameRequired"), path: ["name"] });
|
|
11364
|
+
}
|
|
11365
|
+
if (!fieldsConfig.name.enabled && value.name && value.name.trim().length > 0) {
|
|
11366
|
+
ctx.addIssue({ code: ZodIssueCode.custom, message: t("validation.nameRequired"), path: ["name"] });
|
|
11367
|
+
}
|
|
11368
|
+
if (fieldsConfig.age.required && typeof value.age !== "number") {
|
|
11369
|
+
ctx.addIssue({ code: ZodIssueCode.custom, message: t("validation.ageRequired"), path: ["age"] });
|
|
11370
|
+
}
|
|
11371
|
+
if (fieldsConfig.level.required && !value.level) {
|
|
11372
|
+
ctx.addIssue({ code: ZodIssueCode.custom, message: t("validation.levelRequired"), path: ["level"] });
|
|
11373
|
+
}
|
|
11320
11374
|
});
|
|
11321
|
-
function createBookingFormSchema(t) {
|
|
11375
|
+
function createBookingFormSchema(t, fieldsConfig = DEFAULT_PARTICIPANT_FIELDS_CONFIG) {
|
|
11322
11376
|
const tr = t ?? ((key) => key);
|
|
11323
11377
|
return objectType({
|
|
11324
11378
|
customerName: stringType().trim().min(2, tr("validation.nameMinLength")),
|
|
@@ -11328,7 +11382,7 @@
|
|
|
11328
11382
|
.email(tr("validation.emailInvalid"))
|
|
11329
11383
|
.regex(/\.[a-zA-Z]{2,}$/, tr("validation.emailDomainInvalid")),
|
|
11330
11384
|
customerPhone: stringType().trim().optional(),
|
|
11331
|
-
participants: arrayType(participantSchema(tr)).min(1, tr("validation.participantRequired")),
|
|
11385
|
+
participants: arrayType(participantSchema(tr, fieldsConfig)).min(1, tr("validation.participantRequired")),
|
|
11332
11386
|
discountCode: stringType().trim().optional(),
|
|
11333
11387
|
comment: stringType().trim().optional(),
|
|
11334
11388
|
acceptTerms: booleanType().refine((val) => val === true, {
|
|
@@ -11471,7 +11525,8 @@
|
|
|
11471
11525
|
gap: "8px",
|
|
11472
11526
|
marginTop: "10px",
|
|
11473
11527
|
paddingTop: "10px",
|
|
11474
|
-
|
|
11528
|
+
paddingBottom: "25px",
|
|
11529
|
+
borderBottom: "1px dashed var(--bw-border-color)",
|
|
11475
11530
|
},
|
|
11476
11531
|
label: {
|
|
11477
11532
|
display: "inline-flex",
|
|
@@ -11529,6 +11584,8 @@
|
|
|
11529
11584
|
const { locale } = useLocale();
|
|
11530
11585
|
const timezone = useTimezone();
|
|
11531
11586
|
const roundEnabled = systemConfig?.roundPricesEnabled !== false;
|
|
11587
|
+
const participantFieldsConfig = eventDetails.participantFieldsConfig ?? DEFAULT_PARTICIPANT_FIELDS_CONFIG;
|
|
11588
|
+
const participantLevelOptions = eventDetails.participantLevelOptions ?? ["beginner", "advanced"];
|
|
11532
11589
|
const roundDiscountUp = (minorUnits) => Math.ceil(minorUnits / 100) * 100;
|
|
11533
11590
|
const calcPercentDiscountAmount = (baseAmount, basisPoints, round) => {
|
|
11534
11591
|
const raw = Math.round((baseAmount * basisPoints) / 10000);
|
|
@@ -11541,18 +11598,19 @@
|
|
|
11541
11598
|
// Per-participant upsell selections: participantIndex -> array of upsell package IDs
|
|
11542
11599
|
const [participantUpsells, setParticipantUpsells] = d$1({});
|
|
11543
11600
|
const form = useForm({
|
|
11544
|
-
resolver: t(createBookingFormSchema(t$1)),
|
|
11601
|
+
resolver: t(createBookingFormSchema(t$1, participantFieldsConfig)),
|
|
11545
11602
|
defaultValues: {
|
|
11546
11603
|
customerName: "",
|
|
11547
11604
|
customerEmail: "",
|
|
11548
11605
|
customerPhone: "",
|
|
11549
|
-
participants: [{ name: "" }],
|
|
11606
|
+
participants: [{ name: "", level: undefined }],
|
|
11550
11607
|
discountCode: "",
|
|
11551
11608
|
comment: "",
|
|
11552
11609
|
acceptTerms: false,
|
|
11553
11610
|
},
|
|
11554
11611
|
});
|
|
11555
11612
|
const watchedParticipants = form.watch("participants");
|
|
11613
|
+
const participantCount = watchedParticipants.length;
|
|
11556
11614
|
const watchedCustomerName = form.watch("customerName");
|
|
11557
11615
|
const watchedCustomerEmail = form.watch("customerEmail");
|
|
11558
11616
|
const watchedComment = form.watch("comment");
|
|
@@ -11594,14 +11652,13 @@
|
|
|
11594
11652
|
const calculateBaseTotal = q$2(() => {
|
|
11595
11653
|
if (!eventDetails)
|
|
11596
11654
|
return 0;
|
|
11597
|
-
return eventDetails.price *
|
|
11598
|
-
}, [eventDetails,
|
|
11655
|
+
return eventDetails.price * participantCount;
|
|
11656
|
+
}, [eventDetails, participantCount]);
|
|
11599
11657
|
// Calculate upsells total based on per-participant selections
|
|
11600
11658
|
const calculateUpsellsTotal = q$2(() => {
|
|
11601
11659
|
let total = 0;
|
|
11602
|
-
watchedParticipants.forEach((
|
|
11603
|
-
|
|
11604
|
-
if (participant.name.trim()) {
|
|
11660
|
+
watchedParticipants.forEach((_, index) => {
|
|
11661
|
+
if (participantCount > 0) {
|
|
11605
11662
|
const participantUpsellIds = participantUpsells[index] || [];
|
|
11606
11663
|
participantUpsellIds.forEach(upsellId => {
|
|
11607
11664
|
const upsell = upsells.find(u => u.id === upsellId);
|
|
@@ -11612,7 +11669,7 @@
|
|
|
11612
11669
|
}
|
|
11613
11670
|
});
|
|
11614
11671
|
return total;
|
|
11615
|
-
}, [participantUpsells, upsells, watchedParticipants]);
|
|
11672
|
+
}, [participantUpsells, upsells, watchedParticipants, participantCount]);
|
|
11616
11673
|
const calculateTotalDiscount = q$2(() => {
|
|
11617
11674
|
return appliedVouchers.reduce((total, voucher) => {
|
|
11618
11675
|
if (voucher.type === "discount") {
|
|
@@ -11633,8 +11690,7 @@
|
|
|
11633
11690
|
const calculateDeposit = () => {
|
|
11634
11691
|
if (!eventDetails || !eventDetails.deposit)
|
|
11635
11692
|
return 0;
|
|
11636
|
-
|
|
11637
|
-
return eventDetails.deposit * participantCount;
|
|
11693
|
+
return eventDetails.deposit * watchedParticipants.length;
|
|
11638
11694
|
};
|
|
11639
11695
|
const baseTotal = calculateBaseTotal();
|
|
11640
11696
|
const upsellsTotal = calculateUpsellsTotal();
|
|
@@ -11651,8 +11707,8 @@
|
|
|
11651
11707
|
// Includes participantIndices to track which participants selected each upsell
|
|
11652
11708
|
const aggregatedUpsellSelections = q$2(() => {
|
|
11653
11709
|
const upsellParticipantMap = {};
|
|
11654
|
-
watchedParticipants.forEach((
|
|
11655
|
-
if (
|
|
11710
|
+
watchedParticipants.forEach((_, index) => {
|
|
11711
|
+
if (participantCount > 0) {
|
|
11656
11712
|
const participantUpsellIds = participantUpsells[index] || [];
|
|
11657
11713
|
participantUpsellIds.forEach(upsellId => {
|
|
11658
11714
|
if (!upsellParticipantMap[upsellId]) {
|
|
@@ -11686,15 +11742,17 @@
|
|
|
11686
11742
|
setAppliedVouchers((prev) => prev.filter((v) => v.code !== code));
|
|
11687
11743
|
}, []);
|
|
11688
11744
|
const isReadyForPayment = () => {
|
|
11689
|
-
const participantsWithNames = watchedParticipants.filter((p) => p.name
|
|
11745
|
+
const participantsWithNames = watchedParticipants.filter((p) => p.name?.trim()).length;
|
|
11690
11746
|
const totalParticipantRows = watchedParticipants.length;
|
|
11691
|
-
const allParticipantsHaveNames =
|
|
11747
|
+
const allParticipantsHaveNames = participantFieldsConfig.name.required
|
|
11748
|
+
? participantsWithNames === totalParticipantRows
|
|
11749
|
+
: true;
|
|
11692
11750
|
const participantsWithinLimit = participantsWithNames <= (eventDetails?.availableSpots || 0);
|
|
11693
11751
|
const hasValidCustomerName = watchedCustomerName && watchedCustomerName.trim().length >= 2;
|
|
11694
11752
|
const hasValidCustomerEmail = watchedCustomerEmail && watchedCustomerEmail.trim().length > 0 && !customerEmailError;
|
|
11695
11753
|
return allParticipantsHaveNames &&
|
|
11696
11754
|
participantsWithinLimit &&
|
|
11697
|
-
participantsWithNames > 0 &&
|
|
11755
|
+
(participantFieldsConfig.name.required ? participantsWithNames > 0 : totalParticipantRows > 0) &&
|
|
11698
11756
|
hasValidCustomerName &&
|
|
11699
11757
|
hasValidCustomerEmail &&
|
|
11700
11758
|
watchedAcceptTerms;
|
|
@@ -11702,7 +11760,7 @@
|
|
|
11702
11760
|
y$1(() => {
|
|
11703
11761
|
if (appliedVouchers.length > 0) {
|
|
11704
11762
|
const newBaseTotal = eventDetails?.price
|
|
11705
|
-
? eventDetails.price * watchedParticipants.
|
|
11763
|
+
? eventDetails.price * watchedParticipants.length
|
|
11706
11764
|
: 0;
|
|
11707
11765
|
const currentUpsellsTotal = calculateUpsellsTotal();
|
|
11708
11766
|
const orderTotal = newBaseTotal + currentUpsellsTotal;
|
|
@@ -11747,7 +11805,7 @@
|
|
|
11747
11805
|
const currentParticipants = form.getValues("participants");
|
|
11748
11806
|
const availableSpots = eventDetails?.availableSpots || 0;
|
|
11749
11807
|
if (currentParticipants.length < availableSpots) {
|
|
11750
|
-
form.setValue("participants", [...currentParticipants, { name: "" }]);
|
|
11808
|
+
form.setValue("participants", [...currentParticipants, { name: "", level: undefined }]);
|
|
11751
11809
|
}
|
|
11752
11810
|
else {
|
|
11753
11811
|
alert(t$1("booking.maxParticipants", { count: availableSpots }));
|
|
@@ -11866,7 +11924,7 @@
|
|
|
11866
11924
|
justifyContent: "space-between",
|
|
11867
11925
|
alignItems: "center",
|
|
11868
11926
|
marginBottom: "16px",
|
|
11869
|
-
}, children: u$2("h2", { style: { ...sectionHeaderStyles$1, marginBottom: 0 }, children: t$1("booking.participants") }) }), u$2("div", { style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [watchedParticipants.map((_, index) => (u$2("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [u$2("div", { style: { display: "flex", gap: "12px", alignItems: "center" }, children: [u$2("div", { style: { flex: 1 }, children: [u$2("label", { htmlFor: `participant-name-${index}`, style: labelStyles$1, children: t$1("booking.participantName") }), u$2("input", { id: `participant-name-${index}`, ...form.register(`participants.${index}.name`), type: "text", style: inputStyles$1, placeholder: t$1("booking.participantNamePlaceholder") }), form.formState.errors.participants?.[index]?.name && (u$2("p", { style: errorTextStyles$1, children: form.formState.errors.participants[index]?.name?.message }))] }), u$2("div", { style: { width: "80px" }, children: [u$2("label", { htmlFor: `participant-age-${index}`, style: labelStyles$1, children: t$1("booking.participantAge") }), u$2("input", { id: `participant-age-${index}`, ...form.register(`participants.${index}.age`, {
|
|
11927
|
+
}, children: u$2("h2", { style: { ...sectionHeaderStyles$1, marginBottom: 0 }, children: t$1("booking.participants") }) }), u$2("div", { style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [watchedParticipants.map((_, index) => (u$2("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [u$2("div", { style: { display: "flex", gap: "12px", alignItems: "center" }, children: [participantFieldsConfig.name.enabled && (u$2("div", { style: { flex: 1 }, children: [u$2("label", { htmlFor: `participant-name-${index}`, style: labelStyles$1, children: t$1("booking.participantName") }), u$2("input", { id: `participant-name-${index}`, ...form.register(`participants.${index}.name`), type: "text", style: inputStyles$1, placeholder: t$1("booking.participantNamePlaceholder") }), form.formState.errors.participants?.[index]?.name && (u$2("p", { style: errorTextStyles$1, children: form.formState.errors.participants[index]?.name?.message }))] })), participantFieldsConfig.age.enabled && (u$2("div", { style: { width: "80px" }, children: [u$2("label", { htmlFor: `participant-age-${index}`, style: labelStyles$1, children: t$1("booking.participantAge") }), u$2("input", { id: `participant-age-${index}`, ...form.register(`participants.${index}.age`, {
|
|
11870
11928
|
setValueAs: (value) => {
|
|
11871
11929
|
if (value === "" || value === null || value === undefined) {
|
|
11872
11930
|
return undefined;
|
|
@@ -11874,7 +11932,7 @@
|
|
|
11874
11932
|
const num = Number(value);
|
|
11875
11933
|
return Number.isNaN(num) ? undefined : num;
|
|
11876
11934
|
},
|
|
11877
|
-
}), type: "number", min: "0", max: "120", style: inputStyles$1, placeholder: "25" })] }), watchedParticipants.length > 1 && (u$2("div", { children: [u$2("label", { style: { ...labelStyles$1, visibility: "hidden" }, children: "\u00A0" }), u$2("button", { type: "button", onClick: () => removeParticipant(index), style: {
|
|
11935
|
+
}), type: "number", min: "0", max: "120", style: inputStyles$1, placeholder: "25" })] })), watchedParticipants.length > 1 && (u$2("div", { children: [u$2("label", { style: { ...labelStyles$1, visibility: "hidden" }, children: "\u00A0" }), u$2("button", { type: "button", onClick: () => removeParticipant(index), style: {
|
|
11878
11936
|
color: "var(--bw-error-color)",
|
|
11879
11937
|
backgroundColor: "var(--bw-surface-color)",
|
|
11880
11938
|
border: "1px solid var(--bw-border-color)",
|
|
@@ -11890,7 +11948,7 @@
|
|
|
11890
11948
|
fontWeight: 700,
|
|
11891
11949
|
fontFamily: "var(--bw-font-family)",
|
|
11892
11950
|
padding: 0,
|
|
11893
|
-
}, children: "\u00D7" })] }))] }), upsells.length > 0 && (u$2("div", { style: participantUpsellStyles.container, children: upsells.map((upsell) => {
|
|
11951
|
+
}, children: "\u00D7" })] }))] }), participantFieldsConfig.level.enabled && (u$2("div", { style: { minWidth: "140px" }, children: [u$2("label", { htmlFor: `participant-level-${index}`, style: labelStyles$1, children: t$1("booking.participantLevel") }), u$2("select", { id: `participant-level-${index}`, ...form.register(`participants.${index}.level`), style: inputStyles$1, children: [u$2("option", { value: "", children: t$1("booking.participantLevelPlaceholder") }), participantLevelOptions.map((level) => (u$2("option", { value: level, children: t$1(`level.${level}`) }, level)))] }), form.formState.errors.participants?.[index]?.level && (u$2("p", { style: errorTextStyles$1, children: form.formState.errors.participants[index]?.level?.message }))] })), upsells.length > 0 && (u$2("div", { style: participantUpsellStyles.container, children: upsells.map((upsell) => {
|
|
11894
11952
|
const isSelected = (participantUpsells[index] || []).includes(upsell.id);
|
|
11895
11953
|
return (u$2("label", { htmlFor: `upsell-${index}-${upsell.id}`, style: isSelected ? participantUpsellStyles.labelSelected : participantUpsellStyles.label, children: [u$2("input", { id: `upsell-${index}-${upsell.id}`, type: "checkbox", style: participantUpsellStyles.checkbox, checked: isSelected, onChange: () => toggleParticipantUpsell(index, upsell.id) }), u$2("span", { style: { fontWeight: 500 }, children: upsell.name }), u$2("span", { style: { fontSize: "12px", opacity: 0.8 }, children: ["(+", formatCurrency(upsell.price), ")"] })] }, upsell.id));
|
|
11896
11954
|
}) }))] }, index))), watchedParticipants.length < eventDetails.availableSpots ? (u$2("div", { style: {
|
|
@@ -11919,9 +11977,9 @@
|
|
|
11919
11977
|
color: "var(--bw-text-color)",
|
|
11920
11978
|
fontWeight: 500,
|
|
11921
11979
|
fontFamily: "var(--bw-font-family)",
|
|
11922
|
-
}, children: [u$2("span", { style: { fontWeight: 200 }, children: [watchedParticipants.length > 1 ? watchedParticipants.
|
|
11980
|
+
}, children: [u$2("span", { style: { fontWeight: 200 }, children: [watchedParticipants.length > 1 ? watchedParticipants.length : 1, " x "] }), " ", formatCurrency(eventDetails.price)] })] }), upsellsTotal > 0 && (u$2("div", { style: { marginTop: "8px", paddingTop: "8px", borderTop: "1px dashed var(--bw-border-color)" }, children: [u$2("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "13px", display: "block", marginBottom: "4px" }, children: [t$1("common.extras"), ":"] }), upsells.map((upsell) => {
|
|
11923
11981
|
// Count how many participants have this upsell selected
|
|
11924
|
-
const countWithUpsell = watchedParticipants.filter((
|
|
11982
|
+
const countWithUpsell = watchedParticipants.filter((_, idx) => (participantUpsells[idx] || []).includes(upsell.id)).length;
|
|
11925
11983
|
if (countWithUpsell === 0)
|
|
11926
11984
|
return null;
|
|
11927
11985
|
const upsellLineTotal = upsell.price * countWithUpsell;
|
|
@@ -12022,15 +12080,17 @@
|
|
|
12022
12080
|
}, children: t$1("summary.remainingOnSite", { amount: formatCurrency(totalAmount - depositAmount) }) }))] })] })] }), u$2("div", { ref: paymentSectionRef, children: (stripePromise || systemConfig?.paymentProvider === "mollie") &&
|
|
12023
12081
|
(() => {
|
|
12024
12082
|
if (!isReadyForPayment()) {
|
|
12025
|
-
const participantsWithNames = watchedParticipants.filter((p) => p.name
|
|
12083
|
+
const participantsWithNames = watchedParticipants.filter((p) => p.name?.trim()).length;
|
|
12026
12084
|
const totalParticipantRows = watchedParticipants.length;
|
|
12027
12085
|
const participantsWithoutNames = totalParticipantRows - participantsWithNames;
|
|
12028
12086
|
const missing = [];
|
|
12029
|
-
if (
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12087
|
+
if (participantFieldsConfig.name.required) {
|
|
12088
|
+
if (participantsWithNames === 0) {
|
|
12089
|
+
missing.push(t$1("payment.needParticipant"));
|
|
12090
|
+
}
|
|
12091
|
+
else if (participantsWithoutNames > 0) {
|
|
12092
|
+
missing.push(t$1("payment.needAllNames", { count: totalParticipantRows }));
|
|
12093
|
+
}
|
|
12034
12094
|
}
|
|
12035
12095
|
if (participantsWithNames > (eventDetails?.availableSpots || 0)) {
|
|
12036
12096
|
missing.push(t$1("payment.reduceParticipants", { count: eventDetails?.availableSpots || 0 }));
|
|
@@ -12205,7 +12265,7 @@
|
|
|
12205
12265
|
try {
|
|
12206
12266
|
const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/get-booking-by-payment"), {
|
|
12207
12267
|
method: "POST",
|
|
12208
|
-
headers: createApiHeaders(config),
|
|
12268
|
+
headers: createApiHeaders(config, locale),
|
|
12209
12269
|
body: JSON.stringify(createRequestBody(config, {
|
|
12210
12270
|
paymentIntentId: targetPaymentIntentId,
|
|
12211
12271
|
})),
|
|
@@ -12439,7 +12499,7 @@
|
|
|
12439
12499
|
flexDirection: "column",
|
|
12440
12500
|
gap: "var(--bw-spacing-small)",
|
|
12441
12501
|
}, children: formData.participants
|
|
12442
|
-
.filter((p) => p.name
|
|
12502
|
+
.filter((p) => p.name?.trim() || p.age || p.level)
|
|
12443
12503
|
.map((participant, index) => (u$2("div", { className: "print-participant", style: {
|
|
12444
12504
|
display: "flex",
|
|
12445
12505
|
justifyContent: "space-between",
|
|
@@ -12450,11 +12510,15 @@
|
|
|
12450
12510
|
}, children: u$2("div", { className: "print-participant-info", children: [u$2("div", { className: "print-participant-name", style: {
|
|
12451
12511
|
color: "var(--bw-text-color)",
|
|
12452
12512
|
fontFamily: "var(--bw-font-family)",
|
|
12453
|
-
}, children: participant.name }), participant.age && (u$2("div", { className: "print-participant-age", style: {
|
|
12513
|
+
}, children: participant.name || `#${index + 1}` }), participant.age && (u$2("div", { className: "print-participant-age", style: {
|
|
12454
12514
|
color: "var(--bw-text-muted)",
|
|
12455
12515
|
fontSize: "var(--bw-font-size-small)",
|
|
12456
12516
|
fontFamily: "var(--bw-font-family)",
|
|
12457
|
-
}, children: t("success.age", { age: participant.age }) }))
|
|
12517
|
+
}, children: t("success.age", { age: participant.age }) })), participant.level && (u$2("div", { style: {
|
|
12518
|
+
color: "var(--bw-text-muted)",
|
|
12519
|
+
fontSize: "var(--bw-font-size-small)",
|
|
12520
|
+
fontFamily: "var(--bw-font-family)",
|
|
12521
|
+
}, children: [t("booking.participantLevel"), ": ", t(`level.${participant.level}`)] }))] }) }, index))) }) })] })), u$2("div", { className: "print-booking-card", style: {
|
|
12458
12522
|
backgroundColor: "var(--bw-surface-color)",
|
|
12459
12523
|
border: `1px solid var(--bw-border-color)`,
|
|
12460
12524
|
borderRadius: "var(--bw-border-radius)",
|
|
@@ -16633,11 +16697,7 @@
|
|
|
16633
16697
|
function UniversalBookingWidget(props) {
|
|
16634
16698
|
const [languagePolicy, setLanguagePolicy] = d$1(null);
|
|
16635
16699
|
const [orgTimezone, setOrgTimezone] = d$1("Europe/Berlin");
|
|
16636
|
-
const
|
|
16637
|
-
? languagePolicy.organizationLocale
|
|
16638
|
-
: undefined;
|
|
16639
|
-
const i18nConfigLocale = serverLockedLocale !== undefined ? serverLockedLocale : props.config.locale;
|
|
16640
|
-
const providerProps = i18nConfigLocale ? { configLocale: i18nConfigLocale } : {};
|
|
16700
|
+
const providerProps = props.config.locale ? { configLocale: props.config.locale } : {};
|
|
16641
16701
|
const showLanguagePicker = props.config.showLanguagePicker !== false &&
|
|
16642
16702
|
(languagePolicy === null || languagePolicy.multiLanguageEnabled);
|
|
16643
16703
|
return (u$2(I18nProvider, { ...providerProps, children: u$2(ShowLanguagePickerProvider, { value: showLanguagePicker, children: u$2(TimezoneProvider, { value: orgTimezone, children: u$2(UniversalBookingWidgetInner, { ...props, onWidgetLanguage: setLanguagePolicy, onTimezone: setOrgTimezone }) }) }) }));
|