@bigz-app/booking-widget 0.3.8 → 0.3.10

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.
@@ -12310,6 +12310,282 @@
12310
12310
  ` })] }));
12311
12311
  }
12312
12312
 
12313
+ function PromoDialog({ onClose, onCtaClick }) {
12314
+ const [copied, setCopied] = d$1(false);
12315
+ const [isVisible, setIsVisible] = d$1(false);
12316
+ const [portalContainer, setPortalContainer] = d$1(null);
12317
+ // Hardcoded Xmas surf school content
12318
+ const discountCode = "X-MAS";
12319
+ // Create portal container on mount to escape stacking context issues
12320
+ y$1(() => {
12321
+ const container = document.createElement("div");
12322
+ container.id = "bigz-promo-dialog-portal";
12323
+ container.style.position = "relative";
12324
+ container.style.zIndex = "2147483647"; // Maximum z-index value
12325
+ document.body.appendChild(container);
12326
+ setPortalContainer(container);
12327
+ return () => {
12328
+ document.body.removeChild(container);
12329
+ };
12330
+ }, []);
12331
+ // Animate in on mount
12332
+ y$1(() => {
12333
+ const timer = setTimeout(() => setIsVisible(true), 50);
12334
+ return () => clearTimeout(timer);
12335
+ }, []);
12336
+ const handleCopyCode = async () => {
12337
+ try {
12338
+ await navigator.clipboard.writeText(discountCode);
12339
+ setCopied(true);
12340
+ setTimeout(() => setCopied(false), 2000);
12341
+ }
12342
+ catch (err) {
12343
+ // Fallback for older browsers
12344
+ const textArea = document.createElement("textarea");
12345
+ textArea.value = discountCode;
12346
+ document.body.appendChild(textArea);
12347
+ textArea.select();
12348
+ document.execCommand("copy");
12349
+ document.body.removeChild(textArea);
12350
+ setCopied(true);
12351
+ setTimeout(() => setCopied(false), 2000);
12352
+ }
12353
+ };
12354
+ const handleClose = () => {
12355
+ setIsVisible(false);
12356
+ setTimeout(onClose, 200);
12357
+ };
12358
+ const handleCtaClick = () => {
12359
+ setIsVisible(false);
12360
+ setTimeout(onCtaClick, 200);
12361
+ };
12362
+ // Don't render until portal container is ready
12363
+ if (!portalContainer) {
12364
+ return null;
12365
+ }
12366
+ const dialogContent = (u$2(k$3, { children: [u$2("style", { children: `
12367
+ @keyframes promo-wave {
12368
+ 0%, 100% { transform: translateX(0) translateY(0); }
12369
+ 25% { transform: translateX(5px) translateY(-3px); }
12370
+ 50% { transform: translateX(0) translateY(-5px); }
12371
+ 75% { transform: translateX(-5px) translateY(-3px); }
12372
+ }
12373
+ @keyframes promo-float {
12374
+ 0%, 100% { transform: translateY(0); }
12375
+ 50% { transform: translateY(-8px); }
12376
+ }
12377
+ @keyframes promo-shimmer {
12378
+ 0% { background-position: -200% center; }
12379
+ 100% { background-position: 200% center; }
12380
+ }
12381
+ @keyframes promo-sparkle {
12382
+ 0%, 100% { opacity: 0.3; transform: scale(1); }
12383
+ 50% { opacity: 1; transform: scale(1.2); }
12384
+ }
12385
+ @keyframes promo-snow {
12386
+ 0% { transform: translateY(-10px) rotate(0deg); opacity: 0; }
12387
+ 10% { opacity: 1; }
12388
+ 90% { opacity: 1; }
12389
+ 100% { transform: translateY(350px) rotate(360deg); opacity: 0; }
12390
+ }
12391
+ ` }), u$2("div", { onClick: handleClose, style: {
12392
+ position: "fixed",
12393
+ inset: 0,
12394
+ backgroundColor: "rgba(0, 20, 40, 0.85)",
12395
+ backdropFilter: "blur(8px)",
12396
+ zIndex: 60,
12397
+ opacity: isVisible ? 1 : 0,
12398
+ transition: "opacity 300ms ease-out",
12399
+ } }), u$2("div", { style: {
12400
+ position: "fixed",
12401
+ top: "50%",
12402
+ left: "50%",
12403
+ transform: `translate(-50%, -50%) scale(${isVisible ? 1 : 0.9})`,
12404
+ zIndex: 61,
12405
+ width: "92%",
12406
+ maxWidth: "440px",
12407
+ opacity: isVisible ? 1 : 0,
12408
+ transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)",
12409
+ }, children: u$2("div", { style: {
12410
+ position: "relative",
12411
+ background: "linear-gradient(165deg, #0c4a6e 0%, #0e7490 40%, #0891b2 100%)",
12412
+ borderRadius: "28px",
12413
+ overflow: "hidden",
12414
+ 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)",
12415
+ }, children: [Array.from({ length: 15 }).map((_, i) => (u$2("div", { style: {
12416
+ position: "absolute",
12417
+ left: `${5 + Math.random() * 90}%`,
12418
+ top: "-10px",
12419
+ fontSize: `${10 + Math.random() * 14}px`,
12420
+ color: "white",
12421
+ opacity: 0,
12422
+ animation: `promo-snow ${4 + Math.random() * 3}s linear infinite`,
12423
+ animationDelay: `${Math.random() * 4}s`,
12424
+ pointerEvents: "none",
12425
+ zIndex: 1,
12426
+ }, children: "\u2744" }, i))), u$2("div", { style: {
12427
+ position: "relative",
12428
+ height: "180px",
12429
+ background: "linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(12,74,110,0.8) 100%)",
12430
+ display: "flex",
12431
+ alignItems: "center",
12432
+ justifyContent: "center",
12433
+ overflow: "hidden",
12434
+ }, children: [u$2("img", { src: "https://images.unsplash.com/photo-1502680390469-be75c86b636f?w=600&q=80", alt: "Surfer at sunset", style: {
12435
+ position: "absolute",
12436
+ inset: 0,
12437
+ width: "100%",
12438
+ height: "100%",
12439
+ objectFit: "cover",
12440
+ opacity: 0.6,
12441
+ } }), u$2("div", { style: {
12442
+ position: "absolute",
12443
+ inset: 0,
12444
+ background: "linear-gradient(180deg, rgba(12,74,110,0.3) 0%, rgba(12,74,110,0.95) 100%)",
12445
+ } }), u$2("div", { style: {
12446
+ position: "relative",
12447
+ zIndex: 2,
12448
+ fontSize: "64px",
12449
+ animation: "promo-float 3s ease-in-out infinite",
12450
+ filter: "drop-shadow(0 8px 16px rgba(0,0,0,0.4))",
12451
+ }, children: "\uD83C\uDFC4\u200D\u2642\uFE0F" }), u$2("div", { style: {
12452
+ position: "absolute",
12453
+ top: "16px",
12454
+ left: "20px",
12455
+ fontSize: "28px",
12456
+ animation: "promo-sparkle 2s ease-in-out infinite",
12457
+ }, children: "\uD83C\uDF84" }), u$2("div", { style: {
12458
+ position: "absolute",
12459
+ top: "20px",
12460
+ right: "20px",
12461
+ fontSize: "24px",
12462
+ animation: "promo-sparkle 2s ease-in-out infinite 0.5s",
12463
+ }, children: "\u2B50" })] }), u$2("button", { onClick: handleClose, style: {
12464
+ position: "absolute",
12465
+ top: "16px",
12466
+ right: "16px",
12467
+ width: "36px",
12468
+ height: "36px",
12469
+ borderRadius: "50%",
12470
+ border: "none",
12471
+ background: "rgba(0, 0, 0, 0.3)",
12472
+ backdropFilter: "blur(4px)",
12473
+ color: "white",
12474
+ fontSize: "22px",
12475
+ cursor: "pointer",
12476
+ display: "flex",
12477
+ alignItems: "center",
12478
+ justifyContent: "center",
12479
+ transition: "all 150ms ease",
12480
+ zIndex: 10,
12481
+ lineHeight: 1,
12482
+ }, onMouseEnter: (e) => {
12483
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.5)";
12484
+ e.currentTarget.style.transform = "scale(1.1)";
12485
+ }, onMouseLeave: (e) => {
12486
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.3)";
12487
+ e.currentTarget.style.transform = "scale(1)";
12488
+ }, children: "\u00D7" }), u$2("div", { style: { padding: "28px 28px 32px", textAlign: "center", position: "relative", zIndex: 2 }, children: [u$2("h2", { style: {
12489
+ fontSize: "26px",
12490
+ fontWeight: "800",
12491
+ color: "white",
12492
+ marginBottom: "6px",
12493
+ textShadow: "0 2px 8px rgba(0,0,0,0.3)",
12494
+ letterSpacing: "-0.5px",
12495
+ }, children: "Frohe Weihnachten! \uD83C\uDF85" }), u$2("p", { style: {
12496
+ fontSize: "17px",
12497
+ color: "rgba(255, 255, 255, 0.9)",
12498
+ marginBottom: "20px",
12499
+ lineHeight: 1.5,
12500
+ }, 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: {
12501
+ background: "white",
12502
+ borderRadius: "16px",
12503
+ padding: "18px 20px",
12504
+ marginBottom: "20px",
12505
+ boxShadow: "0 8px 24px rgba(0,0,0,0.15), inset 0 -2px 0 rgba(0,0,0,0.05)",
12506
+ }, children: [u$2("p", { style: {
12507
+ fontSize: "11px",
12508
+ textTransform: "uppercase",
12509
+ letterSpacing: "1.5px",
12510
+ color: "#64748b",
12511
+ marginBottom: "10px",
12512
+ fontWeight: "600",
12513
+ }, children: "Dein Geschenk-Code" }), u$2("div", { style: {
12514
+ display: "flex",
12515
+ alignItems: "center",
12516
+ justifyContent: "center",
12517
+ gap: "14px",
12518
+ }, children: [u$2("div", { style: {
12519
+ background: "linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)",
12520
+ padding: "10px 20px",
12521
+ borderRadius: "10px",
12522
+ boxShadow: "0 4px 12px rgba(220, 38, 38, 0.3)",
12523
+ }, children: u$2("span", { style: {
12524
+ fontSize: "28px",
12525
+ fontWeight: "900",
12526
+ color: "white",
12527
+ letterSpacing: "6px",
12528
+ textShadow: "0 2px 4px rgba(0,0,0,0.2)",
12529
+ }, children: discountCode }) }), u$2("button", { onClick: handleCopyCode, style: {
12530
+ padding: "12px 16px",
12531
+ borderRadius: "10px",
12532
+ border: "2px solid",
12533
+ borderColor: copied ? "#22c55e" : "#e2e8f0",
12534
+ background: copied ? "#dcfce7" : "#f8fafc",
12535
+ color: copied ? "#15803d" : "#475569",
12536
+ fontSize: "13px",
12537
+ fontWeight: "600",
12538
+ cursor: "pointer",
12539
+ transition: "all 150ms ease",
12540
+ display: "flex",
12541
+ alignItems: "center",
12542
+ gap: "6px",
12543
+ whiteSpace: "nowrap",
12544
+ }, 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: {
12545
+ display: "flex",
12546
+ justifyContent: "center",
12547
+ gap: "8px",
12548
+ marginBottom: "20px",
12549
+ flexWrap: "wrap",
12550
+ }, children: ["🏄 Surfen", "🪁 Wingen", "🏄‍♀️ SUP", "💨 Windsurfen"].map((activity) => (u$2("span", { style: {
12551
+ background: "rgba(255,255,255,0.15)",
12552
+ backdropFilter: "blur(4px)",
12553
+ padding: "6px 12px",
12554
+ borderRadius: "20px",
12555
+ fontSize: "13px",
12556
+ color: "white",
12557
+ fontWeight: "500",
12558
+ }, children: activity }, activity))) }), u$2("button", { onClick: handleCtaClick, style: {
12559
+ width: "100%",
12560
+ padding: "18px 24px",
12561
+ borderRadius: "14px",
12562
+ border: "none",
12563
+ background: "linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",
12564
+ color: "white",
12565
+ fontSize: "18px",
12566
+ fontWeight: "700",
12567
+ cursor: "pointer",
12568
+ transition: "all 150ms ease",
12569
+ boxShadow: "0 8px 24px rgba(245, 158, 11, 0.4), inset 0 1px 0 rgba(255,255,255,0.2)",
12570
+ display: "flex",
12571
+ alignItems: "center",
12572
+ justifyContent: "center",
12573
+ gap: "10px",
12574
+ }, onMouseEnter: (e) => {
12575
+ e.currentTarget.style.transform = "translateY(-2px)";
12576
+ e.currentTarget.style.boxShadow = "0 12px 28px rgba(245, 158, 11, 0.5), inset 0 1px 0 rgba(255,255,255,0.2)";
12577
+ }, onMouseLeave: (e) => {
12578
+ e.currentTarget.style.transform = "translateY(0)";
12579
+ e.currentTarget.style.boxShadow = "0 8px 24px rgba(245, 158, 11, 0.4), inset 0 1px 0 rgba(255,255,255,0.2)";
12580
+ }, 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: {
12581
+ marginTop: "16px",
12582
+ fontSize: "12px",
12583
+ color: "rgba(255,255,255,0.6)",
12584
+ }, children: "G\u00FCltig f\u00FCr alle Buchungen bis 31. Dezember 2025" })] })] }) })] }));
12585
+ // Use portal to render at document body level, escaping any stacking context
12586
+ return $$1(dialogContent, portalContainer);
12587
+ }
12588
+
12313
12589
  // Predefined themes & Style Provider have been moved to ../styles/StyleProvider.tsx
12314
12590
  // Main widget component
12315
12591
  function UniversalBookingWidget({ config: baseConfig }) {
@@ -12352,6 +12628,9 @@
12352
12628
  // PERFORMANCE OPTIMIZATION: Lazy component loading
12353
12629
  const [shouldRenderInstanceSelection, setShouldRenderInstanceSelection] = d$1(false);
12354
12630
  const [shouldRenderBookingForm, setShouldRenderBookingForm] = d$1(false);
12631
+ // Promo dialog state
12632
+ const [showPromoDialog, setShowPromoDialog] = d$1(false);
12633
+ const [widgetContainerRef, setWidgetContainerRef] = d$1(null);
12355
12634
  // Determine initial step and load data
12356
12635
  y$1(() => {
12357
12636
  const initializeWidget = async () => {
@@ -12426,6 +12705,46 @@
12426
12705
  setShouldRenderBookingForm(true);
12427
12706
  }
12428
12707
  }, [currentStep, shouldRenderInstanceSelection, shouldRenderBookingForm]);
12708
+ // Promo dialog: show Xmas promo once per user during holiday season, prevent double-opening across multiple widgets
12709
+ y$1(() => {
12710
+ // Only show during holiday season (December and January)
12711
+ const now = new Date();
12712
+ const month = now.getMonth(); // 0 = January, 11 = December
12713
+ const isHolidaySeason = month === 11 || month === 0; // December (11) or January (0)
12714
+ if (!isHolidaySeason) {
12715
+ return;
12716
+ }
12717
+ const promoId = "xmas-2024";
12718
+ const storageKey = `bigz-promo-${promoId}-shown`;
12719
+ const globalFlagKey = `__bigzPromoShown_${promoId}`;
12720
+ // Check if already shown in this session (localStorage) or claimed by another widget (global flag)
12721
+ const alreadyShown = localStorage.getItem(storageKey) === "true";
12722
+ const claimedByOtherWidget = window[globalFlagKey] === true;
12723
+ if (alreadyShown || claimedByOtherWidget) {
12724
+ return;
12725
+ }
12726
+ // Claim this promo for this widget instance (prevents other widgets from showing it)
12727
+ window[globalFlagKey] = true;
12728
+ // Show the dialog after a short delay for better UX
12729
+ const timer = setTimeout(() => {
12730
+ setShowPromoDialog(true);
12731
+ }, 1000);
12732
+ return () => clearTimeout(timer);
12733
+ }, []);
12734
+ // Handle promo dialog close
12735
+ const handlePromoDialogClose = () => {
12736
+ setShowPromoDialog(false);
12737
+ localStorage.setItem("bigz-promo-xmas-2024-shown", "true");
12738
+ };
12739
+ // Handle promo dialog CTA click - scroll to widget
12740
+ const handlePromoCtaClick = () => {
12741
+ setShowPromoDialog(false);
12742
+ localStorage.setItem("bigz-promo-xmas-2024-shown", "true");
12743
+ // Scroll to the widget container
12744
+ if (widgetContainerRef) {
12745
+ widgetContainerRef.scrollIntoView({ behavior: "smooth", block: "start" });
12746
+ }
12747
+ };
12429
12748
  const loadEventTypes = async () => {
12430
12749
  const requestBody = {
12431
12750
  organizationId: config.organizationId,
@@ -12825,104 +13144,104 @@
12825
13144
  // Main view based on view mode
12826
13145
  if (viewMode === "next-events" && showingPreview) {
12827
13146
  // Next events preview mode
12828
- 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: () => {
12829
- setCurrentStep("eventTypes");
12830
- setShowingPreview(true);
12831
- setEventDetails(null);
12832
- }, onBackToEventTypes: () => {
12833
- setCurrentStep("eventTypes");
12834
- setShowingPreview(true);
12835
- setEventDetails(null);
12836
- }, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => {
12837
- setCurrentStep("eventTypes");
12838
- setShowingPreview(true);
12839
- setEventDetails(null);
12840
- }, systemConfig: systemConfig })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
12841
- setIsSuccess(false);
12842
- setCurrentStep("eventTypes");
12843
- setShowingPreview(true);
12844
- // Reset state
12845
- setSuccessPaymentIntentId(null);
12846
- // Reset lazy loading flags
12847
- setShouldRenderInstanceSelection(false);
12848
- setShouldRenderBookingForm(false);
12849
- // Clean up URL to remove Stripe parameters
12850
- const url = new URL(window.location.href);
12851
- url.searchParams.delete("payment_intent");
12852
- url.searchParams.delete("payment_intent_client_secret");
12853
- url.searchParams.delete("redirect_status");
12854
- window.history.replaceState({}, "", url.toString());
12855
- }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }));
13147
+ 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: () => {
13148
+ setCurrentStep("eventTypes");
13149
+ setShowingPreview(true);
13150
+ setEventDetails(null);
13151
+ }, onBackToEventTypes: () => {
13152
+ setCurrentStep("eventTypes");
13153
+ setShowingPreview(true);
13154
+ setEventDetails(null);
13155
+ }, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => {
13156
+ setCurrentStep("eventTypes");
13157
+ setShowingPreview(true);
13158
+ setEventDetails(null);
13159
+ }, systemConfig: systemConfig })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
13160
+ setIsSuccess(false);
13161
+ setCurrentStep("eventTypes");
13162
+ setShowingPreview(true);
13163
+ // Reset state
13164
+ setSuccessPaymentIntentId(null);
13165
+ // Reset lazy loading flags
13166
+ setShouldRenderInstanceSelection(false);
13167
+ setShouldRenderBookingForm(false);
13168
+ // Clean up URL to remove Stripe parameters
13169
+ const url = new URL(window.location.href);
13170
+ url.searchParams.delete("payment_intent");
13171
+ url.searchParams.delete("payment_intent_client_secret");
13172
+ url.searchParams.delete("redirect_status");
13173
+ window.history.replaceState({}, "", url.toString());
13174
+ }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
12856
13175
  }
12857
13176
  if (viewMode === "next-events" && !showingPreview && currentStep === "eventInstances") {
12858
13177
  // Show all events for the single event type
12859
- return (u$2(StyleProvider, { config: config, children: [shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
12860
- setShowingPreview(true);
12861
- setCurrentStep("eventTypes");
12862
- }, isOpen: currentStep === "eventInstances", onClose: () => {
12863
- setShowingPreview(true);
12864
- setCurrentStep("eventTypes");
12865
- }, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
12866
- setIsSuccess(false);
12867
- setCurrentStep("eventTypes");
12868
- setShowingPreview(true);
12869
- // Reset state
12870
- setSuccessPaymentIntentId(null);
12871
- // Reset lazy loading flags
12872
- setShouldRenderInstanceSelection(false);
12873
- setShouldRenderBookingForm(false);
12874
- // Clean up URL to remove Stripe parameters
12875
- const url = new URL(window.location.href);
12876
- url.searchParams.delete("payment_intent");
12877
- url.searchParams.delete("payment_intent_client_secret");
12878
- url.searchParams.delete("redirect_status");
12879
- window.history.replaceState({}, "", url.toString());
12880
- }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }));
13178
+ return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, children: [shouldRenderInstanceSelection && (u$2(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
13179
+ setShowingPreview(true);
13180
+ setCurrentStep("eventTypes");
13181
+ }, isOpen: currentStep === "eventInstances", onClose: () => {
13182
+ setShowingPreview(true);
13183
+ setCurrentStep("eventTypes");
13184
+ }, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), u$2(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
13185
+ setIsSuccess(false);
13186
+ setCurrentStep("eventTypes");
13187
+ setShowingPreview(true);
13188
+ // Reset state
13189
+ setSuccessPaymentIntentId(null);
13190
+ // Reset lazy loading flags
13191
+ setShouldRenderInstanceSelection(false);
13192
+ setShouldRenderBookingForm(false);
13193
+ // Clean up URL to remove Stripe parameters
13194
+ const url = new URL(window.location.href);
13195
+ url.searchParams.delete("payment_intent");
13196
+ url.searchParams.delete("payment_intent_client_secret");
13197
+ url.searchParams.delete("redirect_status");
13198
+ window.history.replaceState({}, "", url.toString());
13199
+ }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
12881
13200
  }
12882
13201
  if (viewMode === "button" && (isSingleEventTypeMode || isDirectInstanceMode)) {
12883
13202
  // Button mode - show button that opens sidebar/booking directly
12884
- return (u$2(StyleProvider, { config: config, children: u$2("div", { style: {
12885
- display: "flex",
12886
- justifyContent: "center",
12887
- alignItems: "center",
12888
- minHeight: "120px",
12889
- }, children: [u$2("button", { type: "button", style: {
12890
- backgroundColor: "var(--bw-highlight-color)",
12891
- color: "white",
12892
- padding: "16px 32px",
12893
- border: "none",
12894
- borderRadius: "var(--bw-border-radius)",
12895
- fontSize: "18px",
12896
- fontWeight: 600,
12897
- fontFamily: "var(--bw-font-family)",
12898
- boxShadow: "var(--bw-shadow-md)",
12899
- cursor: "pointer",
12900
- }, onClick: () => {
12901
- if (isDirectInstanceMode) {
12902
- setCurrentStep("booking");
12903
- setShouldRenderBookingForm(true);
12904
- }
12905
- else {
12906
- setSidebarOpen(true);
12907
- setShouldRenderInstanceSelection(true);
12908
- }
12909
- }, children: config.buttonText ||
12910
- (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: () => {
12911
- setIsSuccess(false);
12912
- setCurrentStep("eventTypes");
12913
- setSidebarOpen(false);
12914
- // Reset state
12915
- setSuccessPaymentIntentId(null);
12916
- // Reset lazy loading flags
12917
- setShouldRenderInstanceSelection(false);
12918
- setShouldRenderBookingForm(false);
12919
- // Clean up URL to remove Stripe parameters
12920
- const url = new URL(window.location.href);
12921
- url.searchParams.delete("payment_intent");
12922
- url.searchParams.delete("payment_intent_client_secret");
12923
- url.searchParams.delete("redirect_status");
12924
- window.history.replaceState({}, "", url.toString());
12925
- }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }) }));
13203
+ return (u$2(StyleProvider, { config: config, children: [u$2("div", { ref: setWidgetContainerRef, style: {
13204
+ display: "flex",
13205
+ justifyContent: "center",
13206
+ alignItems: "center",
13207
+ minHeight: "120px",
13208
+ }, children: [u$2("button", { type: "button", style: {
13209
+ backgroundColor: "var(--bw-highlight-color)",
13210
+ color: "white",
13211
+ padding: "16px 32px",
13212
+ border: "none",
13213
+ borderRadius: "var(--bw-border-radius)",
13214
+ fontSize: "18px",
13215
+ fontWeight: 600,
13216
+ fontFamily: "var(--bw-font-family)",
13217
+ boxShadow: "var(--bw-shadow-md)",
13218
+ cursor: "pointer",
13219
+ }, onClick: () => {
13220
+ if (isDirectInstanceMode) {
13221
+ setCurrentStep("booking");
13222
+ setShouldRenderBookingForm(true);
13223
+ }
13224
+ else {
13225
+ setSidebarOpen(true);
13226
+ setShouldRenderInstanceSelection(true);
13227
+ }
13228
+ }, children: config.buttonText ||
13229
+ (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: () => {
13230
+ setIsSuccess(false);
13231
+ setCurrentStep("eventTypes");
13232
+ setSidebarOpen(false);
13233
+ // Reset state
13234
+ setSuccessPaymentIntentId(null);
13235
+ // Reset lazy loading flags
13236
+ setShouldRenderInstanceSelection(false);
13237
+ setShouldRenderBookingForm(false);
13238
+ // Clean up URL to remove Stripe parameters
13239
+ const url = new URL(window.location.href);
13240
+ url.searchParams.delete("payment_intent");
13241
+ url.searchParams.delete("payment_intent_client_secret");
13242
+ url.searchParams.delete("redirect_status");
13243
+ window.history.replaceState({}, "", url.toString());
13244
+ }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
12926
13245
  }
12927
13246
  // Cards mode (default) - show event type selection
12928
13247
  const cardsView = (u$2(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, isLoading: isLoading, skeletonCount: getSkeletonCount() }));
@@ -12955,21 +13274,21 @@
12955
13274
  };
12956
13275
  };
12957
13276
  const backHandlers = getBackHandlers();
12958
- 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: () => {
12959
- setIsSuccess(false);
12960
- setCurrentStep("eventTypes");
12961
- // Reset state
12962
- setSuccessPaymentIntentId(null);
12963
- // Reset lazy loading flags
12964
- setShouldRenderInstanceSelection(false);
12965
- setShouldRenderBookingForm(false);
12966
- // Clean up URL to remove Stripe parameters
12967
- const url = new URL(window.location.href);
12968
- url.searchParams.delete("payment_intent");
12969
- url.searchParams.delete("payment_intent_client_secret");
12970
- url.searchParams.delete("redirect_status");
12971
- window.history.replaceState({}, "", url.toString());
12972
- }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }));
13277
+ 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: () => {
13278
+ setIsSuccess(false);
13279
+ setCurrentStep("eventTypes");
13280
+ // Reset state
13281
+ setSuccessPaymentIntentId(null);
13282
+ // Reset lazy loading flags
13283
+ setShouldRenderInstanceSelection(false);
13284
+ setShouldRenderBookingForm(false);
13285
+ // Clean up URL to remove Stripe parameters
13286
+ const url = new URL(window.location.href);
13287
+ url.searchParams.delete("payment_intent");
13288
+ url.searchParams.delete("payment_intent_client_secret");
13289
+ url.searchParams.delete("redirect_status");
13290
+ window.history.replaceState({}, "", url.toString());
13291
+ }, config: config, onError: setError, paymentIntentId: successPaymentIntentId })] }), showPromoDialog && (u$2(PromoDialog, { onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
12973
13292
  }
12974
13293
 
12975
13294
  // Export init function for vanilla JS usage with Preact