@uptrademedia/site-kit 1.0.35 → 1.0.37

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,17 @@ 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 text = await response.text();
290
+ let error = {};
291
+ try {
292
+ error = JSON.parse(text);
293
+ } catch {
294
+ }
295
+ const message = (typeof error?.message === "string" ? error.message : null) || (typeof error?.error === "string" ? error.error : null) || "Payment could not be processed. Please try again or use a different card.";
296
+ if (typeof console !== "undefined" && console.error) {
297
+ console.error("[Commerce] Checkout failed:", response.status, message, error);
298
+ }
299
+ return { success: false, error: message };
273
300
  }
274
301
  const result = await response.json();
275
302
  return {
@@ -2805,6 +2832,17 @@ function CalendarView({
2805
2832
  }, children: "Loading..." })
2806
2833
  ] });
2807
2834
  }
2835
+ function loadSquareSDK(environment) {
2836
+ return new Promise((resolve, reject) => {
2837
+ if (typeof window === "undefined") return reject(new Error("No window"));
2838
+ if (window.Square) return resolve();
2839
+ const script = document.createElement("script");
2840
+ script.src = environment === "sandbox" ? "https://sandbox.web.squarecdn.com/v1/square.js" : "https://web.squarecdn.com/v1/square.js";
2841
+ script.onload = () => resolve();
2842
+ script.onerror = () => reject(new Error("Failed to load Square SDK"));
2843
+ document.head.appendChild(script);
2844
+ });
2845
+ }
2808
2846
  function EventModal({
2809
2847
  event,
2810
2848
  schedule: propSchedule,
@@ -2829,13 +2867,54 @@ function EventModal({
2829
2867
  });
2830
2868
  const [additionalData, setAdditionalData] = useState({});
2831
2869
  const [processor, setProcessor] = useState(null);
2870
+ const [processorConfig, setProcessorConfig] = useState(null);
2871
+ const [squareCard, setSquareCard] = useState(null);
2872
+ const [cardReady, setCardReady] = useState(false);
2873
+ const cardContainerRef = useRef(null);
2832
2874
  const schedule = propSchedule || event?.schedules?.[0] || event?.next_schedule;
2833
2875
  useEffect(() => {
2834
- if (isOpen) {
2835
- fetchActiveProcessor().then((p) => {
2836
- if (p) setProcessor(p);
2876
+ if (!isOpen) return;
2877
+ fetchProcessorConfig().then(async (config) => {
2878
+ setProcessorConfig(config);
2879
+ if (config?.processor) setProcessor(config.processor);
2880
+ if (config?.processor === "square" && config.squareAppId && config.squareLocationId) {
2881
+ try {
2882
+ await loadSquareSDK(config.squareEnvironment || "production");
2883
+ const Square = window.Square;
2884
+ const payments = Square.payments(config.squareAppId, config.squareLocationId);
2885
+ const card = await payments.card({
2886
+ style: {
2887
+ ".input-container": {
2888
+ borderColor: "#d1d5db",
2889
+ borderRadius: "6px"
2890
+ },
2891
+ ".input-container.is-focus": {
2892
+ borderColor: "#2563eb"
2893
+ },
2894
+ ".input-container.is-error": {
2895
+ borderColor: "#dc2626"
2896
+ }
2897
+ }
2898
+ });
2899
+ await card.attach("#sq-card-container");
2900
+ setSquareCard(card);
2901
+ setCardReady(true);
2902
+ } catch (err) {
2903
+ console.error("[Commerce] Square card init failed:", err);
2904
+ }
2905
+ }
2906
+ });
2907
+ return () => {
2908
+ setSquareCard((prev) => {
2909
+ if (prev) {
2910
+ prev.destroy?.().catch(() => {
2911
+ });
2912
+ }
2913
+ return null;
2837
2914
  });
2838
- }
2915
+ setCardReady(false);
2916
+ setProcessorConfig(null);
2917
+ };
2839
2918
  }, [isOpen]);
2840
2919
  useEffect(() => {
2841
2920
  if (isOpen && event) {
@@ -2897,17 +2976,34 @@ function EventModal({
2897
2976
  onError?.(result.error || "Registration failed");
2898
2977
  }
2899
2978
  } else {
2900
- const result = await createCheckoutSession(event.id, {
2979
+ let sourceId;
2980
+ if (squareCard && cardReady) {
2981
+ const tokenResult = await squareCard.tokenize();
2982
+ if (tokenResult.status !== "OK") {
2983
+ const msg = tokenResult.errors?.[0]?.message || "Card verification failed. Please check your card details.";
2984
+ setError(msg);
2985
+ onError?.(msg);
2986
+ setLoading(false);
2987
+ return;
2988
+ }
2989
+ sourceId = tokenResult.token;
2990
+ }
2991
+ const result = await createCheckoutSession({
2992
+ offeringId: event.id,
2901
2993
  scheduleId: schedule.id,
2902
2994
  quantity,
2903
2995
  customer: {
2904
2996
  ...customer,
2905
2997
  ...additionalData
2906
2998
  },
2999
+ sourceId,
2907
3000
  successUrl: window.location.href + "?registration=success",
2908
3001
  cancelUrl: window.location.href
2909
3002
  });
2910
- if (result.success && result.payment_url) {
3003
+ if (result.success && !result.payment_url) {
3004
+ setSuccess(true);
3005
+ onSuccess?.(result);
3006
+ } else if (result.success && result.payment_url) {
2911
3007
  window.location.href = result.payment_url;
2912
3008
  } else {
2913
3009
  setError(result.error || "Checkout failed");
@@ -3231,6 +3327,30 @@ function EventModal({
3231
3327
  )
3232
3328
  ] }, field.name))
3233
3329
  ] }),
3330
+ !isFree && processor === "square" && /* @__PURE__ */ jsxs("div", { style: { marginTop: "1rem" }, children: [
3331
+ /* @__PURE__ */ jsx("label", { style: {
3332
+ display: "block",
3333
+ fontSize: "0.875rem",
3334
+ fontWeight: 500,
3335
+ color: "#374151",
3336
+ marginBottom: "0.375rem"
3337
+ }, children: "Card Details *" }),
3338
+ /* @__PURE__ */ jsx(
3339
+ "div",
3340
+ {
3341
+ id: "sq-card-container",
3342
+ ref: cardContainerRef,
3343
+ style: {
3344
+ minHeight: "42px",
3345
+ border: "1px solid #d1d5db",
3346
+ borderRadius: "6px",
3347
+ padding: "0.5rem 0.75rem",
3348
+ background: "#fff"
3349
+ }
3350
+ }
3351
+ ),
3352
+ !cardReady && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "#9ca3af", marginTop: "0.25rem" }, children: "Loading card form..." })
3353
+ ] }),
3234
3354
  error && /* @__PURE__ */ jsx("div", { style: {
3235
3355
  marginTop: "1rem",
3236
3356
  padding: "0.75rem",
@@ -3244,7 +3364,7 @@ function EventModal({
3244
3364
  "button",
3245
3365
  {
3246
3366
  type: "submit",
3247
- disabled: loading,
3367
+ disabled: loading || !isFree && processor === "square" && !cardReady,
3248
3368
  style: {
3249
3369
  width: "100%",
3250
3370
  marginTop: "1.25rem",
@@ -3253,9 +3373,9 @@ function EventModal({
3253
3373
  fontWeight: 600,
3254
3374
  borderRadius: "8px",
3255
3375
  border: "none",
3256
- background: loading ? "#93c5fd" : "#2563eb",
3376
+ background: loading || !isFree && processor === "square" && !cardReady ? "#93c5fd" : "#2563eb",
3257
3377
  color: "white",
3258
- cursor: loading ? "not-allowed" : "pointer"
3378
+ cursor: loading || !isFree && processor === "square" && !cardReady ? "not-allowed" : "pointer"
3259
3379
  },
3260
3380
  children: loading ? "Processing..." : isFree ? "Register Free" : `Pay ${formatPrice(total, event.currency)}`
3261
3381
  }
@@ -3909,6 +4029,6 @@ function getApiKey() {
3909
4029
  return "";
3910
4030
  }
3911
4031
 
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
4032
+ 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 };
4033
+ //# sourceMappingURL=chunk-35ZB446O.mjs.map
4034
+ //# sourceMappingURL=chunk-35ZB446O.mjs.map