@bigz-app/booking-widget 1.1.5 → 1.1.7

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/index.esm.js CHANGED
@@ -334,6 +334,7 @@ const de$1 = {
334
334
  "success.age": "{{age}} Jahre",
335
335
  "success.paymentSummary": "Zahlungsübersicht",
336
336
  "success.total": "Gesamtbetrag",
337
+ "success.discount": "Rabatt",
337
338
  "success.product": "Produkt",
338
339
  "success.contactInfo": "Kontaktdaten",
339
340
  "success.name": "Name:",
@@ -542,6 +543,7 @@ const en = {
542
543
  "success.age": "{{age}} years",
543
544
  "success.paymentSummary": "Payment Summary",
544
545
  "success.total": "Total",
546
+ "success.discount": "Discount",
545
547
  "success.product": "Product",
546
548
  "success.contactInfo": "Contact Information",
547
549
  "success.name": "Name:",
@@ -750,6 +752,7 @@ const es = {
750
752
  "success.age": "{{age}} años",
751
753
  "success.paymentSummary": "Resumen del pago",
752
754
  "success.total": "Total",
755
+ "success.discount": "Descuento",
753
756
  "success.product": "Producto",
754
757
  "success.contactInfo": "Datos de contacto",
755
758
  "success.name": "Nombre:",
@@ -958,6 +961,7 @@ const pt = {
958
961
  "success.age": "{{age}} anos",
959
962
  "success.paymentSummary": "Resumo do pagamento",
960
963
  "success.total": "Total",
964
+ "success.discount": "Desconto",
961
965
  "success.product": "Produto",
962
966
  "success.contactInfo": "Dados de contacto",
963
967
  "success.name": "Nome:",
@@ -1166,6 +1170,7 @@ const sv = {
1166
1170
  "success.age": "{{age}} år",
1167
1171
  "success.paymentSummary": "Betalningssammanfattning",
1168
1172
  "success.total": "Totalt",
1173
+ "success.discount": "Rabatt",
1169
1174
  "success.product": "Produkt",
1170
1175
  "success.contactInfo": "Kontaktuppgifter",
1171
1176
  "success.name": "Namn:",
@@ -1292,7 +1297,7 @@ function persistLocale(locale) {
1292
1297
  const I18nContext = createContext(null);
1293
1298
  function I18nProvider({ configLocale, children }) {
1294
1299
  // Priority: configLocale (site owner) > persisted user choice > browser language > "de"
1295
- // If configLocale is set, the site owner has locked the language don't restore user choice.
1300
+ // If configLocale is set, the site owner has locked the language - don't restore user choice.
1296
1301
  const [overrideLocale, setOverrideLocale] = useState(() => {
1297
1302
  if (configLocale)
1298
1303
  return null;
@@ -6479,6 +6484,7 @@ function PaymentForm({ config, eventDetails, formData, totalAmount, discountCode
6479
6484
  formData.participants,
6480
6485
  formData.customerEmail,
6481
6486
  formData.customerName,
6487
+ formData.comment,
6482
6488
  totalAmount,
6483
6489
  discountCode,
6484
6490
  giftCards,
@@ -11001,6 +11007,13 @@ function mergeStyles(...styles) {
11001
11007
  return Object.assign({}, ...styles.filter(Boolean));
11002
11008
  }
11003
11009
 
11010
+ function getEffectivePrice(upsell, round) {
11011
+ const dp = upsell.discountPercent ?? 0;
11012
+ if (dp <= 0)
11013
+ return upsell.price;
11014
+ const raw = Math.round(upsell.price * (100 - dp) / 100);
11015
+ return round ? Math.floor(raw / 100) * 100 : raw;
11016
+ }
11004
11017
  // Local style aliases from shared styles
11005
11018
  const cardStyles = cardStyles$1.base;
11006
11019
  const sectionHeaderStyles = sectionStyles.header;
@@ -11011,6 +11024,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11011
11024
  const t$1 = useTranslations();
11012
11025
  const { locale } = useLocale();
11013
11026
  const timezone = useTimezone();
11027
+ const roundEnabled = systemConfig?.roundPricesEnabled !== false;
11014
11028
  const [appliedVouchers, setAppliedVouchers] = useState([]);
11015
11029
  const paymentSectionRef = useRef(null);
11016
11030
  // Payment option: "deposit" or "full" - only relevant when deposit is available
@@ -11032,6 +11046,8 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11032
11046
  const watchedParticipants = form.watch("participants");
11033
11047
  const watchedCustomerName = form.watch("customerName");
11034
11048
  const watchedCustomerEmail = form.watch("customerEmail");
11049
+ const watchedComment = form.watch("comment");
11050
+ const watchedCustomerPhone = form.watch("customerPhone");
11035
11051
  const customerNameError = form.formState.errors.customerName;
11036
11052
  const customerEmailError = form.formState.errors.customerEmail;
11037
11053
  const watchedAcceptTerms = form.watch("acceptTerms");
@@ -11081,7 +11097,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11081
11097
  participantUpsellIds.forEach(upsellId => {
11082
11098
  const upsell = upsells.find(u => u.id === upsellId);
11083
11099
  if (upsell) {
11084
- total += upsell.price;
11100
+ total += getEffectivePrice(upsell, roundEnabled);
11085
11101
  }
11086
11102
  });
11087
11103
  }
@@ -11143,6 +11159,13 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11143
11159
  participantIndices,
11144
11160
  }));
11145
11161
  }, [participantUpsells, watchedParticipants]);
11162
+ const paymentFormData = useMemo(() => ({
11163
+ customerName: watchedCustomerName,
11164
+ customerEmail: watchedCustomerEmail,
11165
+ customerPhone: watchedCustomerPhone,
11166
+ participants: watchedParticipants,
11167
+ comment: watchedComment,
11168
+ }), [watchedCustomerName, watchedCustomerEmail, watchedCustomerPhone, watchedParticipants, watchedComment]);
11146
11169
  const appliedDiscountCode = appliedVouchers.find((v) => v.type === "discount");
11147
11170
  const appliedGiftCards = appliedVouchers.filter((v) => v.type === "giftCard");
11148
11171
  const handleVoucherValidated = useCallback((voucher, _error) => {
@@ -11357,7 +11380,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11357
11380
  padding: 0,
11358
11381
  }, children: "\u00D7" })] }))] }), upsells.length > 0 && (jsx("div", { style: participantUpsellStyles.container, children: upsells.map((upsell) => {
11359
11382
  const isSelected = (participantUpsells[index] || []).includes(upsell.id);
11360
- return (jsxs("label", { htmlFor: `upsell-${index}-${upsell.id}`, style: isSelected ? participantUpsellStyles.labelSelected : participantUpsellStyles.label, children: [jsx("input", { id: `upsell-${index}-${upsell.id}`, type: "checkbox", style: participantUpsellStyles.checkbox, checked: isSelected, onChange: () => toggleParticipantUpsell(index, upsell.id) }), jsx("span", { style: { fontWeight: 500 }, children: upsell.name }), jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: ["(+", formatCurrency(upsell.price), ")"] })] }, upsell.id));
11383
+ return (jsxs("label", { htmlFor: `upsell-${index}-${upsell.id}`, style: isSelected ? participantUpsellStyles.labelSelected : participantUpsellStyles.label, children: [jsx("input", { id: `upsell-${index}-${upsell.id}`, type: "checkbox", style: participantUpsellStyles.checkbox, checked: isSelected, onChange: () => toggleParticipantUpsell(index, upsell.id) }), jsx("span", { style: { fontWeight: 500 }, children: upsell.name }), jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: ["(+", formatCurrency(getEffectivePrice(upsell, roundEnabled)), ")"] })] }, upsell.id));
11361
11384
  }) }))] }, index))), watchedParticipants.length < eventDetails.availableSpots ? (jsx("div", { style: {
11362
11385
  display: "flex",
11363
11386
  flexDirection: "column",
@@ -11389,7 +11412,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11389
11412
  const countWithUpsell = watchedParticipants.filter((p, idx) => p.name.trim() && (participantUpsells[idx] || []).includes(upsell.id)).length;
11390
11413
  if (countWithUpsell === 0)
11391
11414
  return null;
11392
- const upsellLineTotal = upsell.price * countWithUpsell;
11415
+ const upsellLineTotal = getEffectivePrice(upsell, roundEnabled) * countWithUpsell;
11393
11416
  return (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: "13px" }, children: [jsxs("span", { style: { color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+ ", upsell.name, " (", countWithUpsell, "\u00D7)"] }), jsx("span", { style: { color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(upsellLineTotal) })] }, upsell.id));
11394
11417
  })] })), appliedVouchers.length > 0 && (jsxs(Fragment, { children: [jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsx("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)" }, children: t$1("summary.subtotal") }), jsx("span", { style: {
11395
11418
  fontFamily: "var(--bw-font-family)",
@@ -11514,7 +11537,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11514
11537
  : t$1("payment.fillRequired");
11515
11538
  return (jsx("div", { style: {
11516
11539
  ...cardStyles,
11517
- borderColor: "var(--bw-warning-color)",
11540
+ border: "1px solid var(--bw-warning-color)",
11518
11541
  color: "var(--bw-warning-color)",
11519
11542
  fontFamily: "var(--bw-font-family)",
11520
11543
  textAlign: "center",
@@ -11532,9 +11555,9 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11532
11555
  }
11533
11556
  : null;
11534
11557
  if (systemConfig?.paymentProvider === "mollie") {
11535
- return (jsxs("div", { style: cardStyles, children: [jsx("h2", { style: { ...sectionHeaderStyles }, children: t$1("summary.payment") }), jsx(MolliePaymentForm, { config: config, eventDetails: eventDetails, formData: form.getValues(), totalAmount: paymentAmount, discountCode: discountCodeProp, giftCards: appliedGiftCards, onSuccess: onSuccess, onError: onError, upsellSelections: aggregatedUpsellSelections(), mollieProfileId: systemConfig?.mollieProfileId, mollieTestmode: systemConfig?.mollieTestmode })] }));
11558
+ return (jsxs("div", { style: cardStyles, children: [jsx("h2", { style: { ...sectionHeaderStyles }, children: t$1("summary.payment") }), jsx(MolliePaymentForm, { config: config, eventDetails: eventDetails, formData: paymentFormData, totalAmount: paymentAmount, discountCode: discountCodeProp, giftCards: appliedGiftCards, onSuccess: onSuccess, onError: onError, upsellSelections: aggregatedUpsellSelections(), mollieProfileId: systemConfig?.mollieProfileId, mollieTestmode: systemConfig?.mollieTestmode })] }));
11536
11559
  }
11537
- return (jsxs("div", { style: cardStyles, children: [jsx("h2", { style: { ...sectionHeaderStyles }, children: t$1("summary.payment") }), jsx(PaymentForm, { config: config, eventDetails: eventDetails, formData: form.getValues(), totalAmount: paymentAmount, discountCode: discountCodeProp, giftCards: appliedGiftCards, onSuccess: onSuccess, onError: onError, systemConfig: systemConfig ?? null, stripePromise: stripePromise, stripeAppearance: stripeAppearance, upsellSelections: aggregatedUpsellSelections() })] }));
11560
+ return (jsxs("div", { style: cardStyles, children: [jsx("h2", { style: { ...sectionHeaderStyles }, children: t$1("summary.payment") }), jsx(PaymentForm, { config: config, eventDetails: eventDetails, formData: paymentFormData, totalAmount: paymentAmount, discountCode: discountCodeProp, giftCards: appliedGiftCards, onSuccess: onSuccess, onError: onError, systemConfig: systemConfig ?? null, stripePromise: stripePromise, stripeAppearance: stripeAppearance, upsellSelections: aggregatedUpsellSelections() })] }));
11538
11561
  })() })] })] })] }) }));
