@uptrademedia/site-kit 1.0.34 → 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.
@@ -254,6 +254,24 @@ async function registerForEvent(eventId, scheduleId, customer) {
254
254
  return { success: false, error: "Network error. Please try again." };
255
255
  }
256
256
  }
257
+ async function fetchProcessorConfig() {
258
+ const { apiUrl, apiKey } = getApiConfig();
259
+ if (!apiKey) return null;
260
+ try {
261
+ const response = await fetch(`${apiUrl}/api/public/commerce/processor-config`, {
262
+ method: "POST",
263
+ headers: {
264
+ "Content-Type": "application/json",
265
+ "x-api-key": apiKey
266
+ },
267
+ body: JSON.stringify({})
268
+ });
269
+ if (!response.ok) return null;
270
+ return await response.json();
271
+ } catch {
272
+ return null;
273
+ }
274
+ }
257
275
  async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
258
276
  const { apiUrl, apiKey } = getApiConfig();
259
277
  const options = typeof optionsOrOfferingId === "string" ? { offeringId: optionsOrOfferingId, ...legacyOptions } : optionsOrOfferingId;
@@ -274,8 +292,12 @@ async function createCheckoutSession(optionsOrOfferingId, legacyOptions) {
274
292
  })
275
293
  });
276
294
  if (!response.ok) {
277
- const error = await response.json();
278
- return { success: false, error: error.message || "Checkout failed" };
295
+ const error = await response.json().catch(() => ({}));
296
+ const message = error?.message || (typeof error?.error === "string" ? error.error : null) || "Checkout failed";
297
+ if (typeof console !== "undefined" && console.error) {
298
+ console.error("[Commerce] Checkout failed:", response.status, message, error);
299
+ }
300
+ return { success: false, error: message };
279
301
  }
280
302
  const result = await response.json();
281
303
  return {
@@ -2811,6 +2833,17 @@ function CalendarView({
2811
2833
  }, children: "Loading..." })
2812
2834
  ] });
2813
2835
  }
