@bigz-app/booking-widget 0.1.21 → 0.1.23

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.
@@ -7042,17 +7042,18 @@
7042
7042
  backgroundColor: "var(--bw-background-color)",
7043
7043
  borderRadius: "var(--bw-border-radius)",
7044
7044
  border: `1px solid var(--bw-border-color)`,
7045
- }, children: [u$2("div", { children: [u$2("div", { style: {
7046
- fontSize: "14px",
7047
- color: "var(--bw-text-muted)",
7045
+ }, children: [u$2("div", { children: [u$2("div", { className: "bw-event-type-price", style: {
7046
+ fontWeight: "700",
7047
+ color: "var(--bw-text-color)",
7048
7048
  fontFamily: "var(--bw-font-family)",
7049
- marginBottom: "4px",
7050
- }, children: "Preis ab" }), u$2("div", { style: {
7051
- fontSize: "32px",
7049
+ textAlign: "left",
7050
+ }, children: eventType.groupedDurations && u$2("span", { children: eventType.groupedDurations }) }), u$2("div", { className: "bw-event-type-price", style: {
7051
+ fontSize: "clamp(1.72rem, 4vw, 32px)",
7052
7052
  fontWeight: "700",
7053
7053
  color: "var(--bw-text-color)",
7054
7054
  fontFamily: "var(--bw-font-family)",
7055
- }, children: formatCurrency(eventType.basePrice) })] }), isAvailable && (u$2("button", { onClick: handleBookingClick, style: {
7055
+ textAlign: "right",
7056
+ }, children: u$2("span", { children: ["ab ", formatCurrency(eventType.minPrice)] }) })] }), isAvailable && (u$2("button", { onClick: handleBookingClick, style: {
7056
7057
  backgroundColor: "var(--bw-highlight-color)",
7057
7058
  color: "white",
7058
7059
  padding: "14px 28px",
@@ -7627,10 +7628,10 @@
7627
7628
  e.currentTarget.style.color = "var(--bw-highlight-color)";
7628
7629
  e.currentTarget.style.transform = "translateY(0)";
7629
7630
  }, children: [u$2("span", { style: { fontSize: "16px" }, children: "\uD83D\uDD04" }), "Seite neu laden"] })] }) })) : (u$2("div", { className: "bw-event-type-list", style: { padding: "0px 0px" }, children: u$2("div", { style: {
7630
- display: "flex",
7631
- flexWrap: "wrap",
7632
- justifyContent: "center",
7631
+ display: "grid",
7632
+ gridTemplateColumns: "repeat(auto-fill, minmax(350px, 1fr))",
7633
7633
  gap: "24px",
7634
+ gridAutoRows: "1fr",
7634
7635
  }, children: eventTypes.map((eventType) => {
7635
7636
  const isAvailable = eventType.hasAvailableInstances;
7636
7637
  return (u$2("div", { className: "bw-event-type-card", style: {
@@ -7638,16 +7639,11 @@
7638
7639
  backgroundColor: "var(--bw-surface-color)",
7639
7640
  border: `1px solid var(--bw-border-color)`,
7640
7641
  borderRadius: "var(--bw-border-radius)",
7641
- overflow: "hidden",
7642
7642
  transition: "all 0.3s ease",
7643
7643
  cursor: isAvailable ? "pointer" : "not-allowed",
7644
7644
  opacity: isAvailable ? 1 : 0.6,
7645
7645
  boxShadow: "var(--bw-shadow-md)",
7646
7646
  fontFamily: "var(--bw-font-family)",
7647
- maxWidth: "500px",
7648
- flex: "1 1 350px",
7649
- display: "flex",
7650
- flexDirection: "column",
7651
7647
  }, onClick: () => isAvailable && onEventTypeSelect(eventType), onMouseEnter: (e) => {
7652
7648
  if (isAvailable) {
7653
7649
  e.currentTarget.style.boxShadow = "var(--bw-shadow-lg)";
@@ -7674,7 +7670,12 @@
7674
7670
  padding: "3px 8px",
7675
7671
  borderRadius: "var(--bw-border-radius)",
7676
7672
  fontFamily: "var(--bw-font-family)",
7677
- }, children: eventType.category.name }) }), u$2("div", { className: "bw-event-type-img", style: { position: "relative", width: "100%", height: "300px" }, children: u$2(ImageCarousel, { images: eventType.images, eventName: eventType.name }) }), u$2("div", { className: "bw-event-type-content", style: { padding: "12px 18px" }, children: [u$2("h2", { className: "bw-event-type-title", style: {
7673
+ }, children: eventType.category.name }) }), u$2("div", { className: "bw-event-type-img", style: { position: "relative", width: "100%", height: "300px" }, children: u$2(ImageCarousel, { images: eventType.images, eventName: eventType.name }) }), u$2("div", { className: "bw-event-type-content", style: {
7674
+ padding: "12px 18px",
7675
+ display: "flex",
7676
+ flexDirection: "column",
7677
+ justifyContent: "space-between",
7678
+ }, children: [u$2("h2", { className: "bw-event-type-title", style: {
7678
7679
  fontSize: "clamp(1.1rem, 2.5vw, 24px)",
7679
7680
  fontWeight: "700",
7680
7681
  color: "var(--bw-text-color)",
@@ -7727,9 +7728,7 @@
7727
7728
  overflow: "hidden",
7728
7729
  whiteSpace: "nowrap",
7729
7730
  flex: "1",
7730
- }, children: highlight.trim() })] }, index))) }) })) : (
7731
- // Fallback to description with React Markdown
7732
- eventType.description && (u$2("div", { className: "bw-event-type-desc", style: {
7731
+ }, children: highlight.trim() })] }, index))) }) })) : eventType.description ? (u$2("div", { className: "bw-event-type-desc", style: {
7733
7732
  color: "var(--bw-text-muted)",
7734
7733
  fontSize: "clamp(0.95rem, 2vw, 16px)",
7735
7734
  lineHeight: "1.6",
@@ -7746,13 +7745,30 @@
7746
7745
  overflow: "hidden",
7747
7746
  }, children: Markdown({
7748
7747
  children: preprocessMarkdown(eventType.description),
7749
- }) }) }))) }), u$2("div", { children: [u$2("div", { className: "bw-event-type-price", style: {
7748
+ }) }) })) : (u$2("div", { className: "bw-event-type-desc", style: {
7749
+ color: "var(--bw-text-muted)",
7750
+ fontSize: "clamp(0.95rem, 2vw, 16px)",
7751
+ lineHeight: "1.6",
7752
+ fontFamily: "var(--bw-font-family)",
7753
+ margin: "10px 0 10px 0",
7754
+ minHeight: "128px",
7755
+ maxHeight: "128px",
7756
+ overflow: "hidden",
7757
+ textAlign: "left",
7758
+ }, children: "\u00A0" })) }), u$2("div", { children: [u$2("div", { className: "bw-event-type-price", style: {
7759
+ fontWeight: "700",
7760
+ color: "var(--bw-text-color)",
7761
+ fontFamily: "var(--bw-font-family)",
7762
+ textAlign: "right",
7763
+ }, children: eventType.groupedDurations.length > 1 ? (u$2("span", { children: eventType.groupedDurations })) : (u$2("span", { children: eventType.cheapestDurationPerDay % 60 === 0
7764
+ ? `${eventType.cheapestDurationPerDay / 60} Stunde${eventType.cheapestDurationPerDay / 60 > 1 ? "n" : ""}`
7765
+ : `${eventType.cheapestDurationPerDay} Minuten` })) }), u$2("div", { className: "bw-event-type-price", style: {
7750
7766
  fontSize: "clamp(1.72rem, 4vw, 32px)",
7751
7767
  fontWeight: "700",
7752
7768
  color: "var(--bw-text-color)",
7753
7769
  fontFamily: "var(--bw-font-family)",
7754
7770
  textAlign: "right",
7755
- }, children: formatCurrency(eventType.basePrice) }), " "] }), u$2("div", { style: {
7771
+ }, children: u$2("span", { children: ["ab ", formatCurrency(eventType.minPrice)] }) })] }), u$2("div", { style: {
7756
7772
  display: "flex",
7757
7773
  justifyContent: "flex-end",
7758
7774
  alignItems: "center",
@@ -9179,14 +9195,39 @@
9179
9195
  return;
9180
9196
  }
9181
9197
  // First, confirm the payment with Stripe
9198
+ const confirmParams = {
9199
+ return_url: "https://bigz.surfschule-zingst.de/booking/success",
9200
+ };
9201
+ // Ensure return_url is properly formatted and doesn't contain fragment identifiers
9202
+ try {
9203
+ const url = new URL(confirmParams.return_url);
9204
+ // Remove any fragment identifiers that might cause issues
9205
+ url.hash = "";
9206
+ confirmParams.return_url = url.toString();
9207
+ }
9208
+ catch (e) {
9209
+ console.warn("[PAYMENT_FORM] Invalid return_url, using fallback:", confirmParams.return_url);
9210
+ // Fallback to current origin if URL parsing fails
9211
+ confirmParams.return_url = window.location.origin + window.location.pathname;
9212
+ }
9213
+ console.log("[PAYMENT_FORM] Confirming payment with params:", {
9214
+ paymentIntentId: clientSecret.split("_secret_")[0],
9215
+ return_url: confirmParams.return_url,
9216
+ redirect: "if_required",
9217
+ });
9182
9218
  const { error, paymentIntent } = await stripe.confirmPayment({
9183
9219
  elements,
9184
- confirmParams: {
9185
- return_url: window.location.href,
9186
- },
9220
+ confirmParams,
9187
9221
  redirect: "if_required",
9188
9222
  });
9189
9223
  if (error) {
9224
+ console.error("[PAYMENT_FORM] Payment confirmation error:", {
9225
+ type: error.type,
9226
+ code: error.code,
9227
+ message: error.message,
9228
+ decline_code: error.decline_code,
9229
+ payment_intent: error.payment_intent,
9230
+ });
9190
9231
  if (error.type === "card_error" || error.type === "validation_error") {
9191
9232
  setPaymentError(error.message || "Zahlungsfehler");
9192
9233
  }
@@ -9383,16 +9424,41 @@
9383
9424
  const endpoint = isConnectMode
9384
9425
  ? "/booking/create-payment-intent"
9385
9426
  : "/booking-proxy/create-payment-intent";
9386
- // Build request data
9427
+ // Build request data with validation
9387
9428
  const requestData = {
9388
9429
  eventInstanceId: config.eventInstanceId || eventDetails.id,
9389
9430
  organizationId: config.organizationId, // Required for payment intent creation
9390
- amount: totalAmount,
9431
+ amount: Math.round(totalAmount), // Ensure integer (should already be in cents)
9391
9432
  currency: "eur",
9392
- participants: formData.participants.filter((p) => p.name.trim()),
9433
+ participants: formData.participants.filter((p) => p.name?.trim()),
9393
9434
  discountCode: discountCode?.code,
9394
- customerEmail: formData.customerEmail,
9435
+ customerEmail: formData.customerEmail?.trim(),
9395
9436
  };
9437
+ // Validate required fields
9438
+ if (!requestData.eventInstanceId) {
9439
+ throw new Error("Event instance ID is required");
9440
+ }
9441
+ if (!requestData.organizationId) {
9442
+ throw new Error("Organization ID is required");
9443
+ }
9444
+ if (!requestData.amount || requestData.amount <= 0) {
9445
+ throw new Error("Valid amount is required");
9446
+ }
9447
+ if (!requestData.participants || requestData.participants.length === 0) {
9448
+ throw new Error("At least one participant is required");
9449
+ }
9450
+ if (!requestData.customerEmail) {
9451
+ throw new Error("Customer email is required");
9452
+ }
9453
+ console.log("[PAYMENT_FORM] Creating payment intent:", {
9454
+ endpoint,
9455
+ mode: isConnectMode ? "connect" : "apikey",
9456
+ amount: requestData.amount,
9457
+ currency: requestData.currency,
9458
+ participantCount: requestData.participants.length,
9459
+ organizationId: requestData.organizationId,
9460
+ eventInstanceId: requestData.eventInstanceId,
9461
+ });
9396
9462
  // Add mode-specific fields
9397
9463
  if (!isConnectMode) {
9398
9464
  // ApiKey mode needs additional fields
@@ -9408,14 +9474,25 @@
9408
9474
  });
9409
9475
  const data = await response.json();
9410
9476
  if (response.ok) {
9477
+ console.log("[PAYMENT_FORM] Payment intent created successfully:", {
9478
+ hasClientSecret: !!data.clientSecret,
9479
+ clientSecretPrefix: `${data.clientSecret?.substring(0, 20)}...`,
9480
+ });
9411
9481
  setClientSecret(data.clientSecret);
9412
9482
  }
9413
9483
  else {
9484
+ console.error("[PAYMENT_FORM] Payment intent creation failed:", {
9485
+ status: response.status,
9486
+ error: data.error,
9487
+ details: data.details,
9488
+ requestData: { ...requestData, customerEmail: "[redacted]" },
9489
+ });
9414
9490
  setPaymentError(data.error || "Fehler beim Erstellen der Zahlungsabsicht");
9415
9491
  }
9416
9492
  }
9417
9493
  catch (err) {
9418
- setPaymentError("Fehler beim Erstellen der Zahlungsabsicht");
9494
+ console.error("[PAYMENT_FORM] Payment intent creation error:", err);
9495
+ setPaymentError(err.message || "Fehler beim Erstellen der Zahlungsabsicht");
9419
9496
  }
9420
9497
  finally {
9421
9498
  setIsCreatingPaymentIntent(false);
@@ -11678,6 +11755,25 @@
11678
11755
  if (data.connectedAccountId) {
11679
11756
  stripeOptions.stripeAccount = data.connectedAccountId;
11680
11757
  }
11758
+ // Add options to prevent sandbox warnings in vanilla JS environments
11759
+ if (typeof window !== "undefined" && window.document) {
11760
+ // Check if we're in a potential iframe or restricted environment
11761
+ try {
11762
+ // Test if we can access parent window (this will throw in sandbox)
11763
+ const hasParentAccess = window.parent === window || window.parent.location.href;
11764
+ // Add apiVersion to ensure compatibility
11765
+ stripeOptions.apiVersion = "2025-02-24.acacia";
11766
+ // For vanilla JS builds, explicitly set betas to empty array to avoid issues
11767
+ if (!stripeOptions.betas) {
11768
+ stripeOptions.betas = [];
11769
+ }
11770
+ }
11771
+ catch (e) {
11772
+ // We're likely in a sandboxed environment, add specific options
11773
+ console.warn("[WIDGET] Detected restricted environment, adjusting Stripe options");
11774
+ stripeOptions.betas = [];
11775
+ }
11776
+ }
11681
11777
  setStripePromise(loadStripe(data.stripePublishableKey, stripeOptions));
11682
11778
  }
11683
11779
  // If only one instance, skip to booking
@@ -11719,6 +11815,25 @@
11719
11815
  if (data.connectedAccountId) {
11720
11816
  stripeOptions.stripeAccount = data.connectedAccountId;
11721
11817
  }
11818
+ // Add options to prevent sandbox warnings in vanilla JS environments
11819
+ if (typeof window !== "undefined" && window.document) {
11820
+ // Check if we're in a potential iframe or restricted environment
11821
+ try {
11822
+ // Test if we can access parent window (this will throw in sandbox)
11823
+ const hasParentAccess = window.parent === window || window.parent.location.href;
11824
+ // Add apiVersion to ensure compatibility
11825
+ stripeOptions.apiVersion = "2025-02-24.acacia";
11826
+ // For vanilla JS builds, explicitly set betas to empty array to avoid issues
11827
+ if (!stripeOptions.betas) {
11828
+ stripeOptions.betas = [];
11829
+ }
11830
+ }
11831
+ catch (e) {
11832
+ // We're likely in a sandboxed environment, add specific options
11833
+ console.warn("[WIDGET] Detected restricted environment, adjusting Stripe options");
11834
+ stripeOptions.betas = [];
11835
+ }
11836
+ }
11722
11837
  setStripePromise(loadStripe(data.stripePublishableKey, stripeOptions));
11723
11838
  }
11724
11839
  }