11539
11562
  }
11540
11563
 
@@ -11683,6 +11706,7 @@ const BookingSuccessModal = ({ isOpen, onClose, config, onError, paymentIntentId
11683
11706
  payments: data.payments,
11684
11707
  orderItems: data.orderItems,
11685
11708
  purchases: data.purchases || [],
11709
+ discount: data.discount || null,
11686
11710
  stripePaymentIntent: data.stripePaymentIntent,
11687
11711
  });
11688
11712
  setEventDetails({
@@ -11932,7 +11956,7 @@ const BookingSuccessModal = ({ isOpen, onClose, config, onError, paymentIntentId
11932
11956
  color: "var(--bw-text-color)",
11933
11957
  margin: "0",
11934
11958
  fontFamily: "var(--bw-font-family)",
11935
- }, children: t("success.paymentSummary") }) }), jsx("div", { className: "print-only", children: jsx("div", { className: "print-section-title", children: t("success.paymentSummary") }) }), jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [jsxs("div", { className: "print-hidden", style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-small)" }, children: [jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [eventDetails.name, " (", booking.participantCount, "x ", formatCurrency(eventDetails.price), ")"] }), jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(eventDetails.price * booking.participantCount) })] }), bookingData.purchases && bookingData.purchases.length > 0 && (jsx(Fragment, { children: bookingData.purchases.map((purchase) => (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [purchase.product?.name || t("success.product"), " (", purchase.quantity, "x ", formatCurrency(purchase.unitPrice), ")"] }), jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(purchase.totalPrice) })] }, purchase.id))) })), jsxs("div", { style: {
11959
+ }, children: t("success.paymentSummary") }) }), jsx("div", { className: "print-only", children: jsx("div", { className: "print-section-title", children: t("success.paymentSummary") }) }), jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [jsxs("div", { className: "print-hidden", style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-small)" }, children: [jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [eventDetails.name, " (", booking.participantCount, "x ", formatCurrency(eventDetails.price), ")"] }), jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(eventDetails.price * booking.participantCount) })] }), bookingData.discount && bookingData.discount.amount > 0 && (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("span", { style: { color: "var(--bw-success-color, #10B981)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [t("success.discount"), " (", bookingData.discount.code, ")"] }), jsxs("span", { style: { color: "var(--bw-success-color, #10B981)", fontFamily: "var(--bw-font-family)" }, children: ["-", formatCurrency(bookingData.discount.amount)] })] })), bookingData.purchases && bookingData.purchases.length > 0 && (jsx(Fragment, { children: bookingData.purchases.map((purchase) => (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [purchase.product?.name || t("success.product"), " (", purchase.quantity, "x ", formatCurrency(purchase.unitPrice), ")"] }), jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(purchase.totalPrice) })] }, purchase.id))) })), jsxs("div", { style: {
11936
11960
  display: "flex",
11937
11961
  justifyContent: "space-between",
11938
11962
  alignItems: "center",
@@ -13411,7 +13435,7 @@ function PromoDialog({ config, onClose, onCtaClick }) {
13411
13435
  color: "rgba(255, 255, 255, 0.85)",
13412
13436
  lineHeight: 1.5,
13413
13437
  margin: "0 0 16px 0",
13414
- }, children: [config.subtitle, config.discountAmount && (jsxs(Fragment, { children: [" ", jsxs("strong", { style: { color: "white" }, children: [config.discountAmount, " ", t("promo.discount")] })] }))] }), config.discountCode && (jsxs("div", { style: {
13438
+ }, children: [config.subtitle, config.discountAmount && (jsxs(Fragment, { children: [" - ", jsxs("strong", { style: { color: "white" }, children: [config.discountAmount, " ", t("promo.discount")] })] }))] }), config.discountCode && (jsxs("div", { style: {
13415
13439
  marginBottom: "16px",
13416
13440
  backgroundColor: "rgba(255,255,255,0.12)",
13417
13441
  borderRadius: "12px",
@@ -13496,7 +13520,9 @@ const cardBaseStyles = {
13496
13520
  flexDirection: "column",
13497
13521
  padding: "16px",
13498
13522
  backgroundColor: "var(--bw-surface-color)",
13499
- border: "2px solid var(--bw-border-color)",
13523
+ borderWidth: "2px",
13524
+ borderStyle: "solid",
13525
+ borderColor: "var(--bw-border-color)",
13500
13526
  borderRadius: "var(--bw-border-radius)",
13501
13527
  cursor: "pointer",
13502
13528
  transition: "all 0.2s ease",
@@ -13521,7 +13547,9 @@ const checkboxContainerStyles = {
13521
13547
  const checkboxInnerStyles = {
13522
13548
  width: "24px",
13523
13549
  height: "24px",
13524
- border: "2px solid var(--bw-border-color)",
13550
+ borderWidth: "2px",
13551
+ borderStyle: "solid",
13552
+ borderColor: "var(--bw-border-color)",
13525
13553
  borderRadius: "6px",
13526
13554
  display: "flex",
13527
13555
  alignItems: "center",
@@ -13647,10 +13675,11 @@ function formatUnavailableReason(reason, t) {
13647
13675
  return t("upsells.reason.notEnoughSpots", { eventTypeName: reason.eventTypeName });
13648
13676
  }
13649
13677
  }
13650
- function UpsellCard({ upsell, isSelected, participantCount, onSelect, }) {
13678
+ function UpsellCard({ upsell, isSelected, participantCount, onSelect, roundPricesEnabled = true, }) {
13651
13679
  const t = useTranslations();
13652
13680
  const { locale } = useLocale();
13653
- const totalPrice = upsell.price * participantCount;
13681
+ const effectivePrice = getEffectiveUpsellPrice(upsell, roundPricesEnabled);
13682
+ const totalPrice = effectivePrice * participantCount;
13654
13683
  const isDisabled = !upsell.available;
13655
13684
  const getCardStyles = () => {
13656
13685
  if (isDisabled)
@@ -13668,12 +13697,19 @@ function UpsellCard({ upsell, isSelected, participantCount, onSelect, }) {
13668
13697
  weekday: "short",
13669
13698
  day: "numeric",
13670
13699
  month: "short",
13671
- })] }), jsx("span", { style: { color: "var(--bw-text-muted)" }, children: t("upsells.spotsFree", { count: upsell.suggestedEventInstance.availableSpots }) })] }))] }), jsxs("div", { style: priceContainerStyles, children: [jsxs("span", { style: pricePerPersonStyles, children: [formatCurrency(upsell.price), "/", t("common.perPerson")] }), participantCount > 1 && (jsxs("span", { style: priceTotalStyles, children: ["= ", formatCurrency(totalPrice)] }))] }), isDisabled && (jsx("div", { style: unavailableOverlayStyles, children: jsx("span", { children: upsell.unavailableReason
13700
+ })] }), jsx("span", { style: { color: "var(--bw-text-muted)" }, children: t("upsells.spotsFree", { count: upsell.suggestedEventInstance.availableSpots }) })] }))] }), jsxs("div", { style: priceContainerStyles, children: [jsxs("span", { style: pricePerPersonStyles, children: [formatCurrency(effectivePrice), "/", t("common.perPerson")] }), participantCount > 1 && (jsxs("span", { style: priceTotalStyles, children: ["= ", formatCurrency(totalPrice)] }))] }), isDisabled && (jsx("div", { style: unavailableOverlayStyles, children: jsx("span", { children: upsell.unavailableReason
13672
13701
  ? formatUnavailableReason(upsell.unavailableReason, t)
13673
13702
  : t("upsells.notAvailable") }) }))] }));
