@bigz-app/booking-widget 0.3.6 → 0.3.9
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 +1016 -300
- package/dist/booking-widget.js.map +1 -1
- package/dist/components/BookingForm.d.ts.map +1 -1
- package/dist/components/EventInstanceSelection.d.ts.map +1 -1
- package/dist/components/PaymentForm.d.ts +3 -1
- package/dist/components/PaymentForm.d.ts.map +1 -1
- package/dist/components/PromoDialog.d.ts +7 -0
- package/dist/components/PromoDialog.d.ts.map +1 -0
- package/dist/components/UniversalBookingWidget.d.ts.map +1 -1
- package/dist/components/VoucherInput.d.ts +29 -0
- package/dist/components/VoucherInput.d.ts.map +1 -0
- package/dist/index.cjs +1017 -301
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +1018 -302
- package/dist/index.esm.js.map +1 -1
- package/package.json +77 -70
package/dist/booking-widget.js
CHANGED
|
@@ -6946,7 +6946,7 @@
|
|
|
6946
6946
|
// Convert double underscores to HTML underline tags for React Markdown
|
|
6947
6947
|
return markdown.replace(/__([^_]+)__/g, "<u>$1</u>");
|
|
6948
6948
|
};
|
|
6949
|
-
const IconCheck$
|
|
6949
|
+
const IconCheck$2 = ({ size = 16, color = "#10b981" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: u$2("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
6950
6950
|
const IconWave$1 = ({ size = 20, color = "#0ea5e9" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("path", { d: "M2 18c2-2 6-2 8 0s6 2 8 0 6-2 8 0" }), u$2("path", { d: "M2 12c2-2 6-2 8 0s6 2 8 0 6-2 8 0" }), u$2("path", { d: "M2 6c2-2 6-2 8 0s6 2 8 0 6-2 8 0" })] }));
|
|
6951
6951
|
function EventTypeDetailsDialog({ isOpen, onClose, eventType, onEventTypeSelect, }) {
|
|
6952
6952
|
if (!isOpen || !eventType)
|
|
@@ -6993,7 +6993,7 @@
|
|
|
6993
6993
|
fontSize: "16px",
|
|
6994
6994
|
lineHeight: "1.6",
|
|
6995
6995
|
color: "var(--bw-text-color)",
|
|
6996
|
-
}, children: [u$2("div", { style: { marginTop: "4px", flexShrink: 0 }, children: u$2(IconCheck$
|
|
6996
|
+
}, children: [u$2("div", { style: { marginTop: "4px", flexShrink: 0 }, children: u$2(IconCheck$2, { size: 16, color: "var(--bw-success-color)" }) }), u$2("span", { children: highlight.trim() })] }, index))) }) }) }))] }), eventType.description && (u$2("div", { style: {
|
|
6997
6997
|
marginBottom: "24px",
|
|
6998
6998
|
color: "var(--bw-text-muted)",
|
|
6999
6999
|
fontSize: "16px",
|
|
@@ -7302,7 +7302,7 @@
|
|
|
7302
7302
|
// Custom minimal SVG icons (Lucide-style)
|
|
7303
7303
|
const IconClock = ({ size = 16, color = "#10b981" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("circle", { cx: "12", cy: "12", r: "10" }), u$2("polyline", { points: "12 6 12 12 16 14" })] }));
|
|
7304
7304
|
const IconCalendar = ({ size = 16, color = "#3b82f6" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }), u$2("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), u$2("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), u$2("line", { x1: "3", y1: "10", x2: "21", y2: "10" })] }));
|
|
7305
|
-
const IconCheck = ({ size = 16, color = "#10b981" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: u$2("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
7305
|
+
const IconCheck$1 = ({ size = 16, color = "#10b981" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: u$2("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
7306
7306
|
// Wave icon for booking action
|
|
7307
7307
|
const IconWave = ({ size = 20, color = "#0ea5e9" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("path", { d: "M2 18c2-2 6-2 8 0s6 2 8 0 6-2 8 0" }), u$2("path", { d: "M2 12c2-2 6-2 8 0s6 2 8 0 6-2 8 0" }), u$2("path", { d: "M2 6c2-2 6-2 8 0s6 2 8 0 6-2 8 0" })] }));
|
|
7308
7308
|
// Loading skeleton component that matches the actual design
|
|
@@ -7766,7 +7766,7 @@
|
|
|
7766
7766
|
color: "var(--bw-text-muted)",
|
|
7767
7767
|
position: "relative",
|
|
7768
7768
|
maxWidth: "100%",
|
|
7769
|
-
}, children: [u$2("div", { style: { marginTop: "4px", flexShrink: 0 }, children: u$2(IconCheck, { size: 16, color: "var(--bw-success-color)" }) }), u$2("span", { style: {
|
|
7769
|
+
}, children: [u$2("div", { style: { marginTop: "4px", flexShrink: 0 }, children: u$2(IconCheck$1, { size: 16, color: "var(--bw-success-color)" }) }), u$2("span", { style: {
|
|
7770
7770
|
textOverflow: "ellipsis",
|
|
7771
7771
|
overflow: "hidden",
|
|
7772
7772
|
whiteSpace: "nowrap",
|
|
@@ -9196,6 +9196,110 @@
|
|
|
9196
9196
|
|
|
9197
9197
|
var reactStripe_umdExports = reactStripe_umd.exports;
|
|
9198
9198
|
|
|
9199
|
+
// Component for bookings fully covered by gift cards (no Stripe payment needed)
|
|
9200
|
+
function GiftCardOnlyBooking({ config, eventDetails, formData, discountCode, giftCards, onSuccess, onError, }) {
|
|
9201
|
+
const [isLoading, setIsLoading] = d$1(false);
|
|
9202
|
+
const [error, setError] = d$1(null);
|
|
9203
|
+
const handleBooking = async () => {
|
|
9204
|
+
setIsLoading(true);
|
|
9205
|
+
setError(null);
|
|
9206
|
+
try {
|
|
9207
|
+
// Create booking directly without Stripe payment
|
|
9208
|
+
const requestData = {
|
|
9209
|
+
eventInstanceId: config.eventInstanceId || eventDetails.id,
|
|
9210
|
+
organizationId: config.organizationId,
|
|
9211
|
+
participants: formData.participants.filter((p) => p.name?.trim()),
|
|
9212
|
+
discountCode: discountCode?.code,
|
|
9213
|
+
giftCardCodes: giftCards.map((gc) => gc.code),
|
|
9214
|
+
customerName: formData.customerName?.trim(),
|
|
9215
|
+
customerEmail: formData.customerEmail?.trim(),
|
|
9216
|
+
customerPhone: formData.customerPhone?.trim(),
|
|
9217
|
+
comment: formData.comment?.trim(),
|
|
9218
|
+
paymentMethod: "gift_card",
|
|
9219
|
+
};
|
|
9220
|
+
const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/create-gift-card-booking"), {
|
|
9221
|
+
method: "POST",
|
|
9222
|
+
headers: createApiHeaders(config),
|
|
9223
|
+
body: JSON.stringify(createRequestBody(config, requestData)),
|
|
9224
|
+
});
|
|
9225
|
+
const data = await response.json();
|
|
9226
|
+
if (response.ok) {
|
|
9227
|
+
onSuccess({
|
|
9228
|
+
booking: data.booking,
|
|
9229
|
+
order: data.order,
|
|
9230
|
+
giftCardRedemptions: data.giftCardRedemptions,
|
|
9231
|
+
});
|
|
9232
|
+
}
|
|
9233
|
+
else {
|
|
9234
|
+
setError(data.error || "Fehler beim Erstellen der Buchung");
|
|
9235
|
+
onError(data.error || "Fehler beim Erstellen der Buchung");
|
|
9236
|
+
}
|
|
9237
|
+
}
|
|
9238
|
+
catch (err) {
|
|
9239
|
+
setError(err.message || "Fehler beim Erstellen der Buchung");
|
|
9240
|
+
onError(err.message || "Fehler beim Erstellen der Buchung");
|
|
9241
|
+
}
|
|
9242
|
+
finally {
|
|
9243
|
+
setIsLoading(false);
|
|
9244
|
+
}
|
|
9245
|
+
};
|
|
9246
|
+
const totalGiftCardAmount = giftCards.reduce((sum, gc) => sum + (gc.balanceToUse || gc.discountAmount || 0), 0);
|
|
9247
|
+
return (u$2("div", { style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing)" }, children: [u$2("div", { style: {
|
|
9248
|
+
backgroundColor: "var(--bw-success-color)15",
|
|
9249
|
+
border: "1px solid var(--bw-success-color)40",
|
|
9250
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9251
|
+
padding: "var(--bw-spacing)",
|
|
9252
|
+
}, children: [u$2("div", { style: {
|
|
9253
|
+
display: "flex",
|
|
9254
|
+
alignItems: "center",
|
|
9255
|
+
gap: "8px",
|
|
9256
|
+
marginBottom: "8px",
|
|
9257
|
+
color: "var(--bw-success-color)",
|
|
9258
|
+
fontFamily: "var(--bw-font-family)",
|
|
9259
|
+
fontWeight: "600",
|
|
9260
|
+
}, children: "\uD83C\uDF81 Vollst\u00E4ndig durch Gutschein(e) gedeckt" }), u$2("div", { style: {
|
|
9261
|
+
fontSize: "var(--bw-font-size)",
|
|
9262
|
+
color: "var(--bw-text-muted)",
|
|
9263
|
+
fontFamily: "var(--bw-font-family)",
|
|
9264
|
+
}, children: ["Gutschein-Guthaben: ", formatCurrency(totalGiftCardAmount)] })] }), error && (u$2("div", { style: {
|
|
9265
|
+
backgroundColor: "var(--bw-error-color)15",
|
|
9266
|
+
border: "1px solid var(--bw-error-color)40",
|
|
9267
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9268
|
+
padding: "var(--bw-spacing)",
|
|
9269
|
+
color: "var(--bw-error-color)",
|
|
9270
|
+
fontSize: "var(--bw-font-size)",
|
|
9271
|
+
fontFamily: "var(--bw-font-family)",
|
|
9272
|
+
}, children: ["\u26A0\uFE0F ", error] })), u$2("button", { type: "button", onClick: handleBooking, disabled: isLoading, style: {
|
|
9273
|
+
width: "100%",
|
|
9274
|
+
padding: "12px 24px",
|
|
9275
|
+
backgroundColor: "var(--bw-highlight-color)",
|
|
9276
|
+
color: "#fff",
|
|
9277
|
+
border: "none",
|
|
9278
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9279
|
+
fontSize: "var(--bw-font-size)",
|
|
9280
|
+
fontWeight: "600",
|
|
9281
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
9282
|
+
opacity: isLoading ? 0.6 : 1,
|
|
9283
|
+
transition: "all 0.2s ease",
|
|
9284
|
+
fontFamily: "var(--bw-font-family)",
|
|
9285
|
+
display: "flex",
|
|
9286
|
+
alignItems: "center",
|
|
9287
|
+
justifyContent: "center",
|
|
9288
|
+
gap: "8px",
|
|
9289
|
+
}, children: isLoading ? (u$2(k$3, { children: [u$2("div", { style: {
|
|
9290
|
+
width: "16px",
|
|
9291
|
+
height: "16px",
|
|
9292
|
+
border: "2px solid #fff",
|
|
9293
|
+
borderTopColor: "transparent",
|
|
9294
|
+
borderRadius: "50%",
|
|
9295
|
+
animation: "spin 1s linear infinite",
|
|
9296
|
+
} }), "Buchung wird erstellt..."] })) : ("Mit Gutschein buchen") }), u$2("style", { children: `
|
|
9297
|
+
@keyframes spin {
|
|
9298
|
+
from { transform: rotate(0deg); }
|
|
9299
|
+
to { transform: rotate(360deg); }
|
|
9300
|
+
}
|
|
9301
|
+
` })] }));
|
|
9302
|
+
}
|
|
9199
9303
|
const spinner$1 = (borderColor) => (u$2("div", { style: {
|
|
9200
9304
|
width: "auto",
|
|
9201
9305
|
height: "auto",
|
|
@@ -9212,7 +9316,7 @@
|
|
|
9212
9316
|
borderRadius: "50%",
|
|
9213
9317
|
} }) }));
|
|
9214
9318
|
// Inner component that uses the Stripe hooks
|
|
9215
|
-
function PaymentFormInner({ config, eventDetails, formData, totalAmount, discountCode, onSuccess, onError, }) {
|
|
9319
|
+
function PaymentFormInner({ config, eventDetails, formData, totalAmount, discountCode, giftCards, onSuccess, onError, }) {
|
|
9216
9320
|
const stripe = reactStripe_umdExports.useStripe();
|
|
9217
9321
|
const elements = reactStripe_umdExports.useElements();
|
|
9218
9322
|
const [isLoading, setIsLoading] = d$1(false);
|
|
@@ -9343,7 +9447,7 @@
|
|
|
9343
9447
|
` })] }));
|
|
9344
9448
|
}
|
|
9345
9449
|
// Main PaymentForm component that handles payment intent creation and Elements wrapper
|
|
9346
|
-
function PaymentForm({ config, eventDetails, formData, totalAmount, discountCode, onSuccess, onError, systemConfig, stripePromise, stripeAppearance, }) {
|
|
9450
|
+
function PaymentForm({ config, eventDetails, formData, totalAmount, discountCode, giftCards, onSuccess, onError, systemConfig, stripePromise, stripeAppearance, }) {
|
|
9347
9451
|
const [clientSecret, setClientSecret] = d$1(null);
|
|
9348
9452
|
const [paymentIntentId, setPaymentIntentId] = d$1(null);
|
|
9349
9453
|
const [isCreatingPaymentIntent, setIsCreatingPaymentIntent] = d$1(false);
|
|
@@ -9439,6 +9543,7 @@
|
|
|
9439
9543
|
currency: "eur",
|
|
9440
9544
|
participants: formData.participants.filter((p) => p.name?.trim()),
|
|
9441
9545
|
discountCode: discountCode?.code,
|
|
9546
|
+
giftCardCodes: giftCards?.map((gc) => gc.code) || [],
|
|
9442
9547
|
customerName: formData.customerName?.trim(),
|
|
9443
9548
|
customerEmail: formData.customerEmail?.trim(),
|
|
9444
9549
|
customerPhone: formData.customerPhone?.trim(),
|
|
@@ -9500,8 +9605,21 @@
|
|
|
9500
9605
|
formData.customerName,
|
|
9501
9606
|
totalAmount,
|
|
9502
9607
|
discountCode,
|
|
9608
|
+
giftCards,
|
|
9503
9609
|
config,
|
|
9504
9610
|
]);
|
|
9611
|
+
// Calculate total gift card coverage
|
|
9612
|
+
const totalGiftCardAmount = giftCards?.reduce((sum, gc) => sum + (gc.balanceToUse || gc.discountAmount || 0), 0) || 0;
|
|
9613
|
+
const baseTotal = eventDetails?.price
|
|
9614
|
+
? eventDetails.price * (formData.participants?.filter((p) => p.name?.trim()).length || 0)
|
|
9615
|
+
: 0;
|
|
9616
|
+
const discountAmount = discountCode?.discountAmount || 0;
|
|
9617
|
+
const amountAfterDiscount = Math.max(0, baseTotal - discountAmount);
|
|
9618
|
+
const isFullyCoveredByGiftCards = totalGiftCardAmount >= amountAfterDiscount && amountAfterDiscount > 0;
|
|
9619
|
+
// If gift cards fully cover the payment, show a simplified booking button
|
|
9620
|
+
if (isFullyCoveredByGiftCards && totalAmount <= 0) {
|
|
9621
|
+
return (u$2(GiftCardOnlyBooking, { config: config, eventDetails: eventDetails, formData: formData, discountCode: discountCode, giftCards: giftCards || [], onSuccess: onSuccess, onError: onError }));
|
|
9622
|
+
}
|
|
9505
9623
|
// Show loading state while creating payment intent
|
|
9506
9624
|
if (isCreatingPaymentIntent || !clientSecret) {
|
|
9507
9625
|
return (u$2("div", { style: {
|
|
@@ -9535,7 +9653,7 @@
|
|
|
9535
9653
|
clientSecret,
|
|
9536
9654
|
appearance: stripeAppearance || { theme: "stripe" },
|
|
9537
9655
|
locale: config.locale || "de",
|
|
9538
|
-
}, children: u$2(PaymentFormInner, { config: config, eventDetails: eventDetails, formData: formData, totalAmount: totalAmount, discountCode: discountCode, onSuccess: (result) => {
|
|
9656
|
+
}, children: u$2(PaymentFormInner, { config: config, eventDetails: eventDetails, formData: formData, totalAmount: totalAmount, discountCode: discountCode, giftCards: giftCards, onSuccess: (result) => {
|
|
9539
9657
|
// Clear persisted PI data on successful payment
|
|
9540
9658
|
clearPersistedPaymentIntent();
|
|
9541
9659
|
setPaymentIntentId(null);
|
|
@@ -9740,6 +9858,222 @@
|
|
|
9740
9858
|
}, children: children }))] }));
|
|
9741
9859
|
}
|
|
9742
9860
|
|
|
9861
|
+
// Icons
|
|
9862
|
+
const IconTicket = ({ size = 20, color = "currentColor" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("path", { d: "M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z" }), u$2("path", { d: "M13 5v2" }), u$2("path", { d: "M13 17v2" }), u$2("path", { d: "M13 11v2" })] }));
|
|
9863
|
+
const IconGift = ({ size = 20, color = "currentColor" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("rect", { x: "3", y: "8", width: "18", height: "4", rx: "1" }), u$2("path", { d: "M12 8v13" }), u$2("path", { d: "M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7" }), u$2("path", { d: "M7.5 8a2.5 2.5 0 0 1 0-5A4.8 8 0 0 1 12 8a4.8 8 0 0 1 4.5-5 2.5 2.5 0 0 1 0 5" })] }));
|
|
9864
|
+
const IconCheck = ({ size = 16, color = "currentColor" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: u$2("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
9865
|
+
const IconX = ({ size = 16, color = "currentColor" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), u$2("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
|
|
9866
|
+
const IconSpinner = ({ size = 16, color = "currentColor" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { animation: "spin 1s linear infinite" }, children: u$2("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }));
|
|
9867
|
+
function VoucherInput({ config, orderValue, eventInstanceId, customerEmail, onVoucherValidated, appliedVouchers, onRemoveVoucher, disabled = false, }) {
|
|
9868
|
+
const [inputValue, setInputValue] = d$1("");
|
|
9869
|
+
const [isLoading, setIsLoading] = d$1(false);
|
|
9870
|
+
const [error, setError] = d$1(null);
|
|
9871
|
+
const [isExpanded, setIsExpanded] = d$1(false);
|
|
9872
|
+
// Check if a discount code is already applied (only one allowed)
|
|
9873
|
+
const hasDiscountCode = appliedVouchers.some((v) => v.type === "discount");
|
|
9874
|
+
const validateVoucher = q$2(async (code) => {
|
|
9875
|
+
if (!code.trim()) {
|
|
9876
|
+
setError(null);
|
|
9877
|
+
return;
|
|
9878
|
+
}
|
|
9879
|
+
// Check if code is already applied
|
|
9880
|
+
if (appliedVouchers.some((v) => v.code.toUpperCase() === code.toUpperCase())) {
|
|
9881
|
+
setError("Dieser Code wurde bereits angewendet");
|
|
9882
|
+
return;
|
|
9883
|
+
}
|
|
9884
|
+
setIsLoading(true);
|
|
9885
|
+
setError(null);
|
|
9886
|
+
try {
|
|
9887
|
+
const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/validate-voucher"), {
|
|
9888
|
+
method: "POST",
|
|
9889
|
+
headers: createApiHeaders(config),
|
|
9890
|
+
body: JSON.stringify(createRequestBody(config, {
|
|
9891
|
+
code: code.trim(),
|
|
9892
|
+
orderValue: orderValue,
|
|
9893
|
+
eventInstanceId: eventInstanceId,
|
|
9894
|
+
customerEmail: customerEmail,
|
|
9895
|
+
})),
|
|
9896
|
+
});
|
|
9897
|
+
const data = await response.json();
|
|
9898
|
+
if (data.valid && data.voucher) {
|
|
9899
|
+
// Check if trying to add a second discount code
|
|
9900
|
+
if (data.voucher.type === "discount" && hasDiscountCode) {
|
|
9901
|
+
setError("Es kann nur ein Rabattcode verwendet werden");
|
|
9902
|
+
onVoucherValidated(null, "Es kann nur ein Rabattcode verwendet werden");
|
|
9903
|
+
return;
|
|
9904
|
+
}
|
|
9905
|
+
onVoucherValidated(data.voucher);
|
|
9906
|
+
setInputValue("");
|
|
9907
|
+
setError(null);
|
|
9908
|
+
}
|
|
9909
|
+
else {
|
|
9910
|
+
setError(data.error || "Code nicht gefunden oder ungültig");
|
|
9911
|
+
onVoucherValidated(null, data.error);
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9914
|
+
catch (err) {
|
|
9915
|
+
const errorMsg = "Fehler beim Validieren des Codes";
|
|
9916
|
+
setError(errorMsg);
|
|
9917
|
+
onVoucherValidated(null, errorMsg);
|
|
9918
|
+
}
|
|
9919
|
+
finally {
|
|
9920
|
+
setIsLoading(false);
|
|
9921
|
+
}
|
|
9922
|
+
}, [
|
|
9923
|
+
config,
|
|
9924
|
+
orderValue,
|
|
9925
|
+
eventInstanceId,
|
|
9926
|
+
customerEmail,
|
|
9927
|
+
appliedVouchers,
|
|
9928
|
+
hasDiscountCode,
|
|
9929
|
+
onVoucherValidated,
|
|
9930
|
+
]);
|
|
9931
|
+
const handleSubmit = () => {
|
|
9932
|
+
if (inputValue.trim() && !isLoading && !disabled) {
|
|
9933
|
+
validateVoucher(inputValue);
|
|
9934
|
+
}
|
|
9935
|
+
};
|
|
9936
|
+
const handleKeyDown = (e) => {
|
|
9937
|
+
if (e.key === "Enter") {
|
|
9938
|
+
e.preventDefault();
|
|
9939
|
+
if (inputValue.trim() && !isLoading && !disabled) {
|
|
9940
|
+
validateVoucher(inputValue);
|
|
9941
|
+
}
|
|
9942
|
+
}
|
|
9943
|
+
};
|
|
9944
|
+
const inputStyle = {
|
|
9945
|
+
flex: 1,
|
|
9946
|
+
padding: "10px 12px",
|
|
9947
|
+
backgroundColor: "var(--bw-background-color)",
|
|
9948
|
+
border: "1px solid var(--bw-border-color)",
|
|
9949
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9950
|
+
color: "var(--bw-text-color)",
|
|
9951
|
+
fontSize: "var(--bw-font-size)",
|
|
9952
|
+
fontFamily: "var(--bw-font-family)",
|
|
9953
|
+
outline: "none",
|
|
9954
|
+
transition: "all 0.2s ease",
|
|
9955
|
+
textTransform: "uppercase",
|
|
9956
|
+
};
|
|
9957
|
+
const buttonStyle = {
|
|
9958
|
+
padding: "10px 16px",
|
|
9959
|
+
backgroundColor: "var(--bw-highlight-color)",
|
|
9960
|
+
border: "none",
|
|
9961
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9962
|
+
color: "#fff",
|
|
9963
|
+
fontSize: "var(--bw-font-size)",
|
|
9964
|
+
fontFamily: "var(--bw-font-family)",
|
|
9965
|
+
fontWeight: "600",
|
|
9966
|
+
cursor: disabled || isLoading ? "not-allowed" : "pointer",
|
|
9967
|
+
opacity: disabled || isLoading ? 0.6 : 1,
|
|
9968
|
+
transition: "all 0.2s ease",
|
|
9969
|
+
display: "flex",
|
|
9970
|
+
alignItems: "center",
|
|
9971
|
+
justifyContent: "center",
|
|
9972
|
+
gap: "6px",
|
|
9973
|
+
minWidth: "100px",
|
|
9974
|
+
};
|
|
9975
|
+
const appliedVoucherStyle = {
|
|
9976
|
+
display: "flex",
|
|
9977
|
+
alignItems: "center",
|
|
9978
|
+
justifyContent: "space-between",
|
|
9979
|
+
padding: "10px 12px",
|
|
9980
|
+
backgroundColor: "var(--bw-surface-color)",
|
|
9981
|
+
border: "1px solid var(--bw-border-color)",
|
|
9982
|
+
borderRadius: "var(--bw-border-radius)",
|
|
9983
|
+
marginBottom: "8px",
|
|
9984
|
+
};
|
|
9985
|
+
const removeButtonStyle = {
|
|
9986
|
+
background: "none",
|
|
9987
|
+
border: "none",
|
|
9988
|
+
padding: "4px",
|
|
9989
|
+
cursor: "pointer",
|
|
9990
|
+
color: "var(--bw-error-color)",
|
|
9991
|
+
display: "flex",
|
|
9992
|
+
alignItems: "center",
|
|
9993
|
+
justifyContent: "center",
|
|
9994
|
+
borderRadius: "50%",
|
|
9995
|
+
transition: "background-color 0.2s ease",
|
|
9996
|
+
};
|
|
9997
|
+
return (u$2("div", { style: {
|
|
9998
|
+
backgroundColor: "var(--bw-surface-color)",
|
|
9999
|
+
border: "1px solid var(--bw-border-color)",
|
|
10000
|
+
borderRadius: "var(--bw-border-radius)",
|
|
10001
|
+
overflow: "hidden",
|
|
10002
|
+
}, children: [u$2("button", { type: "button", onClick: () => setIsExpanded(!isExpanded), style: {
|
|
10003
|
+
width: "100%",
|
|
10004
|
+
padding: "var(--bw-spacing)",
|
|
10005
|
+
backgroundColor: "transparent",
|
|
10006
|
+
border: "none",
|
|
10007
|
+
cursor: "pointer",
|
|
10008
|
+
display: "flex",
|
|
10009
|
+
alignItems: "center",
|
|
10010
|
+
justifyContent: "space-between",
|
|
10011
|
+
color: "var(--bw-text-color)",
|
|
10012
|
+
fontFamily: "var(--bw-font-family)",
|
|
10013
|
+
fontSize: "var(--bw-font-size)",
|
|
10014
|
+
fontWeight: "500",
|
|
10015
|
+
}, children: [u$2("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [u$2(IconTicket, { size: 18, color: "var(--bw-highlight-color)" }), "Rabattcode oder Gutschein", appliedVouchers.length > 0 && (u$2("span", { style: {
|
|
10016
|
+
backgroundColor: "var(--bw-highlight-color)",
|
|
10017
|
+
color: "#fff",
|
|
10018
|
+
padding: "2px 8px",
|
|
10019
|
+
borderRadius: "12px",
|
|
10020
|
+
fontSize: "12px",
|
|
10021
|
+
fontWeight: "600",
|
|
10022
|
+
}, children: appliedVouchers.length }))] }), u$2("span", { style: {
|
|
10023
|
+
transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
|
|
10024
|
+
transition: "transform 0.2s ease",
|
|
10025
|
+
}, children: "\u25BC" })] }), isExpanded && (u$2("div", { style: { padding: "0 var(--bw-spacing) var(--bw-spacing)" }, children: [appliedVouchers.length > 0 && (u$2("div", { style: { marginBottom: "12px" }, children: appliedVouchers.map((voucher) => (u$2("div", { style: appliedVoucherStyle, children: [u$2("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [voucher.type === "discount" ? (u$2(IconTicket, { size: 18, color: "var(--bw-success-color)" })) : (u$2(IconGift, { size: 18, color: "var(--bw-success-color)" })), u$2("div", { children: [u$2("div", { style: {
|
|
10026
|
+
fontFamily: "var(--bw-font-family)",
|
|
10027
|
+
fontSize: "var(--bw-font-size)",
|
|
10028
|
+
fontWeight: "600",
|
|
10029
|
+
color: "var(--bw-text-color)",
|
|
10030
|
+
display: "flex",
|
|
10031
|
+
alignItems: "center",
|
|
10032
|
+
gap: "6px",
|
|
10033
|
+
}, children: [u$2("span", { style: { fontFamily: "monospace" }, children: voucher.code }), u$2(IconCheck, { size: 14, color: "var(--bw-success-color)" })] }), u$2("div", { style: {
|
|
10034
|
+
fontFamily: "var(--bw-font-family)",
|
|
10035
|
+
fontSize: "12px",
|
|
10036
|
+
color: "var(--bw-success-color)",
|
|
10037
|
+
}, children: [voucher.type === "discount"
|
|
10038
|
+
? `−${formatCurrency(voucher.discountAmount)} Rabatt`
|
|
10039
|
+
: `−${formatCurrency(voucher.balanceToUse || voucher.discountAmount)} Gutschein`, voucher.type === "giftCard" &&
|
|
10040
|
+
voucher.remainingBalance !== undefined &&
|
|
10041
|
+
voucher.remainingBalance > 0 && (u$2("span", { style: { color: "var(--bw-text-muted)", marginLeft: "8px" }, children: ["(Rest: ", formatCurrency(voucher.remainingBalance), ")"] }))] })] })] }), u$2("button", { type: "button", onClick: () => onRemoveVoucher(voucher.code), style: removeButtonStyle, title: "Entfernen", children: u$2(IconX, { size: 16 }) })] }, voucher.code))) })), u$2("div", { style: { display: "flex", gap: "8px" }, children: [u$2("input", { type: "text", value: inputValue, onChange: (e) => {
|
|
10042
|
+
setInputValue(e.target.value.toUpperCase());
|
|
10043
|
+
setError(null);
|
|
10044
|
+
}, onKeyDown: handleKeyDown, placeholder: hasDiscountCode
|
|
10045
|
+
? "Gutscheincode eingeben..."
|
|
10046
|
+
: "Rabatt- oder Gutscheincode eingeben...", style: inputStyle, disabled: disabled || isLoading, onFocus: (e) => {
|
|
10047
|
+
e.target.style.borderColor = "var(--bw-highlight-color)";
|
|
10048
|
+
e.target.style.boxShadow = "0 0 0 2px var(--bw-highlight-color)33";
|
|
10049
|
+
}, onBlur: (e) => {
|
|
10050
|
+
e.target.style.borderColor = "var(--bw-border-color)";
|
|
10051
|
+
e.target.style.boxShadow = "none";
|
|
10052
|
+
} }), u$2("button", { type: "button", onClick: handleSubmit, style: buttonStyle, disabled: disabled || isLoading || !inputValue.trim(), children: isLoading ? (u$2(IconSpinner, { size: 16, color: "#fff" })) : (u$2(k$3, { children: [u$2(IconCheck, { size: 16 }), "Einl\u00F6sen"] })) })] }), error && (u$2("div", { style: {
|
|
10053
|
+
marginTop: "8px",
|
|
10054
|
+
padding: "8px 12px",
|
|
10055
|
+
backgroundColor: "var(--bw-error-color)15",
|
|
10056
|
+
border: "1px solid var(--bw-error-color)40",
|
|
10057
|
+
borderRadius: "var(--bw-border-radius)",
|
|
10058
|
+
color: "var(--bw-error-color)",
|
|
10059
|
+
fontSize: "var(--bw-font-size)",
|
|
10060
|
+
fontFamily: "var(--bw-font-family)",
|
|
10061
|
+
display: "flex",
|
|
10062
|
+
alignItems: "center",
|
|
10063
|
+
gap: "8px",
|
|
10064
|
+
}, children: [u$2(IconX, { size: 16 }), error] })), hasDiscountCode && (u$2("div", { style: {
|
|
10065
|
+
marginTop: "8px",
|
|
10066
|
+
fontSize: "12px",
|
|
10067
|
+
color: "var(--bw-text-muted)",
|
|
10068
|
+
fontFamily: "var(--bw-font-family)",
|
|
10069
|
+
}, children: "\uD83D\uDCA1 Es wurde bereits ein Rabattcode angewendet. Du kannst weitere Gutscheine hinzuf\u00FCgen." }))] })), u$2("style", { children: `
|
|
10070
|
+
@keyframes spin {
|
|
10071
|
+
from { transform: rotate(0deg); }
|
|
10072
|
+
to { transform: rotate(360deg); }
|
|
10073
|
+
}
|
|
10074
|
+
` })] }));
|
|
10075
|
+
}
|
|
10076
|
+
|
|
9743
10077
|
// Form schemas
|
|
9744
10078
|
const participantSchema = objectType({
|
|
9745
10079
|
name: stringType().min(1, "Name ist erforderlich"),
|
|
@@ -9759,6 +10093,10 @@
|
|
|
9759
10093
|
const IconWarning = ({ size = 48, color = "var(--bw-error-color)" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("circle", { cx: "12", cy: "12", r: "10" }), u$2("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), u$2("circle", { cx: "12", cy: "16", r: "1" })] }));
|
|
9760
10094
|
const IconMoney = ({ size = 20, color = "var(--bw-text-muted)" }) => (u$2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [u$2("rect", { x: "2", y: "6", width: "20", height: "12", rx: "2" }), u$2("circle", { cx: "12", cy: "12", r: "4" }), u$2("line", { x1: "2", y1: "10", x2: "2", y2: "14" }), u$2("line", { x1: "22", y1: "10", x2: "22", y2: "14" })] }));
|
|
9761
10095
|
function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError, onBackToEventInstances, onBackToEventTypes, selectedEventType, selectedEventInstance, isOpen, onClose, systemConfig, }) {
|
|
10096
|
+
// New voucher system - supports multiple gift cards + one discount code
|
|
10097
|
+
const [appliedVouchers, setAppliedVouchers] = d$1([]);
|
|
10098
|
+
const [voucherError, setVoucherError] = d$1(null);
|
|
10099
|
+
// Legacy state for backward compatibility
|
|
9762
10100
|
const [discountCode, setDiscountCode] = d$1(null);
|
|
9763
10101
|
const [discountLoading, setDiscountLoading] = d$1(false);
|
|
9764
10102
|
const [discountError, setDiscountError] = d$1(null);
|
|
@@ -9772,28 +10110,66 @@
|
|
|
9772
10110
|
},
|
|
9773
10111
|
});
|
|
9774
10112
|
const watchedParticipants = form.watch("participants");
|
|
9775
|
-
|
|
10113
|
+
form.watch("discountCode");
|
|
9776
10114
|
const watchedCustomerName = form.watch("customerName");
|
|
9777
10115
|
const watchedCustomerEmail = form.watch("customerEmail");
|
|
9778
10116
|
const customerNameError = form.formState.errors.customerName;
|
|
9779
10117
|
const customerEmailError = form.formState.errors.customerEmail;
|
|
9780
10118
|
const watchedAcceptTerms = form.watch("acceptTerms");
|
|
9781
|
-
// Calculate total
|
|
9782
|
-
const
|
|
10119
|
+
// Calculate base total before any discounts
|
|
10120
|
+
const calculateBaseTotal = q$2(() => {
|
|
9783
10121
|
if (!eventDetails)
|
|
9784
10122
|
return 0;
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
10123
|
+
return eventDetails.price * watchedParticipants.filter((p) => p.name.trim()).length;
|
|
10124
|
+
}, [eventDetails, watchedParticipants]);
|
|
10125
|
+
// Calculate total discount from all applied vouchers
|
|
10126
|
+
const calculateTotalDiscount = q$2(() => {
|
|
10127
|
+
return appliedVouchers.reduce((total, voucher) => {
|
|
10128
|
+
if (voucher.type === "discount") {
|
|
10129
|
+
return total + voucher.discountAmount;
|
|
10130
|
+
}
|
|
10131
|
+
else if (voucher.type === "giftCard") {
|
|
10132
|
+
return total + (voucher.balanceToUse || voucher.discountAmount);
|
|
10133
|
+
}
|
|
10134
|
+
return total;
|
|
10135
|
+
}, 0);
|
|
10136
|
+
}, [appliedVouchers]);
|
|
10137
|
+
// Calculate total amount after discounts
|
|
10138
|
+
const calculateTotal = q$2(() => {
|
|
10139
|
+
const baseTotal = calculateBaseTotal();
|
|
10140
|
+
const totalDiscount = calculateTotalDiscount();
|
|
10141
|
+
return Math.max(0, baseTotal - totalDiscount);
|
|
10142
|
+
}, [calculateBaseTotal, calculateTotalDiscount]);
|
|
9788
10143
|
const calculateDeposit = () => {
|
|
9789
10144
|
if (!eventDetails || !eventDetails.deposit)
|
|
9790
10145
|
return 0;
|
|
9791
10146
|
const participantCount = watchedParticipants.filter((p) => p.name.trim()).length;
|
|
9792
10147
|
return eventDetails.deposit * participantCount;
|
|
9793
10148
|
};
|
|
10149
|
+
const baseTotal = calculateBaseTotal();
|
|
10150
|
+
const totalDiscount = calculateTotalDiscount();
|
|
9794
10151
|
const totalAmount = calculateTotal();
|
|
9795
10152
|
const depositAmount = calculateDeposit();
|
|
9796
|
-
|
|
10153
|
+
// If there's a deposit, we pay the deposit; otherwise we pay the total after discounts
|
|
10154
|
+
const paymentAmount = depositAmount > 0 ? Math.max(0, depositAmount - totalDiscount) : totalAmount;
|
|
10155
|
+
// Get discount code for legacy compatibility
|
|
10156
|
+
const appliedDiscountCode = appliedVouchers.find((v) => v.type === "discount");
|
|
10157
|
+
// Get gift cards
|
|
10158
|
+
const appliedGiftCards = appliedVouchers.filter((v) => v.type === "giftCard");
|
|
10159
|
+
// Voucher handlers
|
|
10160
|
+
const handleVoucherValidated = q$2((voucher, error) => {
|
|
10161
|
+
if (error) {
|
|
10162
|
+
setVoucherError(error);
|
|
10163
|
+
return;
|
|
10164
|
+
}
|
|
10165
|
+
if (voucher) {
|
|
10166
|
+
setAppliedVouchers((prev) => [...prev, voucher]);
|
|
10167
|
+
setVoucherError(null);
|
|
10168
|
+
}
|
|
10169
|
+
}, []);
|
|
10170
|
+
const handleRemoveVoucher = q$2((code) => {
|
|
10171
|
+
setAppliedVouchers((prev) => prev.filter((v) => v.code !== code));
|
|
10172
|
+
}, []);
|
|
9797
10173
|
// Form validation helper
|
|
9798
10174
|
const isFormValid = () => {
|
|
9799
10175
|
const participantCount = watchedParticipants.filter((p) => p.name.trim()).length;
|
|
@@ -9807,48 +10183,51 @@
|
|
|
9807
10183
|
const hasAcceptedTerms = watchedAcceptTerms === true;
|
|
9808
10184
|
return validParticipants && participantsWithinLimit && hasName && hasEmail && hasAcceptedTerms;
|
|
9809
10185
|
};
|
|
9810
|
-
//
|
|
10186
|
+
// Re-validate vouchers when participant count changes (affects order value)
|
|
9811
10187
|
y$1(() => {
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
10188
|
+
// When participants change, we need to recalculate voucher amounts
|
|
10189
|
+
// For now, we'll clear vouchers if the order value changes significantly
|
|
10190
|
+
// In a production app, you might want to re-validate each voucher
|
|
10191
|
+
if (appliedVouchers.length > 0) {
|
|
10192
|
+
// Recalculate discount amounts based on new order value
|
|
10193
|
+
const newBaseTotal = eventDetails?.price
|
|
10194
|
+
? eventDetails.price * watchedParticipants.filter((p) => p.name.trim()).length
|
|
10195
|
+
: 0;
|
|
10196
|
+
// Update voucher amounts (simplified - in production, re-validate via API)
|
|
10197
|
+
setAppliedVouchers((prev) => prev.map((voucher) => {
|
|
10198
|
+
if (voucher.type === "discount") {
|
|
10199
|
+
let newDiscountAmount = 0;
|
|
10200
|
+
if (voucher.discountType === "percentage") {
|
|
10201
|
+
newDiscountAmount = Math.round((newBaseTotal * (voucher.discountValue || 0)) / 10000);
|
|
10202
|
+
}
|
|
10203
|
+
else {
|
|
10204
|
+
newDiscountAmount = voucher.discountValue || 0;
|
|
10205
|
+
}
|
|
10206
|
+
newDiscountAmount = Math.min(newDiscountAmount, newBaseTotal);
|
|
10207
|
+
return {
|
|
10208
|
+
...voucher,
|
|
10209
|
+
discountAmount: newDiscountAmount,
|
|
10210
|
+
newTotal: newBaseTotal - newDiscountAmount,
|
|
10211
|
+
};
|
|
9833
10212
|
}
|
|
9834
|
-
else {
|
|
9835
|
-
|
|
9836
|
-
|
|
10213
|
+
else if (voucher.type === "giftCard") {
|
|
10214
|
+
// Gift card balance stays the same, but amount to use might change
|
|
10215
|
+
const remainingAfterDiscount = newBaseTotal -
|
|
10216
|
+
prev
|
|
10217
|
+
.filter((v) => v.type === "discount")
|
|
10218
|
+
.reduce((sum, v) => sum + v.discountAmount, 0);
|
|
10219
|
+
const balanceToUse = Math.min(voucher.currentBalance || 0, Math.max(0, remainingAfterDiscount));
|
|
10220
|
+
return {
|
|
10221
|
+
...voucher,
|
|
10222
|
+
balanceToUse,
|
|
10223
|
+
remainingBalance: (voucher.currentBalance || 0) - balanceToUse,
|
|
10224
|
+
discountAmount: balanceToUse,
|
|
10225
|
+
};
|
|
9837
10226
|
}
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
}
|
|
9843
|
-
finally {
|
|
9844
|
-
setDiscountLoading(false);
|
|
9845
|
-
}
|
|
9846
|
-
};
|
|
9847
|
-
const timer = setTimeout(() => {
|
|
9848
|
-
validateDiscountCode(watchedDiscountCode || "");
|
|
9849
|
-
}, 500);
|
|
9850
|
-
return () => clearTimeout(timer);
|
|
9851
|
-
}, [watchedDiscountCode, watchedParticipants, eventDetails, config]);
|
|
10227
|
+
return voucher;
|
|
10228
|
+
}));
|
|
10229
|
+
}
|
|
10230
|
+
}, [watchedParticipants, eventDetails]);
|
|
9852
10231
|
// Helper functions
|
|
9853
10232
|
const addParticipant = () => {
|
|
9854
10233
|
const currentParticipants = form.getValues("participants");
|
|
@@ -10003,7 +10382,7 @@
|
|
|
10003
10382
|
color: "var(--bw-text-color)",
|
|
10004
10383
|
fontWeight: "500",
|
|
10005
10384
|
fontFamily: "var(--bw-font-family)",
|
|
10006
|
-
}, children: [formatCurrency(eventDetails.price), " pro Person"] })] })] })] }), u$2("div", { style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-large)" }, children: [u$2("
|
|
10385
|
+
}, children: [formatCurrency(eventDetails.price), " pro Person"] })] })] })] }), u$2("div", { style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-large)" }, children: [u$2("div", { style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-large)" }, children: [u$2("div", { style: {
|
|
10007
10386
|
backgroundColor: "var(--bw-surface-color)",
|
|
10008
10387
|
border: `1px solid var(--bw-border-color)`,
|
|
10009
10388
|
backdropFilter: "blur(4px)",
|
|
@@ -10148,7 +10527,7 @@
|
|
|
10148
10527
|
color: "var(--bw-error-color)",
|
|
10149
10528
|
fontSize: "var(--bw-font-size)",
|
|
10150
10529
|
fontFamily: "var(--bw-font-family)",
|
|
10151
|
-
}, children: ["Maximal ", eventDetails.availableSpots, " Pl\u00E4tze verf\u00FCgbar."] }))] })] }), u$2("div", { style: {
|
|
10530
|
+
}, children: ["Maximal ", eventDetails.availableSpots, " Pl\u00E4tze verf\u00FCgbar."] }))] })] }), u$2(VoucherInput, { config: config, orderValue: baseTotal, eventInstanceId: eventDetails?.id, customerEmail: watchedCustomerEmail, onVoucherValidated: handleVoucherValidated, appliedVouchers: appliedVouchers, onRemoveVoucher: handleRemoveVoucher, disabled: !eventDetails }), u$2("div", { style: {
|
|
10152
10531
|
backgroundColor: "var(--bw-surface-color)",
|
|
10153
10532
|
border: `1px solid var(--bw-border-color)`,
|
|
10154
10533
|
backdropFilter: "blur(4px)",
|
|
@@ -10247,7 +10626,7 @@
|
|
|
10247
10626
|
color: "var(--bw-text-color)",
|
|
10248
10627
|
fontWeight: "500",
|
|
10249
10628
|
fontFamily: "var(--bw-font-family)",
|
|
10250
|
-
}, children: formatCurrency(eventDetails.deposit || 0) })] })),
|
|
10629
|
+
}, children: formatCurrency(eventDetails.deposit || 0) })] })), appliedVouchers.length > 0 && (u$2(k$3, { children: [u$2("div", { style: {
|
|
10251
10630
|
display: "flex",
|
|
10252
10631
|
justifyContent: "space-between",
|
|
10253
10632
|
alignItems: "center",
|
|
@@ -10256,20 +10635,31 @@
|
|
|
10256
10635
|
fontFamily: "var(--bw-font-family)",
|
|
10257
10636
|
}, children: "Zwischensumme:" }), u$2("span", { style: {
|
|
10258
10637
|
color: "var(--bw-text-muted)",
|
|
10259
|
-
textDecoration: "line-through",
|
|
10638
|
+
textDecoration: totalDiscount > 0 ? "line-through" : "none",
|
|
10639
|
+
fontFamily: "var(--bw-font-family)",
|
|
10640
|
+
}, children: formatCurrency(baseTotal) })] }), appliedDiscountCode && (u$2("div", { style: {
|
|
10641
|
+
display: "flex",
|
|
10642
|
+
justifyContent: "space-between",
|
|
10643
|
+
alignItems: "center",
|
|
10644
|
+
}, children: [u$2("span", { style: {
|
|
10645
|
+
color: "var(--bw-success-color)",
|
|
10260
10646
|
fontFamily: "var(--bw-font-family)",
|
|
10261
|
-
|
|
10262
|
-
|
|
10647
|
+
fontSize: "var(--bw-font-size)",
|
|
10648
|
+
}, children: ["Rabatt (", appliedDiscountCode.code, "):"] }), u$2("span", { style: {
|
|
10649
|
+
color: "var(--bw-success-color)",
|
|
10650
|
+
fontFamily: "var(--bw-font-family)",
|
|
10651
|
+
}, children: ["-", formatCurrency(appliedDiscountCode.discountAmount)] })] })), appliedGiftCards.map((giftCard) => (u$2("div", { style: {
|
|
10263
10652
|
display: "flex",
|
|
10264
10653
|
justifyContent: "space-between",
|
|
10265
10654
|
alignItems: "center",
|
|
10266
10655
|
}, children: [u$2("span", { style: {
|
|
10267
10656
|
color: "var(--bw-success-color)",
|
|
10268
10657
|
fontFamily: "var(--bw-font-family)",
|
|
10269
|
-
|
|
10658
|
+
fontSize: "var(--bw-font-size)",
|
|
10659
|
+
}, children: ["Gutschein (", giftCard.code, "):"] }), u$2("span", { style: {
|
|
10270
10660
|
color: "var(--bw-success-color)",
|
|
10271
10661
|
fontFamily: "var(--bw-font-family)",
|
|
10272
|
-
}, children: ["-", formatCurrency(
|
|
10662
|
+
}, children: ["-", formatCurrency(giftCard.balanceToUse || giftCard.discountAmount)] })] }, giftCard.code)))] })), u$2("div", { style: {
|
|
10273
10663
|
borderTop: `1px solid var(--bw-border-color)`,
|
|
10274
10664
|
paddingTop: "12px",
|
|
10275
10665
|
}, children: [depositAmount > 0 && (u$2("div", { style: {
|
|
@@ -10342,7 +10732,15 @@
|
|
|
10342
10732
|
fontFamily: "var(--bw-font-family)",
|
|
10343
10733
|
borderBottom: "2px solid var(--bw-highlight-color)",
|
|
10344
10734
|
paddingBottom: 4,
|
|
10345
|
-
}, children: "Zahlung" }), u$2(PaymentForm, { config: config, eventDetails: eventDetails, formData: form.getValues(), totalAmount: paymentAmount, discountCode:
|
|
10735
|
+
}, children: "Zahlung" }), u$2(PaymentForm, { config: config, eventDetails: eventDetails, formData: form.getValues(), totalAmount: paymentAmount, discountCode: appliedDiscountCode ? {
|
|
10736
|
+
id: appliedDiscountCode.id,
|
|
10737
|
+
code: appliedDiscountCode.code,
|
|
10738
|
+
description: appliedDiscountCode.description || undefined,
|
|
10739
|
+
type: appliedDiscountCode.discountType || "percentage",
|
|
10740
|
+
value: appliedDiscountCode.discountValue || 0,
|
|
10741
|
+
discountAmount: appliedDiscountCode.discountAmount,
|
|
10742
|
+
newTotal: appliedDiscountCode.newTotal,
|
|
10743
|
+
} : null, giftCards: appliedGiftCards, onSuccess: onSuccess, onError: onError, systemConfig: systemConfig, stripePromise: stripePromise, stripeAppearance: stripeAppearance })] }));
|
|
10346
10744
|
})()] })] }), u$2("style", { children: `
|
|
10347
10745
|
.booking-widget-container *,
|
|
10348
10746
|
.booking-widget-container *::before,
|
|
@@ -11369,137 +11767,155 @@
|
|
|
11369
11767
|
font-size: 1.1rem !important;
|
|
11370
11768
|
}
|
|
11371
11769
|
}
|
|
11372
|
-
` }), u$2(Sidebar, { isOpen: isOpen, onClose: handleClose, title:
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
backgroundColor:
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
:
|
|
11392
|
-
|
|
11393
|
-
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11403
|
-
|
|
11404
|
-
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
|
|
11408
|
-
|
|
11409
|
-
|
|
11410
|
-
|
|
11411
|
-
|
|
11412
|
-
|
|
11413
|
-
|
|
11414
|
-
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11420
|
-
|
|
11421
|
-
|
|
11422
|
-
|
|
11423
|
-
|
|
11424
|
-
|
|
11425
|
-
|
|
11426
|
-
|
|
11427
|
-
|
|
11428
|
-
|
|
11429
|
-
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11441
|
-
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
}, children:
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11770
|
+
` }), u$2(Sidebar, { isOpen: isOpen, onClose: handleClose, title: `${selectedEventType?.name}`, children: u$2("div", { className: "bw-event-instance-list", style: { padding: "24px" }, children: u$2("div", { style: {
|
|
11771
|
+
display: "flex",
|
|
11772
|
+
flexDirection: "column",
|
|
11773
|
+
gap: "20px",
|
|
11774
|
+
}, children: monthYearGroups.map(({ key, label, events, minPrice, year }, idx) => {
|
|
11775
|
+
const monthPriceDisplayInfo = getMonthPriceDisplayInfo(minPrice);
|
|
11776
|
+
return (u$2(k$3, { children: [idx > 0 && monthYearGroups[idx - 1].year !== year && (u$2("div", { style: {
|
|
11777
|
+
height: 1,
|
|
11778
|
+
backgroundColor: "var(--bw-border-color)",
|
|
11779
|
+
margin: "4px 0",
|
|
11780
|
+
} })), u$2(Accordion, { title: label, priceInfo: u$2("div", { style: {
|
|
11781
|
+
fontSize: "1rem",
|
|
11782
|
+
backgroundColor: monthPriceDisplayInfo
|
|
11783
|
+
? monthPriceDisplayInfo.backgroundColor
|
|
11784
|
+
: "#14532d",
|
|
11785
|
+
color: monthPriceDisplayInfo
|
|
11786
|
+
? monthPriceDisplayInfo.textColor
|
|
11787
|
+
: "#4ade80",
|
|
11788
|
+
fontWeight: 500,
|
|
11789
|
+
marginLeft: "auto",
|
|
11790
|
+
padding: "4px 8px",
|
|
11791
|
+
borderRadius: "var(--bw-border-radius-small)",
|
|
11792
|
+
border: monthPriceDisplayInfo ? "none" : undefined,
|
|
11793
|
+
boxShadow: monthPriceDisplayInfo
|
|
11794
|
+
? "0 2px 4px rgba(0, 0, 0, 0.2)"
|
|
11795
|
+
: undefined,
|
|
11796
|
+
}, children: `ab ${formatCurrency(minPrice)}` }), isOpen: openGroups.has(key), onToggle: () => toggleGroup(key), children: u$2("div", { style: {
|
|
11797
|
+
display: "flex",
|
|
11798
|
+
flexDirection: "column",
|
|
11799
|
+
gap: "12px",
|
|
11800
|
+
paddingTop: "12px",
|
|
11801
|
+
}, children: events.map((event) => {
|
|
11802
|
+
const availableSpots = event.maxParticipants - event.participantCount;
|
|
11803
|
+
const isFullyBooked = availableSpots === 0;
|
|
11804
|
+
const startDate = new Date(event.startTime);
|
|
11805
|
+
const isPastEvent = today.toISOString() >= startDate.toISOString();
|
|
11806
|
+
return (u$2("div", { className: "bw-event-instance-card", style: {
|
|
11807
|
+
position: "relative",
|
|
11808
|
+
cursor: !isFullyBooked && !isPastEvent && event.bookingOpen
|
|
11809
|
+
? "pointer"
|
|
11810
|
+
: "not-allowed",
|
|
11811
|
+
border: "1px solid var(--bw-border-color)",
|
|
11812
|
+
backgroundColor: "var(--bw-surface-color)",
|
|
11813
|
+
borderRadius: "var(--bw-border-radius)",
|
|
11814
|
+
padding: "16px 20px",
|
|
11815
|
+
transition: "all 0.2s ease",
|
|
11816
|
+
opacity: isFullyBooked || isPastEvent ? 0.3 : 1,
|
|
11817
|
+
filter: isFullyBooked || isPastEvent ? "grayscale(40%)" : "none",
|
|
11818
|
+
fontFamily: "var(--bw-font-family)",
|
|
11819
|
+
}, onClick: () => {
|
|
11820
|
+
if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
|
|
11821
|
+
handleEventInstanceSelect(event);
|
|
11822
|
+
}
|
|
11823
|
+
}, onMouseEnter: (e) => {
|
|
11824
|
+
if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
|
|
11825
|
+
e.currentTarget.style.transform = "scale(1.02)";
|
|
11826
|
+
e.currentTarget.style.backgroundColor =
|
|
11827
|
+
"var(--bw-surface-muted, rgba(59, 130, 246, 0.1))";
|
|
11828
|
+
}
|
|
11829
|
+
}, onMouseLeave: (e) => {
|
|
11830
|
+
if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
|
|
11831
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
11832
|
+
e.currentTarget.style.backgroundColor = "var(--bw-surface-color)";
|
|
11833
|
+
}
|
|
11834
|
+
}, children: [selectedEventInstanceId === event.id && isLoadingEventDetails && (u$2("div", { style: {
|
|
11835
|
+
position: "absolute",
|
|
11836
|
+
top: 0,
|
|
11837
|
+
left: 0,
|
|
11838
|
+
width: "100%",
|
|
11839
|
+
height: "100%",
|
|
11840
|
+
backgroundColor: "var(--bw-overlay-color, rgba(15, 23, 42, 0.8))",
|
|
11841
|
+
borderRadius: "var(--bw-border-radius)",
|
|
11842
|
+
display: "flex",
|
|
11843
|
+
alignItems: "center",
|
|
11844
|
+
justifyContent: "center",
|
|
11845
|
+
}, children: u$2("div", { style: {
|
|
11846
|
+
width: "32px",
|
|
11847
|
+
height: "32px",
|
|
11848
|
+
color: "var(--bw-highlight-color-muted, rgba(59, 130, 246, 0.8))",
|
|
11849
|
+
animation: "spin 1s linear infinite",
|
|
11850
|
+
fontSize: "32px",
|
|
11851
|
+
}, children: spinner() }) })), u$2(SpecialPriceBadge, { price: event.price, yearPrices: yearPrices }), u$2(AllocationBadge, { availableSpots: availableSpots, maxParticipants: event.maxParticipants }), u$2("div", { style: {
|
|
11852
|
+
display: "flex",
|
|
11853
|
+
justifyContent: "space-between",
|
|
11854
|
+
width: "100%",
|
|
11855
|
+
alignItems: "start",
|
|
11856
|
+
gap: "12px",
|
|
11857
|
+
marginBottom: "4px",
|
|
11858
|
+
}, children: [u$2("div", { style: { display: "flex", alignItems: "start", gap: "12px" }, children: [u$2("div", { className: "bw-event-instance-datebox", style: {
|
|
11859
|
+
fontSize: "var(--bw-font-size)",
|
|
11860
|
+
transition: "all 0.2s ease",
|
|
11861
|
+
borderRadius: "var(--bw-border-radius-small)",
|
|
11862
|
+
borderTop: `4px solid var(--bw-border-color)`,
|
|
11863
|
+
border: "1px solid var(--bw-border-color)",
|
|
11864
|
+
width: "40px",
|
|
11865
|
+
height: "40px",
|
|
11866
|
+
display: "flex",
|
|
11867
|
+
alignItems: "center",
|
|
11868
|
+
justifyContent: "center",
|
|
11869
|
+
fontWeight: "bold",
|
|
11870
|
+
color: "var(--bw-text-color)",
|
|
11871
|
+
backgroundColor: "var(--bw-background-color)",
|
|
11872
|
+
}, children: startDate.getDate() }), u$2("div", { style: {
|
|
11873
|
+
fontSize: "var(--bw-font-size)",
|
|
11874
|
+
color: "var(--bw-text-color)",
|
|
11875
|
+
display: "flex",
|
|
11876
|
+
flexDirection: "column",
|
|
11877
|
+
alignItems: "start",
|
|
11878
|
+
justifyContent: "start",
|
|
11879
|
+
lineHeight: "1.2",
|
|
11880
|
+
}, children: [u$2("div", { children: [u$2("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.startTime) }), formatWeekday(event.startTime) !==
|
|
11881
|
+
formatWeekday(event.endTime) && (u$2(k$3, { children: [u$2("span", { style: {
|
|
11882
|
+
color: "var(--bw-text-muted)",
|
|
11883
|
+
fontSize: "14px",
|
|
11884
|
+
}, children: " - " }), u$2("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.endTime) })] }))] }), u$2("div", { children: formatWeekday(event.startTime) ===
|
|
11885
|
+
formatWeekday(event.endTime) ? (u$2(k$3, { children: [u$2("span", { style: {
|
|
11886
|
+
color: "var(--bw-text-muted)",
|
|
11887
|
+
fontSize: "14px",
|
|
11888
|
+
}, children: formatTime(event.startTime) }), u$2("span", { style: {
|
|
11889
|
+
color: "var(--bw-text-muted)",
|
|
11890
|
+
fontSize: "14px",
|
|
11891
|
+
}, children: " - " }), u$2("span", { style: {
|
|
11892
|
+
color: "var(--bw-text-muted)",
|
|
11893
|
+
fontSize: "14px",
|
|
11894
|
+
}, children: formatTime(event.endTime) })] })) : (u$2("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: [formatTime(event.startTime), " Uhr"] })) })] }), u$2("span", { style: {
|
|
11895
|
+
fontSize: "12px",
|
|
11896
|
+
fontWeight: 400,
|
|
11897
|
+
color: "var(--bw-text-muted)",
|
|
11898
|
+
marginLeft: "6px",
|
|
11899
|
+
background: "var(--bw-background-muted)",
|
|
11900
|
+
whiteSpace: "nowrap",
|
|
11901
|
+
}, children: [event.durationDays, " Tag", event.durationDays > 1 ? "e" : ""] })] }), u$2("div", { className: "bw-event-instance-price", style: {
|
|
11902
|
+
textAlign: "right",
|
|
11903
|
+
display: "flex",
|
|
11904
|
+
flexDirection: "column",
|
|
11905
|
+
alignItems: "end",
|
|
11906
|
+
}, children: u$2(PriceDisplay, { price: event.price, yearPrices: yearPrices }) })] }), event.name !== selectedEventType?.name && (u$2("h4", { className: "bw-event-instance-title", style: {
|
|
11907
|
+
fontSize: "var(--bw-font-size)",
|
|
11908
|
+
fontWeight: "600",
|
|
11909
|
+
color: "var(--bw-text-color)",
|
|
11910
|
+
lineHeight: "1.25",
|
|
11911
|
+
margin: "0 0 2px 0",
|
|
11912
|
+
display: "flex",
|
|
11913
|
+
alignItems: "center",
|
|
11914
|
+
gap: "8px",
|
|
11915
|
+
maxWidth: "230px",
|
|
11916
|
+
}, children: event.name }))] }, event.id));
|
|
11917
|
+
}) }) })] }, key));
|
|
11918
|
+
}) }) }) })] }));
|
|
11503
11919
|
}
|
|
11504
11920
|
|
|
11505
11921
|
// Loading skeleton component for NextEventsPreview
|
|
@@ -11894,6 +12310,263 @@
|
|
|
11894
12310
|
` })] }));
|
|
11895
12311
|
}
|
|
11896
12312
|
|
|
12313
|
+
function PromoDialog({ onClose, onCtaClick }) {
|
|
12314
|
+
const [copied, setCopied] = d$1(false);
|
|
12315
|
+
const [isVisible, setIsVisible] = d$1(false);
|
|
12316
|
+
// Hardcoded Xmas surf school content
|
|
12317
|
+
const discountCode = "X-MAS";
|
|
12318
|
+
// Animate in on mount
|
|
12319
|
+
y$1(() => {
|
|
12320
|
+
const timer = setTimeout(() => setIsVisible(true), 50);
|
|
12321
|
+
return () => clearTimeout(timer);
|
|
12322
|
+
}, []);
|
|
12323
|
+
const handleCopyCode = async () => {
|
|
12324
|
+
try {
|
|
12325
|
+
await navigator.clipboard.writeText(discountCode);
|
|
12326
|
+
setCopied(true);
|
|
12327
|
+
setTimeout(() => setCopied(false), 2000);
|
|
12328
|
+
}
|
|
12329
|
+
catch (err) {
|
|
12330
|
+
// Fallback for older browsers
|
|
12331
|
+
const textArea = document.createElement("textarea");
|
|
12332
|
+
textArea.value = discountCode;
|
|
12333
|
+
document.body.appendChild(textArea);
|
|
12334
|
+
textArea.select();
|
|
12335
|
+
document.execCommand("copy");
|
|
12336
|
+
document.body.removeChild(textArea);
|
|
12337
|
+
setCopied(true);
|
|
12338
|
+
setTimeout(() => setCopied(false), 2000);
|
|
12339
|
+
}
|
|
12340
|
+
};
|
|
12341
|
+
const handleClose = () => {
|
|
12342
|
+
setIsVisible(false);
|
|
12343
|
+
setTimeout(onClose, 200);
|
|
12344
|
+
};
|
|
12345
|
+
const handleCtaClick = () => {
|
|
12346
|
+
setIsVisible(false);
|
|
12347
|
+
setTimeout(onCtaClick, 200);
|
|
12348
|
+
};
|
|
12349
|
+
return (u$2(k$3, { children: [u$2("style", { children: `
|
|
12350
|
+
@keyframes promo-wave {
|
|
12351
|
+
0%, 100% { transform: translateX(0) translateY(0); }
|
|
12352
|
+
25% { transform: translateX(5px) translateY(-3px); }
|
|
12353
|
+
50% { transform: translateX(0) translateY(-5px); }
|
|
12354
|
+
75% { transform: translateX(-5px) translateY(-3px); }
|
|
12355
|
+
}
|
|
12356
|
+
@keyframes promo-float {
|
|
12357
|
+
0%, 100% { transform: translateY(0); }
|
|
12358
|
+
50% { transform: translateY(-8px); }
|
|
12359
|
+
}
|
|
12360
|
+
@keyframes promo-shimmer {
|
|
12361
|
+
0% { background-position: -200% center; }
|
|
12362
|
+
100% { background-position: 200% center; }
|
|
12363
|
+
}
|
|
12364
|
+
@keyframes promo-sparkle {
|
|
12365
|
+
0%, 100% { opacity: 0.3; transform: scale(1); }
|
|
12366
|
+
50% { opacity: 1; transform: scale(1.2); }
|
|
12367
|
+
}
|
|
12368
|
+
@keyframes promo-snow {
|
|
12369
|
+
0% { transform: translateY(-10px) rotate(0deg); opacity: 0; }
|
|
12370
|
+
10% { opacity: 1; }
|
|
12371
|
+
90% { opacity: 1; }
|
|
12372
|
+
100% { transform: translateY(350px) rotate(360deg); opacity: 0; }
|
|
12373
|
+
}
|
|
12374
|
+
` }), u$2("div", { onClick: handleClose, style: {
|
|
12375
|
+
position: "fixed",
|
|
12376
|
+
inset: 0,
|
|
12377
|
+
backgroundColor: "rgba(0, 20, 40, 0.85)",
|
|
12378
|
+
backdropFilter: "blur(8px)",
|
|
12379
|
+
zIndex: 9998,
|
|
12380
|
+
opacity: isVisible ? 1 : 0,
|
|
12381
|
+
transition: "opacity 300ms ease-out",
|
|
12382
|
+
} }), u$2("div", { style: {
|
|
12383
|
+
position: "fixed",
|
|
12384
|
+
top: "50%",
|
|
12385
|
+
left: "50%",
|
|
12386
|
+
transform: `translate(-50%, -50%) scale(${isVisible ? 1 : 0.9})`,
|
|
12387
|
+
zIndex: 9999,
|
|
12388
|
+
width: "92%",
|
|
12389
|
+
maxWidth: "440px",
|
|
12390
|
+
opacity: isVisible ? 1 : 0,
|
|
12391
|
+
transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
12392
|
+
}, children: u$2("div", { style: {
|
|
12393
|
+
position: "relative",
|
|
12394
|
+
background: "linear-gradient(165deg, #0c4a6e 0%, #0e7490 40%, #0891b2 100%)",
|
|
12395
|
+
borderRadius: "28px",
|
|
12396
|
+
overflow: "hidden",
|
|
12397
|
+
boxShadow: "0 25px 60px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.2)",
|
|
12398
|
+
}, children: [Array.from({ length: 15 }).map((_, i) => (u$2("div", { style: {
|
|
12399
|
+
position: "absolute",
|
|
12400
|
+
left: `${5 + Math.random() * 90}%`,
|
|
12401
|
+
top: "-10px",
|
|
12402
|
+
fontSize: `${10 + Math.random() * 14}px`,
|
|
12403
|
+
color: "white",
|
|
12404
|
+
opacity: 0,
|
|
12405
|
+
animation: `promo-snow ${4 + Math.random() * 3}s linear infinite`,
|
|
12406
|
+
animationDelay: `${Math.random() * 4}s`,
|
|
12407
|
+
pointerEvents: "none",
|
|
12408
|
+
zIndex: 1,
|
|
12409
|
+
}, children: "\u2744" }, i))), u$2("div", { style: {
|
|
12410
|
+
position: "relative",
|
|
12411
|
+
height: "180px",
|
|
12412
|
+
background: "linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(12,74,110,0.8) 100%)",
|
|
12413
|
+
display: "flex",
|
|
12414
|
+
alignItems: "center",
|
|
12415
|
+
justifyContent: "center",
|
|
12416
|
+
overflow: "hidden",
|
|
12417
|
+
}, children: [u$2("img", { src: "https://images.unsplash.com/photo-1502680390469-be75c86b636f?w=600&q=80", alt: "Surfer at sunset", style: {
|
|
12418
|
+
position: "absolute",
|
|
12419
|
+
inset: 0,
|
|
12420
|
+
width: "100%",
|
|
12421
|
+
height: "100%",
|
|
12422
|
+
objectFit: "cover",
|
|
12423
|
+
opacity: 0.6,
|
|
12424
|
+
} }), u$2("div", { style: {
|
|
12425
|
+
position: "absolute",
|
|
12426
|
+
inset: 0,
|
|
12427
|
+
background: "linear-gradient(180deg, rgba(12,74,110,0.3) 0%, rgba(12,74,110,0.95) 100%)",
|
|
12428
|
+
} }), u$2("div", { style: {
|
|
12429
|
+
position: "relative",
|
|
12430
|
+
zIndex: 2,
|
|
12431
|
+
fontSize: "64px",
|
|
12432
|
+
animation: "promo-float 3s ease-in-out infinite",
|
|
12433
|
+
filter: "drop-shadow(0 8px 16px rgba(0,0,0,0.4))",
|
|
12434
|
+
}, children: "\uD83C\uDFC4\u200D\u2642\uFE0F" }), u$2("div", { style: {
|
|
12435
|
+
position: "absolute",
|
|
12436
|
+
top: "16px",
|
|
12437
|
+
left: "20px",
|
|
12438
|
+
fontSize: "28px",
|
|
12439
|
+
animation: "promo-sparkle 2s ease-in-out infinite",
|
|
12440
|
+
}, children: "\uD83C\uDF84" }), u$2("div", { style: {
|
|
12441
|
+
position: "absolute",
|
|
12442
|
+
top: "20px",
|
|
12443
|
+
right: "20px",
|
|
12444
|
+
fontSize: "24px",
|
|
12445
|
+
animation: "promo-sparkle 2s ease-in-out infinite 0.5s",
|
|
12446
|
+
}, children: "\u2B50" })] }), u$2("button", { onClick: handleClose, style: {
|
|
12447
|
+
position: "absolute",
|
|
12448
|
+
top: "16px",
|
|
12449
|
+
right: "16px",
|
|
12450
|
+
width: "36px",
|
|
12451
|
+
height: "36px",
|
|
12452
|
+
borderRadius: "50%",
|
|
12453
|
+
border: "none",
|
|
12454
|
+
background: "rgba(0, 0, 0, 0.3)",
|
|
12455
|
+
backdropFilter: "blur(4px)",
|
|
12456
|
+
color: "white",
|
|
12457
|
+
fontSize: "22px",
|
|
12458
|
+
cursor: "pointer",
|
|
12459
|
+
display: "flex",
|
|
12460
|
+
alignItems: "center",
|
|
12461
|
+
justifyContent: "center",
|
|
12462
|
+
transition: "all 150ms ease",
|
|
12463
|
+
zIndex: 10,
|
|
12464
|
+
lineHeight: 1,
|
|
12465
|
+
}, onMouseEnter: (e) => {
|
|
12466
|
+
e.currentTarget.style.background = "rgba(0, 0, 0, 0.5)";
|
|
12467
|
+
e.currentTarget.style.transform = "scale(1.1)";
|
|
12468
|
+
}, onMouseLeave: (e) => {
|
|
12469
|
+
e.currentTarget.style.background = "rgba(0, 0, 0, 0.3)";
|
|
12470
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
12471
|
+
}, children: "\u00D7" }), u$2("div", { style: { padding: "28px 28px 32px", textAlign: "center", position: "relative", zIndex: 2 }, children: [u$2("h2", { style: {
|
|
12472
|
+
fontSize: "26px",
|
|
12473
|
+
fontWeight: "800",
|
|
12474
|
+
color: "white",
|
|
12475
|
+
marginBottom: "6px",
|
|
12476
|
+
textShadow: "0 2px 8px rgba(0,0,0,0.3)",
|
|
12477
|
+
letterSpacing: "-0.5px",
|
|
12478
|
+
}, children: "Frohe Weihnachten! \uD83C\uDF85" }), u$2("p", { style: {
|
|
12479
|
+
fontSize: "17px",
|
|
12480
|
+
color: "rgba(255, 255, 255, 0.9)",
|
|
12481
|
+
marginBottom: "20px",
|
|
12482
|
+
lineHeight: 1.5,
|
|
12483
|
+
}, children: ["Schenk dir oder deinen Liebsten", u$2("br", {}), u$2("strong", { style: { color: "#fbbf24" }, children: "10% Rabatt" }), " auf alle Kurse!"] }), u$2("div", { style: {
|
|
12484
|
+
background: "white",
|
|
12485
|
+
borderRadius: "16px",
|
|
12486
|
+
padding: "18px 20px",
|
|
12487
|
+
marginBottom: "20px",
|
|
12488
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.15), inset 0 -2px 0 rgba(0,0,0,0.05)",
|
|
12489
|
+
}, children: [u$2("p", { style: {
|
|
12490
|
+
fontSize: "11px",
|
|
12491
|
+
textTransform: "uppercase",
|
|
12492
|
+
letterSpacing: "1.5px",
|
|
12493
|
+
color: "#64748b",
|
|
12494
|
+
marginBottom: "10px",
|
|
12495
|
+
fontWeight: "600",
|
|
12496
|
+
}, children: "Dein Geschenk-Code" }), u$2("div", { style: {
|
|
12497
|
+
display: "flex",
|
|
12498
|
+
alignItems: "center",
|
|
12499
|
+
justifyContent: "center",
|
|
12500
|
+
gap: "14px",
|
|
12501
|
+
}, children: [u$2("div", { style: {
|
|
12502
|
+
background: "linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)",
|
|
12503
|
+
padding: "10px 20px",
|
|
12504
|
+
borderRadius: "10px",
|
|
12505
|
+
boxShadow: "0 4px 12px rgba(220, 38, 38, 0.3)",
|
|
12506
|
+
}, children: u$2("span", { style: {
|
|
12507
|
+
fontSize: "28px",
|
|
12508
|
+
fontWeight: "900",
|
|
12509
|
+
color: "white",
|
|
12510
|
+
letterSpacing: "6px",
|
|
12511
|
+
textShadow: "0 2px 4px rgba(0,0,0,0.2)",
|
|
12512
|
+
}, children: discountCode }) }), u$2("button", { onClick: handleCopyCode, style: {
|
|
12513
|
+
padding: "12px 16px",
|
|
12514
|
+
borderRadius: "10px",
|
|
12515
|
+
border: "2px solid",
|
|
12516
|
+
borderColor: copied ? "#22c55e" : "#e2e8f0",
|
|
12517
|
+
background: copied ? "#dcfce7" : "#f8fafc",
|
|
12518
|
+
color: copied ? "#15803d" : "#475569",
|
|
12519
|
+
fontSize: "13px",
|
|
12520
|
+
fontWeight: "600",
|
|
12521
|
+
cursor: "pointer",
|
|
12522
|
+
transition: "all 150ms ease",
|
|
12523
|
+
display: "flex",
|
|
12524
|
+
alignItems: "center",
|
|
12525
|
+
gap: "6px",
|
|
12526
|
+
whiteSpace: "nowrap",
|
|
12527
|
+
}, children: copied ? (u$2(k$3, { children: "\u2713 Kopiert!" })) : (u$2(k$3, { children: [u$2("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [u$2("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), u$2("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }), "Kopieren"] })) })] })] }), u$2("div", { style: {
|
|
12528
|
+
display: "flex",
|
|
12529
|
+
justifyContent: "center",
|
|
12530
|
+
gap: "8px",
|
|
12531
|
+
marginBottom: "20px",
|
|
12532
|
+
flexWrap: "wrap",
|
|
12533
|
+
}, children: ["🏄 Surfen", "🪁 Wingen", "🏄♀️ SUP", "💨 Windsurfen"].map((activity) => (u$2("span", { style: {
|
|
12534
|
+
background: "rgba(255,255,255,0.15)",
|
|
12535
|
+
backdropFilter: "blur(4px)",
|
|
12536
|
+
padding: "6px 12px",
|
|
12537
|
+
borderRadius: "20px",
|
|
12538
|
+
fontSize: "13px",
|
|
12539
|
+
color: "white",
|
|
12540
|
+
fontWeight: "500",
|
|
12541
|
+
}, children: activity }, activity))) }), u$2("button", { onClick: handleCtaClick, style: {
|
|
12542
|
+
width: "100%",
|
|
12543
|
+
padding: "18px 24px",
|
|
12544
|
+
borderRadius: "14px",
|
|
12545
|
+
border: "none",
|
|
12546
|
+
background: "linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",
|
|
12547
|
+
color: "white",
|
|
12548
|
+
fontSize: "18px",
|
|
12549
|
+
fontWeight: "700",
|
|
12550
|
+
cursor: "pointer",
|
|
12551
|
+
transition: "all 150ms ease",
|
|
12552
|
+
boxShadow: "0 8px 24px rgba(245, 158, 11, 0.4), inset 0 1px 0 rgba(255,255,255,0.2)",
|
|
12553
|
+
display: "flex",
|
|
12554
|
+
alignItems: "center",
|
|
12555
|
+
justifyContent: "center",
|
|
12556
|
+
gap: "10px",
|
|
12557
|
+
}, onMouseEnter: (e) => {
|
|
12558
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
12559
|
+
e.currentTarget.style.boxShadow = "0 12px 28px rgba(245, 158, 11, 0.5), inset 0 1px 0 rgba(255,255,255,0.2)";
|
|
12560
|
+
}, onMouseLeave: (e) => {
|
|
12561
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
12562
|
+
e.currentTarget.style.boxShadow = "0 8px 24px rgba(245, 158, 11, 0.4), inset 0 1px 0 rgba(255,255,255,0.2)";
|
|
12563
|
+
}, children: [u$2("span", { style: { animation: "promo-wave 2s ease-in-out infinite" }, children: "\uD83C\uDF81" }), "Jetzt Kurs buchen", u$2("span", { children: "\u2192" })] }), u$2("p", { style: {
|
|
12564
|
+
marginTop: "16px",
|
|
12565
|
+
fontSize: "12px",
|
|
12566
|
+
color: "rgba(255,255,255,0.6)",
|
|
12567
|
+
}, children: "G\u00FCltig f\u00FCr alle Buchungen bis 31. Dezember 2025" })] })] }) })] }));
|
|
12568
|
+
}
|
|
12569
|
+
|
|
11897
12570
|
// Predefined themes & Style Provider have been moved to ../styles/StyleProvider.tsx
|
|
11898
12571
|
// Main widget component
|
|
11899
12572
|
function UniversalBookingWidget({ config: baseConfig }) {
|
|
@@ -11936,6 +12609,9 @@
|
|
|
11936
12609
|
// PERFORMANCE OPTIMIZATION: Lazy component loading
|
|
11937
12610
|
const [shouldRenderInstanceSelection, setShouldRenderInstanceSelection] = d$1(false);
|
|
11938
12611
|
const [shouldRenderBookingForm, setShouldRenderBookingForm] = d$1(false);
|
|
12612
|
+
// Promo dialog state
|
|
12613
|
+
const [showPromoDialog, setShowPromoDialog] = d$1(false);
|
|
12614
|
+
const [widgetContainerRef, setWidgetContainerRef] = d$1(null);
|
|
11939
12615
|
// Determine initial step and load data
|
|
11940
12616
|
y$1(() => {
|
|
11941
12617
|
const initializeWidget = async () => {
|
|
@@ -12010,6 +12686,46 @@
|
|
|
12010
12686
|
setShouldRenderBookingForm(true);
|
|
12011
12687
|
}
|
|
12012
12688
|
}, [currentStep, shouldRenderInstanceSelection, shouldRenderBookingForm]);
|
|
12689
|
+
// Promo dialog: show Xmas promo once per user during holiday season, prevent double-opening across multiple widgets
|
|
12690
|
+
y$1(() => {
|
|
12691
|
+
// Only show during holiday season (December and January)
|
|
12692
|
+
const now = new Date();
|
|
12693
|
+
const month = now.getMonth(); // 0 = January, 11 = December
|
|
12694
|
+
const isHolidaySeason = month === 11 || month === 0; // December (11) or January (0)
|
|
12695
|
+
if (!isHolidaySeason) {
|
|
12696
|
+
return;
|
|
12697
|
+
}
|
|
12698
|
+
const promoId = "xmas-2024";
|
|
12699
|
+
const storageKey = `bigz-promo-${promoId}-shown`;
|
|
12700
|
+
const globalFlagKey = `__bigzPromoShown_${promoId}`;
|
|
12701
|
+
// Check if already shown in this session (localStorage) or claimed by another widget (global flag)
|
|
12702
|
+
const alreadyShown = localStorage.getItem(storageKey) === "true";
|
|
12703
|
+
const claimedByOtherWidget = window[globalFlagKey] === true;
|
|
12704
|
+
if (alreadyShown || claimedByOtherWidget) {
|
|
12705
|
+
return;
|
|
12706
|
+
}
|
|
12707
|
+
// Claim this promo for this widget instance (prevents other widgets from showing it)
|
|
12708
|
+
window[globalFlagKey] = true;
|
|
12709
|
+
// Show the dialog after a short delay for better UX
|
|
12710
|
+
const timer = setTimeout(() => {
|
|
12711
|
+
setShowPromoDialog(true);
|
|
12712
|
+
}, 1000);
|
|
12713
|
+
return () => clearTimeout(timer);
|
|
12714
|
+
}, []);
|
|
12715
|
+
// Handle promo dialog close
|
|
12716
|
+
const handlePromoDialogClose = () => {
|
|
12717
|
+
setShowPromoDialog(false);
|
|
12718
|
+
localStorage.setItem("bigz-promo-xmas-2024-shown", "true");
|
|
12719
|
+
};
|
|
12720
|
+
// Handle promo dialog CTA click - scroll to widget
|
|
12721
|
+
const handlePromoCtaClick = () => {
|
|
12722
|
+
setShowPromoDialog(false);
|
|
12723
|
+
localStorage.setItem("bigz-promo-xmas-2024-shown", "true");
|
|
12724
|
+
// Scroll to the widget container
|
|
12725
|
+
if (widgetContainerRef) {
|
|
12726
|
+
widgetContainerRef.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
12727
|
+
}
|
|
12728
|
+
};
|
|
12013
12729
|
const loadEventTypes = async () => {
|
|
12014
12730
|
const requestBody = {
|
|
12015
12731
|
organizationId: config.organizationId,
|
|
@@ -12409,104 +13125,104 @@
|
|
|
12409
13125
|
// Main view based on view mode
|
|
12410
13126
|
if (viewMode === "next-events" && showingPreview) {
|
|
12411
13127
|
// Next events preview mode
|
|
12412
|
-
return (u$2(StyleProvider, { config: config, children: [u$2(NextEventsPreview, { events: upcomingEvents, onEventSelect: handleUpcomingEventSelect, onShowAll: handleShowAllEvents, showAllButtonText: nextEventsSettings.showAllButtonText, showAllButton: nextEventsSettings.showAllButton, isLoadingEventDetails: isLoadingEventDetails, isLoadingShowAll: isLoadingShowAll, isLoading: isLoading }), shouldRenderBookingForm && eventDetails && (u$2(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => {
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
13128
|
+
return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, children: [u$2(NextEventsPreview, { events: upcomingEvents, onEventSelect: handleUpcomingEventSelect, onShowAll: handleShowAllEvents, showAllButtonText: nextEventsSettings.showAllButtonText, showAllButton: nextEventsSettings.showAllButton, isLoadingEventDetails: isLoadingEventDetails, isLoadingShowAll: isLoadingShowAll, isLoading: isLoading }), shouldRenderBookingForm && eventDetails && (u$2(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => {
|
|
13129
|
+
setCurrentStep("eventTypes");
|
|
13130
|
+
setShowingPreview(true);
|
|
13131
|
+
setEventDetails(null);
|
|
13132
|
+
}, onBackToEventTypes: () => {
|
|
13133
|
+
setCurrentStep("eventTypes");
|
|
13134
|
+
setShowingPreview(true);
|
|
13135
|
+
setEventDetails(null);
|
|
13136
|
+
}, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => {
|
|
13137
|
+
setCurrentStep("eventTypes");
|
|
13138
|
+
setShowingPreview(true);
|
|
13139
|
+
setEventDetails(null);
|
|
13140
|
+
}, systemConfig: systemConfig })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
|
|
13141
|
+
setIsSuccess(false);
|
|
13142
|
+
setCurrentStep("eventTypes");
|
|
13143
|
+
setShowingPreview(true);
|
|
13144
|
+
// Reset state
|
|
13145
|
+
setSuccessPaymentIntentId(null);
|
|
13146
|
+
// Reset lazy loading flags
|
|
13147
|
+
setShouldRenderInstanceSelection(false);
|
|
13148
|
+
setShouldRenderBookingForm(false);
|
|
13149
|
+
// Clean up URL to remove Stripe parameters
|
|
13150
|
+
const url = new URL(window.location.href);
|
|
13151
|
+
url.searchParams.delete("payment_intent");
|
|
13152
|
+
url.searchParams.delete("payment_intent_client_secret");
|
|
13153
|
+
url.searchParams.delete("redirect_status");
|
|
13154
|
+
window.history.replaceState({}, "", url.toString());
|
|
13155
|
+
}, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
|
|
12440
13156
|
}
|
|
12441
13157
|
if (viewMode === "next-events" && !showingPreview && currentStep === "eventInstances") {
|
|
12442
13158
|
// Show all events for the single event type
|
|
12443
|
-
return (u$2(StyleProvider, { config: config, children: [shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
13159
|
+
return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, children: [shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
|
|
13160
|
+
setShowingPreview(true);
|
|
13161
|
+
setCurrentStep("eventTypes");
|
|
13162
|
+
}, isOpen: currentStep === "eventInstances", onClose: () => {
|
|
13163
|
+
setShowingPreview(true);
|
|
13164
|
+
setCurrentStep("eventTypes");
|
|
13165
|
+
}, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
|
|
13166
|
+
setIsSuccess(false);
|
|
13167
|
+
setCurrentStep("eventTypes");
|
|
13168
|
+
setShowingPreview(true);
|
|
13169
|
+
// Reset state
|
|
13170
|
+
setSuccessPaymentIntentId(null);
|
|
13171
|
+
// Reset lazy loading flags
|
|
13172
|
+
setShouldRenderInstanceSelection(false);
|
|
13173
|
+
setShouldRenderBookingForm(false);
|
|
13174
|
+
// Clean up URL to remove Stripe parameters
|
|
13175
|
+
const url = new URL(window.location.href);
|
|
13176
|
+
url.searchParams.delete("payment_intent");
|
|
13177
|
+
url.searchParams.delete("payment_intent_client_secret");
|
|
13178
|
+
url.searchParams.delete("redirect_status");
|
|
13179
|
+
window.history.replaceState({}, "", url.toString());
|
|
13180
|
+
}, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
|
|
12465
13181
|
}
|
|
12466
13182
|
if (viewMode === "button" && (isSingleEventTypeMode || isDirectInstanceMode)) {
|
|
12467
13183
|
// Button mode - show button that opens sidebar/booking directly
|
|
12468
|
-
return (u$2(StyleProvider, { config: config, children: u$2("div", { style: {
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
13184
|
+
return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, style: {
|
|
13185
|
+
display: "flex",
|
|
13186
|
+
justifyContent: "center",
|
|
13187
|
+
alignItems: "center",
|
|
13188
|
+
minHeight: "120px",
|
|
13189
|
+
}, children: [u$2("button", { type: "button", style: {
|
|
13190
|
+
backgroundColor: "var(--bw-highlight-color)",
|
|
13191
|
+
color: "white",
|
|
13192
|
+
padding: "16px 32px",
|
|
13193
|
+
border: "none",
|
|
13194
|
+
borderRadius: "var(--bw-border-radius)",
|
|
13195
|
+
fontSize: "18px",
|
|
13196
|
+
fontWeight: 600,
|
|
13197
|
+
fontFamily: "var(--bw-font-family)",
|
|
13198
|
+
boxShadow: "var(--bw-shadow-md)",
|
|
13199
|
+
cursor: "pointer",
|
|
13200
|
+
}, onClick: () => {
|
|
13201
|
+
if (isDirectInstanceMode) {
|
|
13202
|
+
setCurrentStep("booking");
|
|
13203
|
+
setShouldRenderBookingForm(true);
|
|
13204
|
+
}
|
|
13205
|
+
else {
|
|
13206
|
+
setSidebarOpen(true);
|
|
13207
|
+
setShouldRenderInstanceSelection(true);
|
|
13208
|
+
}
|
|
13209
|
+
}, children: config.buttonText ||
|
|
13210
|
+
(isDirectInstanceMode ? "Jetzt buchen" : "Jetzt Termin auswählen") }), shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen, onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderBookingForm && eventDetails && (u$2(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 })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
|
|
13211
|
+
setIsSuccess(false);
|
|
13212
|
+
setCurrentStep("eventTypes");
|
|
13213
|
+
setSidebarOpen(false);
|
|
13214
|
+
// Reset state
|
|
13215
|
+
setSuccessPaymentIntentId(null);
|
|
13216
|
+
// Reset lazy loading flags
|
|
13217
|
+
setShouldRenderInstanceSelection(false);
|
|
13218
|
+
setShouldRenderBookingForm(false);
|
|
13219
|
+
// Clean up URL to remove Stripe parameters
|
|
13220
|
+
const url = new URL(window.location.href);
|
|
13221
|
+
url.searchParams.delete("payment_intent");
|
|
13222
|
+
url.searchParams.delete("payment_intent_client_secret");
|
|
13223
|
+
url.searchParams.delete("redirect_status");
|
|
13224
|
+
window.history.replaceState({}, "", url.toString());
|
|
13225
|
+
}, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
|
|
12510
13226
|
}
|
|
12511
13227
|
// Cards mode (default) - show event type selection
|
|
12512
13228
|
const cardsView = (u$2(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, isLoading: isLoading, skeletonCount: getSkeletonCount() }));
|
|
@@ -12539,21 +13255,21 @@
|
|
|
12539
13255
|
};
|
|
12540
13256
|
};
|
|
12541
13257
|
const backHandlers = getBackHandlers();
|
|
12542
|
-
return (u$2(StyleProvider, { config: config, children: [cardsView, shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderBookingForm && eventDetails && (u$2(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 })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
13258
|
+
return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderBookingForm && eventDetails && (u$2(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 })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
|
|
13259
|
+
setIsSuccess(false);
|
|
13260
|
+
setCurrentStep("eventTypes");
|
|
13261
|
+
// Reset state
|
|
13262
|
+
setSuccessPaymentIntentId(null);
|
|
13263
|
+
// Reset lazy loading flags
|
|
13264
|
+
setShouldRenderInstanceSelection(false);
|
|
13265
|
+
setShouldRenderBookingForm(false);
|
|
13266
|
+
// Clean up URL to remove Stripe parameters
|
|
13267
|
+
const url = new URL(window.location.href);
|
|
13268
|
+
url.searchParams.delete("payment_intent");
|
|
13269
|
+
url.searchParams.delete("payment_intent_client_secret");
|
|
13270
|
+
url.searchParams.delete("redirect_status");
|
|
13271
|
+
window.history.replaceState({}, "", url.toString());
|
|
13272
|
+
}, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
|
|
12557
13273
|
}
|
|
12558
13274
|
|
|
12559
13275
|
// Export init function for vanilla JS usage with Preact
|