@uptrademedia/site-kit 1.0.35 → 1.0.36

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.
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import React5, { useState, useEffect, useMemo, useCallback } from 'react';
2
+ import React5, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
3
3
 
4
4
  // src/commerce/utils.ts
5
5
  function formatPrice(amount, currency = "USD") {
@@ -248,6 +248,24 @@ async function registerForEvent(eventId, scheduleId, customer) {
248
248
  return { success: false, error: "Network error. Please try again." };
249
249
  }
250
250
  }
251
+ async function fetchProcessorConfig() {
252
+ const { apiUrl, apiKey } = getApiConfig();
253
+ if (!apiKey) return null;
254
+ try {
255
+ const response = await fetch(`${apiUrl}/api/public/commerce/processor-config`, {
256
+ method: "POST",
257
+ headers: {
258
+ "Content-Type": "application/json",
259
+ "x-api-key": apiKey
260
+ },
261
+ body: JSON.stringify({})
262
+ });
263
+ if (!response.ok) return null;
264
+ return await response.json();
265
+ } catch {
266
+ return null;
267
+ }
268
+ }
251
269
  async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
252
270
  const { apiUrl, apiKey } = getApiConfig();
253
271
  const options = typeof optionsOrOfferingId === "string" ? { offeringId: optionsOrOfferingId, ...legacyOptions } : optionsOrOfferingId;
@@ -268,8 +286,12 @@ async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
268
286
  })
269
287
  });
270
288
  if (!response.ok) {
271
- const error = await response.json();
272
- return { success: false, error: error.message || "Checkout failed" };
289
+ const error = await response.json().catch(() => ({}));
290
+ const message = error?.message || (typeof error?.error === "string" ? error.error : null) || "Checkout failed";
291
+ if (typeof console !== "undefined" && console.error) {
292
+ console.error("[Commerce] Checkout failed:", response.status, message, error);
293
+ }
294
+ return { success: false, error: message };
273
295
  }
274
296
  const result = await response.json();
275
297
  return {
@@ -2805,6 +2827,17 @@ function CalendarView({
2805
2827
  }, children: "Loading..." })
2806
2828
  ] });
2807
2829
  }