13674
13703
  }
13675
13704
 
13676
- function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, isOpen, onClose, onSelect, onContinue, onBack, }) {
13705
+ function getEffectiveUpsellPrice(upsell, round = true) {
13706
+ const dp = upsell.discountPercent ?? 0;
13707
+ if (dp <= 0)
13708
+ return upsell.price;
13709
+ const raw = Math.round(upsell.price * (100 - dp) / 100);
13710
+ return round ? Math.floor(raw / 100) * 100 : raw;
13711
+ }
13712
+ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, isOpen, onClose, onSelect, onContinue, onBack, roundPricesEnabled = true, }) {
13677
13713
  const t = useTranslations();
13678
13714
  const selectUpsell = (upsellId) => {
13679
13715
  const exists = selectedUpsells.find((s) => s.upsellPackageId === upsellId);
@@ -13692,7 +13728,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
13692
13728
  return selectedUpsells.reduce((total, selection) => {
13693
13729
  const upsell = upsells.find((u) => u.id === selection.upsellPackageId);
13694
13730
  if (upsell) {
13695
- return total + upsell.price * selection.quantity;
13731
+ return total + getEffectiveUpsellPrice(upsell, roundPricesEnabled) * selection.quantity;
13696
13732
  }
13697
13733
  return total;
13698
13734
  }, 0);
@@ -13700,7 +13736,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
13700
13736
  const selectedTotal = calculateTotal();
13701
13737
  const selectedCount = selectedUpsells.length;
13702
13738
  const footerContent = (jsxs(Fragment, { children: [jsx("button", { type: "button", onClick: onBack, style: mergeStyles(buttonStyles.secondary, buttonStyles.fullWidth), children: t("common.back") }), jsx("button", { type: "button", onClick: onContinue, style: mergeStyles(buttonStyles.primary, buttonStyles.fullWidth), children: selectedCount === 0 ? t("button.continueWithout") : t("button.continue") })] }));
13703
- return (jsx(Sidebar, { isOpen: isOpen, onClose: onClose, title: t("upsells.title"), footer: footerContent, children: jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", padding: "16px 16px" }, children: [isLoading && (jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: "12px", padding: "40px 20px", ...textStyles.muted }, children: [spinner(), jsx("span", { children: t("upsells.loading") })] })), !isLoading && upsells.length === 0 && (jsx("div", { style: { textAlign: "center", padding: "40px 20px", ...textStyles.muted }, children: jsx("p", { children: t("upsells.noExtras") }) })), !isLoading && upsells.length > 0 && (jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", flex: 1, overflowY: "auto", paddingBottom: "16px" }, children: upsells.map((upsell) => (jsx(UpsellCard, { upsell: upsell, isSelected: isSelected(upsell.id), participantCount: participantCount, onSelect: () => selectUpsell(upsell.id) }, upsell.id))) })), selectedCount > 0 && (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "16px", paddingBottom: "16px", paddingTop: "16px", borderTop: "1px solid var(--bw-border-color)", fontSize: "14px" }, children: [jsx("span", { style: textStyles.muted, children: selectedCount === 1 ? t("upsells.selected", { count: selectedCount }) : t("upsells.selectedPlural", { count: selectedCount }) }), jsxs("span", { style: { fontWeight: 600, color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+", formatCurrency(selectedTotal)] })] }))] }) }));
13739
+ return (jsx(Sidebar, { isOpen: isOpen, onClose: onClose, title: t("upsells.title"), footer: footerContent, children: jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", padding: "16px 16px" }, children: [isLoading && (jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: "12px", padding: "40px 20px", ...textStyles.muted }, children: [spinner(), jsx("span", { children: t("upsells.loading") })] })), !isLoading && upsells.length === 0 && (jsx("div", { style: { textAlign: "center", padding: "40px 20px", ...textStyles.muted }, children: jsx("p", { children: t("upsells.noExtras") }) })), !isLoading && upsells.length > 0 && (jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", flex: 1, overflowY: "auto", paddingBottom: "16px" }, children: upsells.map((upsell) => (jsx(UpsellCard, { upsell: upsell, isSelected: isSelected(upsell.id), participantCount: participantCount, onSelect: () => selectUpsell(upsell.id), roundPricesEnabled: roundPricesEnabled }, upsell.id))) })), selectedCount > 0 && (jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "16px", paddingBottom: "16px", paddingTop: "16px", borderTop: "1px solid var(--bw-border-color)", fontSize: "14px" }, children: [jsx("span", { style: textStyles.muted, children: selectedCount === 1 ? t("upsells.selected", { count: selectedCount }) : t("upsells.selectedPlural", { count: selectedCount }) }), jsxs("span", { style: { fontWeight: 600, color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+", formatCurrency(selectedTotal)] })] }))] }) }));
13704
13740
  }
13705
13741
 
13706
13742
  // Main widget component
@@ -13960,6 +13996,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
13960
13996
  connectedAccountId: data.connectedAccountId,
13961
13997
  mollieProfileId: data.mollieProfileId,
13962
13998
  mollieTestmode: data.mollieTestmode,
13999
+ roundPricesEnabled: data.roundPricesEnabled ?? true,
13963
14000
  });
13964
14001
  }
13965
14002
  if (data.stripePublishableKey) {
@@ -14018,6 +14055,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14018
14055
  connectedAccountId: data.connectedAccountId,
14019
14056
  mollieProfileId: data.mollieProfileId,
14020
14057
  mollieTestmode: data.mollieTestmode,
14058
+ roundPricesEnabled: data.roundPricesEnabled ?? true,
14021
14059
  });
14022
14060
  if (!stripePromise && data.stripePublishableKey) {
14023
14061
  const stripeOptions = {
@@ -14166,6 +14204,8 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14166
14204
  const handleBookingSuccess = (result) => {
14167
14205
  setIsSuccess(true);
14168
14206
  setSuccessPaymentIntentId(result.paymentIntent.id);
14207
+ setSidebarOpen(false);
14208
+ setShouldRenderBookingForm(false);
14169
14209
  config.onSuccess?.(result);
14170
14210
  };
14171
14211
  const handleBookingError = (errorMessage) => {
@@ -14422,7 +14462,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14422
14462
  setShouldRenderInstanceSelection(true);
14423
14463
  }
14424
14464
  }, children: config.buttonText ||
14425
- (isDirectInstanceMode ? t("button.bookNow") : t("button.selectDate")) }), shouldRenderInstanceSelection && (jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), onBackToEventTypes: () => setSidebarOpen(false), selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14465
+ (isDirectInstanceMode ? t("button.bookNow") : t("button.selectDate")) }), shouldRenderInstanceSelection && (jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack, roundPricesEnabled: systemConfig?.roundPricesEnabled !== false })), shouldRenderBookingForm && eventDetails && (jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), onBackToEventTypes: () => setSidebarOpen(false), selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14426
14466
  setIsSuccess(false);
14427
14467
  setCurrentStep("eventTypes");
14428
14468
  setSidebarOpen(false);
@@ -14469,7 +14509,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14469
14509
  };
14470
14510
  };
14471
14511
  const backHandlers = getBackHandlers();
14472
- return (jsxs(StyleProvider, { config: config, children: [jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: backHandlers.onBackToEventInstances, onBackToEventTypes: backHandlers.onBackToEventTypes, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14512
+ return (jsxs(StyleProvider, { config: config, children: [jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack, roundPricesEnabled: systemConfig?.roundPricesEnabled !== false })), shouldRenderBookingForm && eventDetails && (jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: backHandlers.onBackToEventInstances, onBackToEventTypes: backHandlers.onBackToEventTypes, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14473
14513
  setIsSuccess(false);
14474
14514
  setCurrentStep("eventTypes");
14475
14515
  setSuccessPaymentIntentId(null);