2836
+ function loadSquareSDK(environment) {
2837
+ return new Promise((resolve, reject) => {
2838
+ if (typeof window === "undefined") return reject(new Error("No window"));
2839
+ if (window.Square) return resolve();
2840
+ const script = document.createElement("script");
2841
+ script.src = environment === "sandbox" ? "https://sandbox.web.squarecdn.com/v1/square.js" : "https://web.squarecdn.com/v1/square.js";
2842
+ script.onload = () => resolve();
2843
+ script.onerror = () => reject(new Error("Failed to load Square SDK"));
2844
+ document.head.appendChild(script);
2845
+ });
2846
+ }
2814
2847
  function EventModal({
2815
2848
  event,
2816
2849
  schedule: propSchedule,
@@ -2834,7 +2867,56 @@ function EventModal({
2834
2867
  phone: ""
2835
2868
  });
2836
2869
  const [additionalData, setAdditionalData] = React5.useState({});
2870
+ const [processor, setProcessor] = React5.useState(null);
2871
+ const [processorConfig, setProcessorConfig] = React5.useState(null);
2872
+ const [squareCard, setSquareCard] = React5.useState(null);
2873
+ const [cardReady, setCardReady] = React5.useState(false);
2874
+ const cardContainerRef = React5.useRef(null);
2837
2875
  const schedule = propSchedule || event?.schedules?.[0] || event?.next_schedule;
2876
+ React5.useEffect(() => {
2877
+ if (!isOpen) return;
2878
+ fetchProcessorConfig().then(async (config) => {
2879
+ setProcessorConfig(config);
2880
+ if (config?.processor) setProcessor(config.processor);
2881
+ if (config?.processor === "square" && config.squareAppId && config.squareLocationId) {
2882
+ try {
2883
+ await loadSquareSDK(config.squareEnvironment || "production");
2884
+ const Square = window.Square;
2885
+ const payments = Square.payments(config.squareAppId, config.squareLocationId);
2886
+ const card = await payments.card({
2887
+ style: {
2888
+ ".input-container": {
2889
+ borderColor: "#d1d5db",
2890
+ borderRadius: "6px"
2891
+ },
2892
+ ".input-container.is-focus": {
2893
+ borderColor: "#2563eb"
2894
+ },
2895
+ ".input-container.is-error": {
2896
+ borderColor: "#dc2626"
2897
+ }
2898
+ }
2899
+ });
2900
+ await card.attach("#sq-card-container");
2901
+ setSquareCard(card);
2902
+ setCardReady(true);
2903
+ } catch (err) {
2904
+ console.error("[Commerce] Square card init failed:", err);
2905
+ }
2906
+ }
2907
+ });
2908
+ return () => {
2909
+ setSquareCard((prev) => {
2910
+ if (prev) {
2911
+ prev.destroy?.().catch(() => {
2912
+ });
2913
+ }
2914
+ return null;
2915
+ });
2916
+ setCardReady(false);
2917
+ setProcessorConfig(null);
2918
+ };
2919
+ }, [isOpen]);
2838
2920
  React5.useEffect(() => {
2839
2921
  if (isOpen && event) {
2840
2922
  setError(null);
@@ -2895,17 +2977,34 @@ function EventModal({
2895
2977
  onError?.(result.error || "Registration failed");
2896
2978
  }
2897
2979
  } else {
2898
- const result = await createCheckoutSession(event.id, {
2980
+ let sourceId;
2981
+ if (squareCard && cardReady) {
2982
+ const tokenResult = await squareCard.tokenize();
2983
+ if (tokenResult.status !== "OK") {
2984
+ const msg = tokenResult.errors?.[0]?.message || "Card verification failed. Please check your card details.";
2985
+ setError(msg);
2986
+ onError?.(msg);
2987
+ setLoading(false);
2988
+ return;
2989
+ }
2990
+ sourceId = tokenResult.token;
2991
+ }
2992
+ const result = await createCheckoutSession({
2993
+ offeringId: event.id,
2899
2994
  scheduleId: schedule.id,
2900
2995
  quantity,
2901
2996
  customer: {
2902
2997
  ...customer,
2903
2998
  ...additionalData
2904
2999
  },
3000
+ sourceId,
2905
3001
  successUrl: window.location.href + "?registration=success",
2906
3002
  cancelUrl: window.location.href
2907
3003
  });
2908
- if (result.success && result.payment_url) {
3004
+ if (result.success && !result.payment_url) {
3005
+ setSuccess(true);
3006
+ onSuccess?.(result);
3007
+ } else if (result.success && result.payment_url) {
2909
3008
  window.location.href = result.payment_url;
2910
3009
  } else {
2911
3010
  setError(result.error || "Checkout failed");
@@ -3229,6 +3328,30 @@ function EventModal({
3229
3328
  )
3230
3329
  ] }, field.name))
3231
3330
  ] }),
3331
+ !isFree && processor === "square" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem" }, children: [
3332
+ /* @__PURE__ */ jsxRuntime.jsx("label", { style: {
3333
+ display: "block",
3334
+ fontSize: "0.875rem",
3335
+ fontWeight: 500,
3336
+ color: "#374151",
3337
+ marginBottom: "0.375rem"
3338
+ }, children: "Card Details *" }),
3339
+ /* @__PURE__ */ jsxRuntime.jsx(
3340
+ "div",
3341
+ {
3342
+ id: "sq-card-container",
3343
+ ref: cardContainerRef,
3344
+ style: {
3345
+ minHeight: "42px",
3346
+ border: "1px solid #d1d5db",
3347
+ borderRadius: "6px",
3348
+ padding: "0.5rem 0.75rem",
3349
+ background: "#fff"
3350
+ }
3351
+ }
3352
+ ),
3353
+ !cardReady && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.75rem", color: "#9ca3af", marginTop: "0.25rem" }, children: "Loading card form..." })
3354
+ ] }),
3232
3355
  error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
3233
3356
  marginTop: "1rem",
3234
3357
  padding: "0.75rem",
@@ -3242,7 +3365,7 @@ function EventModal({
3242
3365
  "button",
3243
3366
  {
3244
3367
  type: "submit",
3245
- disabled: loading,
3368
+ disabled: loading || !isFree && processor === "square" && !cardReady,
3246
3369
  style: {
3247
3370
  width: "100%",
3248
3371
  marginTop: "1.25rem",
@@ -3251,19 +3374,26 @@ function EventModal({
3251
3374
  fontWeight: 600,
3252
3375
  borderRadius: "8px",
3253
3376
  border: "none",
3254
- background: loading ? "#93c5fd" : "#2563eb",
3377
+ background: loading || !isFree && processor === "square" && !cardReady ? "#93c5fd" : "#2563eb",
3255
3378
  color: "white",
3256
- cursor: loading ? "not-allowed" : "pointer"
3379
+ cursor: loading || !isFree && processor === "square" && !cardReady ? "not-allowed" : "pointer"
3257
3380
  },
3258
3381
  children: loading ? "Processing..." : isFree ? "Register Free" : `Pay ${formatPrice(total, event.currency)}`
3259
3382
  }
3260
3383
  ),
3261
- !isFree && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
3384
+ !isFree && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: {
3262
3385
  textAlign: "center",
3263
3386
  fontSize: "0.75rem",
3264
3387
  color: "#666",
3265
3388
  margin: "0.75rem 0 0"
3266
- }, children: "\u{1F512} Secure checkout via Stripe" })
3389
+ }, children: [
3390
+ "\u{1F512} Secure checkout via ",
3391
+ processor === "square" ? "Square" : processor === "stripe" ? "Stripe" : "secure payment"
3392
+ ] }),
3393
+ !isFree && processor && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.625rem", color: "#999", margin: "0.25rem 0 0", textAlign: "center" }, children: [
3394
+ "Powered by ",
3395
+ processor === "stripe" ? "Stripe" : "Square"
3396
+ ] })
3267
3397
  ] })
3268
3398
  ] }) })
3269
3399
  ]
@@ -3922,6 +4052,7 @@ exports.fetchLatestOffering = fetchLatestOffering;
3922
4052
  exports.fetchNextEvent = fetchNextEvent;
3923
4053
  exports.fetchOffering = fetchOffering;
3924
4054
  exports.fetchOfferings = fetchOfferings;
4055
+ exports.fetchProcessorConfig = fetchProcessorConfig;
3925
4056
  exports.fetchProductBySlug = fetchProductBySlug;
3926
4057
  exports.fetchProducts = fetchProducts;
3927
4058
  exports.fetchProductsPublic = fetchProductsPublic;
@@ -3938,5 +4069,5 @@ exports.getSpotsRemaining = getSpotsRemaining;
3938
4069
  exports.isEventSoldOut = isEventSoldOut;
3939
4070
  exports.registerForEvent = registerForEvent;
3940
4071
  exports.useEventModal = useEventModal;
3941
- //# sourceMappingURL=chunk-7BEMFSF6.js.map
3942
- //# sourceMappingURL=chunk-7BEMFSF6.js.map
4072
+ //# sourceMappingURL=chunk-WTMMXY7S.js.map
4073
+ //# sourceMappingURL=chunk-WTMMXY7S.js.map