2830
+ function loadSquareSDK(environment) {
2831
+ return new Promise((resolve, reject) => {
2832
+ if (typeof window === "undefined") return reject(new Error("No window"));
2833
+ if (window.Square) return resolve();
2834
+ const script = document.createElement("script");
2835
+ script.src = environment === "sandbox" ? "https://sandbox.web.squarecdn.com/v1/square.js" : "https://web.squarecdn.com/v1/square.js";
2836
+ script.onload = () => resolve();
2837
+ script.onerror = () => reject(new Error("Failed to load Square SDK"));
2838
+ document.head.appendChild(script);
2839
+ });
2840
+ }
2808
2841
  function EventModal({
2809
2842
  event,
2810
2843
  schedule: propSchedule,
@@ -2829,13 +2862,54 @@ function EventModal({
2829
2862
  });
2830
2863
  const [additionalData, setAdditionalData] = useState({});
2831
2864
  const [processor, setProcessor] = useState(null);
2865
+ const [processorConfig, setProcessorConfig] = useState(null);
2866
+ const [squareCard, setSquareCard] = useState(null);
2867
+ const [cardReady, setCardReady] = useState(false);
2868
+ const cardContainerRef = useRef(null);
2832
2869
  const schedule = propSchedule || event?.schedules?.[0] || event?.next_schedule;
2833
2870
  useEffect(() => {
2834
- if (isOpen) {
2835
- fetchActiveProcessor().then((p) => {
2836
- if (p) setProcessor(p);
2871
+ if (!isOpen) return;
2872
+ fetchProcessorConfig().then(async (config) => {
2873
+ setProcessorConfig(config);
2874
+ if (config?.processor) setProcessor(config.processor);
2875
+ if (config?.processor === "square" && config.squareAppId && config.squareLocationId) {
2876
+ try {
2877
+ await loadSquareSDK(config.squareEnvironment || "production");
2878
+ const Square = window.Square;
2879
+ const payments = Square.payments(config.squareAppId, config.squareLocationId);
2880
+ const card = await payments.card({
2881
+ style: {
2882
+ ".input-container": {
2883
+ borderColor: "#d1d5db",
2884
+ borderRadius: "6px"
2885
+ },
2886
+ ".input-container.is-focus": {
2887
+ borderColor: "#2563eb"
2888
+ },
2889
+ ".input-container.is-error": {
2890
+ borderColor: "#dc2626"
2891
+ }
2892
+ }
2893
+ });
2894
+ await card.attach("#sq-card-container");
2895
+ setSquareCard(card);
2896
+ setCardReady(true);
2897
+ } catch (err) {
2898
+ console.error("[Commerce] Square card init failed:", err);
2899
+ }
2900
+ }
2901
+ });
2902
+ return () => {
2903
+ setSquareCard((prev) => {
2904
+ if (prev) {
2905
+ prev.destroy?.().catch(() => {
2906
+ });
2907
+ }
2908
+ return null;
2837
2909
  });
2838
- }
2910
+ setCardReady(false);
2911
+ setProcessorConfig(null);
2912
+ };
2839
2913
  }, [isOpen]);
2840
2914
  useEffect(() => {
2841
2915
  if (isOpen && event) {
@@ -2897,17 +2971,34 @@ function EventModal({
2897
2971
  onError?.(result.error || "Registration failed");
2898
2972
  }
2899
2973
  } else {
2900
- const result = await createCheckoutSession(event.id, {
2974
+ let sourceId;
2975
+ if (squareCard && cardReady) {
2976
+ const tokenResult = await squareCard.tokenize();
2977
+ if (tokenResult.status !== "OK") {
2978
+ const msg = tokenResult.errors?.[0]?.message || "Card verification failed. Please check your card details.";
2979
+ setError(msg);
2980
+ onError?.(msg);
2981
+ setLoading(false);
2982
+ return;
2983
+ }
2984
+ sourceId = tokenResult.token;
2985
+ }
2986
+ const result = await createCheckoutSession({
2987
+ offeringId: event.id,
2901
2988
  scheduleId: schedule.id,
2902
2989
  quantity,
2903
2990
  customer: {
2904
2991
  ...customer,
2905
2992
  ...additionalData
2906
2993
  },
2994
+ sourceId,
2907
2995
  successUrl: window.location.href + "?registration=success",
2908
2996
  cancelUrl: window.location.href
2909
2997
  });
2910
- if (result.success && result.payment_url) {
2998
+ if (result.success && !result.payment_url) {
2999
+ setSuccess(true);
3000
+ onSuccess?.(result);
3001
+ } else if (result.success && result.payment_url) {
2911
3002
  window.location.href = result.payment_url;
2912
3003
  } else {
2913
3004
  setError(result.error || "Checkout failed");
@@ -3231,6 +3322,30 @@ function EventModal({
3231
3322
  )
3232
3323
  ] }, field.name))
3233
3324
  ] }),
3325
+ !isFree && processor === "square" && /* @__PURE__ */ jsxs("div", { style: { marginTop: "1rem" }, children: [
3326
+ /* @__PURE__ */ jsx("label", { style: {
3327
+ display: "block",
3328
+ fontSize: "0.875rem",
3329
+ fontWeight: 500,
3330
+ color: "#374151",
3331
+ marginBottom: "0.375rem"
3332
+ }, children: "Card Details *" }),
3333
+ /* @__PURE__ */ jsx(
3334
+ "div",
3335
+ {
3336
+ id: "sq-card-container",
3337
+ ref: cardContainerRef,
3338
+ style: {
3339
+ minHeight: "42px",
3340
+ border: "1px solid #d1d5db",
3341
+ borderRadius: "6px",
3342
+ padding: "0.5rem 0.75rem",
3343
+ background: "#fff"
3344
+ }
3345
+ }
3346
+ ),
3347
+ !cardReady && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "#9ca3af", marginTop: "0.25rem" }, children: "Loading card form..." })
3348
+ ] }),
3234
3349
  error && /* @__PURE__ */ jsx("div", { style: {
3235
3350
  marginTop: "1rem",
3236
3351
  padding: "0.75rem",
@@ -3244,7 +3359,7 @@ function EventModal({
3244
3359
  "button",
3245
3360
  {
3246
3361
  type: "submit",
3247
- disabled: loading,
3362
+ disabled: loading || !isFree && processor === "square" && !cardReady,
3248
3363
  style: {
3249
3364
  width: "100%",
3250
3365
  marginTop: "1.25rem",
@@ -3253,9 +3368,9 @@ function EventModal({
3253
3368
  fontWeight: 600,
3254
3369
  borderRadius: "8px",
3255
3370
  border: "none",
3256
- background: loading ? "#93c5fd" : "#2563eb",
3371
+ background: loading || !isFree && processor === "square" && !cardReady ? "#93c5fd" : "#2563eb",
3257
3372
  color: "white",
3258
- cursor: loading ? "not-allowed" : "pointer"
3373
+ cursor: loading || !isFree && processor === "square" && !cardReady ? "not-allowed" : "pointer"
3259
3374
  },
3260
3375
  children: loading ? "Processing..." : isFree ? "Register Free" : `Pay ${formatPrice(total, event.currency)}`
3261
3376
  }
@@ -3909,6 +4024,6 @@ function getApiKey() {
3909
4024
  return "";
3910
4025
  }
3911
4026
 
3912
- export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, EventsWidget, OfferingCard, OfferingList, ProductDetail, ProductEmbed, ProductGrid, ProductPage, RegistrationForm, UpcomingEvents, createCheckoutSession, fetchActiveProcessor, fetchCategories, fetchLatestOffering, fetchNextEvent, fetchOffering, fetchOfferings, fetchProductBySlug, fetchProducts, fetchProductsPublic, fetchServices, fetchUpcomingEvents, formatDate, formatDateRange, formatDateTime, formatPrice, formatTime, getOfferingUrl, getRelativeTimeUntil, getSpotsRemaining, isEventSoldOut, registerForEvent, useEventModal };
3913
- //# sourceMappingURL=chunk-CNPLYTFZ.mjs.map
3914
- //# sourceMappingURL=chunk-CNPLYTFZ.mjs.map
4027
+ export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, EventsWidget, OfferingCard, OfferingList, ProductDetail, ProductEmbed, ProductGrid, ProductPage, RegistrationForm, UpcomingEvents, createCheckoutSession, fetchActiveProcessor, fetchCategories, fetchLatestOffering, fetchNextEvent, fetchOffering, fetchOfferings, fetchProcessorConfig, fetchProductBySlug, fetchProducts, fetchProductsPublic, fetchServices, fetchUpcomingEvents, formatDate, formatDateRange, formatDateTime, formatPrice, formatTime, getOfferingUrl, getRelativeTimeUntil, getSpotsRemaining, isEventSoldOut, registerForEvent, useEventModal };
4028
+ //# sourceMappingURL=chunk-R4OKQVFD.mjs.map
4029
+ //# sourceMappingURL=chunk-R4OKQVFD.mjs.map