@ecomiq/storefront 1.1.1 → 1.1.2

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,11 +1,12 @@
1
1
  "use client";
2
2
  import { z } from 'zod';
3
3
  import { QueryClient, hydrate, QueryClientProvider, useMutation, useQuery, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
4
- import React2, { createContext, useRef, useEffect, useContext, useState, useMemo, useCallback } from 'react';
4
+ import React2, { createContext, forwardRef, useRef, useState, useCallback, useMemo, useImperativeHandle, useEffect, useContext } from 'react';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  import { toast } from 'sonner';
7
7
  import { create } from 'zustand';
8
8
  import { persist } from 'zustand/middleware';
9
+ import { useShallow } from 'zustand/shallow';
9
10
 
10
11
  // src/core/client/store-api-errors.ts
11
12
  function isCartNotActiveApiError(error) {
@@ -57,7 +58,10 @@ var StoreApiClient = class {
57
58
  const pathNorm = path.replace(/^\/+/, "");
58
59
  const url = path.startsWith("http") ? path : `${this.baseUrl}/${pathNorm}`;
59
60
  const headers = new Headers(init.headers ?? {});
60
- headers.set("Content-Type", "application/json");
61
+ const isFormData = typeof FormData !== "undefined" && init.body instanceof FormData;
62
+ if (!isFormData) {
63
+ headers.set("Content-Type", "application/json");
64
+ }
61
65
  headers.set("Accept-Encoding", "identity");
62
66
  const explicitStoreId = options?.xStoreId?.trim();
63
67
  const runtimeStoreId = explicitStoreId || (typeof window === "undefined" ? serverStoreIdGetter : clientStoreIdGetter);
@@ -121,6 +125,10 @@ var StoreApiClient = class {
121
125
  options
122
126
  );
123
127
  }
128
+ /** POST multipart (no fuerza `Content-Type`; el runtime añade el boundary). */
129
+ postForm(path, form, options) {
130
+ return this.request(path, { method: "POST", body: form }, options);
131
+ }
124
132
  patch(path, data, options) {
125
133
  return this.request(path, {
126
134
  method: "PATCH",
@@ -475,6 +483,9 @@ var CartItemRequestSchema = z.object({
475
483
  quantity: z.number().int().positive(),
476
484
  modifiers: z.array(CartItemModifierRequestSchema).optional()
477
485
  });
486
+ var CartItemUpdateRequestSchema = z.object({
487
+ quantity: z.number().int().positive()
488
+ });
478
489
  var CartCouponRequestSchema = z.object({
479
490
  code: z.string().min(1)
480
491
  });
@@ -544,6 +555,8 @@ var CartResponseSchema = z.object({
544
555
  firstName: z.string().nullable().optional(),
545
556
  lastName: z.string().nullable().optional(),
546
557
  currencyCode: z.string(),
558
+ /** Estado del carrito en backend (`inProgress`, `completed`, etc.). */
559
+ status: z.string().nullable().optional(),
547
560
  completedAt: z.string().nullable().optional(),
548
561
  shippingAddress: z.unknown().nullable().optional(),
549
562
  billingAddress: z.unknown().nullable().optional(),
@@ -702,6 +715,26 @@ async function addCartItem(data, cartId) {
702
715
  });
703
716
  return CartResponseSchema.parse(response);
704
717
  }
718
+ async function updateCartItem(cartId, itemId, data) {
719
+ if (!cartId) throw new Error("cartId is required");
720
+ if (!itemId.trim()) throw new Error("itemId is required");
721
+ const payload = CartItemUpdateRequestSchema.parse(data);
722
+ const client = await getStoreApiClient();
723
+ const response = await client.patch(
724
+ `carts/${cartId}/items/${encodeURIComponent(itemId.trim())}`,
725
+ payload
726
+ );
727
+ return CartResponseSchema.parse(response);
728
+ }
729
+ async function deleteCartItem(cartId, itemId) {
730
+ if (!cartId) throw new Error("cartId is required");
731
+ if (!itemId.trim()) throw new Error("itemId is required");
732
+ const client = await getStoreApiClient();
733
+ const response = await client.delete(
734
+ `carts/${cartId}/items/${encodeURIComponent(itemId.trim())}`
735
+ );
736
+ return CartResponseSchema.parse(response);
737
+ }
705
738
  async function patchCartBuyer(data, cartId) {
706
739
  if (!cartId) throw new Error("cartId is required");
707
740
  const payload = CartBuyerRequestSchema.parse(data);
@@ -753,32 +786,15 @@ async function checkoutCart(data, cartId) {
753
786
  }
754
787
  async function uploadPaymentReceipt(cartId, file) {
755
788
  if (!cartId) throw new Error("cartId is required");
756
- const baseUrl = await getStoreApiBaseUrl();
789
+ const client = await getStoreApiClient();
757
790
  const form = new FormData();
758
791
  form.set("file", file);
759
- const response = await fetch(
760
- `${baseUrl.replace(/\/$/, "")}/carts/${encodeURIComponent(cartId)}/payment-receipt`,
761
- {
762
- method: "POST",
763
- body: form,
764
- ...typeof window === "undefined" && { cache: "no-store" }
765
- }
792
+ const response = await client.postForm(
793
+ `carts/${cartId}/payment-receipt`,
794
+ form,
795
+ typeof window === "undefined" ? { noStore: true } : void 0
766
796
  );
767
- if (!response.ok) {
768
- let body;
769
- try {
770
- const errorText = await response.text();
771
- body = errorText ? JSON.parse(errorText) : void 0;
772
- } catch {
773
- body = void 0;
774
- }
775
- const message = typeof body === "object" && body !== null && "title" in body && typeof body.title === "string" ? body.title : response.statusText || "Store API error";
776
- const error = new Error(message);
777
- error.status = response.status;
778
- error.body = body;
779
- throw error;
780
- }
781
- return CartPaymentReceiptResponseSchema.parse(await response.json());
797
+ return CartPaymentReceiptResponseSchema.parse(response);
782
798
  }
783
799
  async function getCartCheckout(cartId) {
784
800
  if (!cartId) throw new Error("cartId is required");
@@ -1366,6 +1382,7 @@ function useStorePages() {
1366
1382
  useRefreshStorefrontPages
1367
1383
  };
1368
1384
  }
1385
+ var CART_PERSIST_KEY = "cart-storage";
1369
1386
  var useCart = create()(
1370
1387
  persist(
1371
1388
  (set) => ({
@@ -1421,6 +1438,14 @@ var useCart = create()(
1421
1438
  const count = Math.max(0, cart.reduce((sum, i) => sum + Math.max(0, i.quantity), 0));
1422
1439
  return { count, cart };
1423
1440
  }),
1441
+ replaceCartItems: (items) => set(() => {
1442
+ const cart = items.map((item) => ({
1443
+ ...item,
1444
+ quantity: Math.max(0, item.quantity)
1445
+ }));
1446
+ const count = cart.reduce((sum, i) => sum + Math.max(0, i.quantity), 0);
1447
+ return { count, cart };
1448
+ }),
1424
1449
  clearCartSession: () => set(() => ({
1425
1450
  count: 0,
1426
1451
  cart: [],
@@ -1429,9 +1454,15 @@ var useCart = create()(
1429
1454
  checkoutCustomerLocal: null
1430
1455
  }))
1431
1456
  }),
1432
- { name: "cart-storage" }
1457
+ { name: CART_PERSIST_KEY }
1433
1458
  )
1434
1459
  );
1460
+ if (typeof window !== "undefined") {
1461
+ window.addEventListener("storage", (event) => {
1462
+ if (event.key !== CART_PERSIST_KEY) return;
1463
+ void useCart.persist.rehydrate();
1464
+ });
1465
+ }
1435
1466
 
1436
1467
  // src/react/shell/hooks/use-store-cart.ts
1437
1468
  function useStoreCart() {
@@ -1460,6 +1491,12 @@ function useStoreCart() {
1460
1491
  const useAddCartItem = () => useMutation({
1461
1492
  mutationFn: ({ cartId, ...data }) => addCartItem(data, cartId)
1462
1493
  });
1494
+ const useUpdateCartItem = () => useMutation({
1495
+ mutationFn: ({ cartId, itemId, data }) => updateCartItem(cartId, itemId, data)
1496
+ });
1497
+ const useDeleteCartItem = () => useMutation({
1498
+ mutationFn: ({ cartId, itemId }) => deleteCartItem(cartId, itemId)
1499
+ });
1463
1500
  const useCheckoutCart = () => useMutation({
1464
1501
  mutationFn: ({ data, cartId }) => checkoutCart(data, cartId)
1465
1502
  });
@@ -1544,6 +1581,8 @@ function useStoreCart() {
1544
1581
  useUpdateCartBuyer,
1545
1582
  useUpdateCartAddresses,
1546
1583
  useAddCartItem,
1584
+ useUpdateCartItem,
1585
+ useDeleteCartItem,
1547
1586
  useCheckoutCart,
1548
1587
  useUploadPaymentReceipt,
1549
1588
  useGetCartPaymentMethods,
@@ -1913,6 +1952,2814 @@ function formatCurrency(amount, currency = "USD") {
1913
1952
  currency
1914
1953
  }).format(amount);
1915
1954
  }
1955
+ var CHECKOUT_FIELD_FOCUS_ORDER = [
1956
+ "email",
1957
+ "firstName",
1958
+ "lastName",
1959
+ "countryCode",
1960
+ "address",
1961
+ "department",
1962
+ "province-geo",
1963
+ "district",
1964
+ "city",
1965
+ "province-region",
1966
+ "phone",
1967
+ "checkout-shipping-method",
1968
+ "checkout-payment-method"
1969
+ ];
1970
+ var zodPathToFieldId = {
1971
+ email: "email",
1972
+ firstName: "firstName",
1973
+ lastName: "lastName",
1974
+ countryCode: "countryCode",
1975
+ address: "address",
1976
+ phone: "phone",
1977
+ departmentCode: "department",
1978
+ provinceCode: "province-geo",
1979
+ districtCode: "district",
1980
+ city: "city",
1981
+ province: "province-region",
1982
+ selectedShippingKey: "checkout-shipping-method",
1983
+ selectedPaymentCode: "checkout-payment-method"
1984
+ };
1985
+ function buildCheckoutFormValidationSchema(currency) {
1986
+ const phoneDigits = currency === "PEN" ? 9 : 10;
1987
+ return z.object({
1988
+ email: z.string().trim().min(1, "El email es requerido").email("Ingresa un email v\xE1lido"),
1989
+ firstName: z.string().trim().min(1, "El nombre es requerido").min(2, "El nombre debe tener al menos 2 caracteres"),
1990
+ lastName: z.string().trim().min(1, "El apellido es requerido").min(2, "El apellido debe tener al menos 2 caracteres"),
1991
+ countryCode: z.string().trim().min(2, "Selecciona un pa\xEDs"),
1992
+ address: z.string().trim().min(1, "La direcci\xF3n es requerida").min(5, "La direcci\xF3n debe tener al menos 5 caracteres"),
1993
+ phone: z.string().trim().min(1, "El tel\xE9fono es requerido").regex(/^\d+$/, "El tel\xE9fono solo debe contener n\xFAmeros").length(
1994
+ phoneDigits,
1995
+ `El tel\xE9fono debe tener ${phoneDigits} d\xEDgitos`
1996
+ ),
1997
+ departmentCode: z.string(),
1998
+ provinceCode: z.string(),
1999
+ districtCode: z.string(),
2000
+ city: z.string(),
2001
+ province: z.string(),
2002
+ selectedShippingKey: z.string().nullable(),
2003
+ shippingOptionsCount: z.number().int().nonnegative(),
2004
+ selectedPaymentCode: z.string().nullable(),
2005
+ paymentMethodsCount: z.number().int().nonnegative()
2006
+ }).superRefine((data, ctx) => {
2007
+ const country = data.countryCode.toUpperCase();
2008
+ if (country === "PE") {
2009
+ if (!data.departmentCode.trim()) {
2010
+ ctx.addIssue({
2011
+ code: z.ZodIssueCode.custom,
2012
+ path: ["departmentCode"],
2013
+ message: "Selecciona un departamento"
2014
+ });
2015
+ }
2016
+ if (!data.provinceCode.trim()) {
2017
+ ctx.addIssue({
2018
+ code: z.ZodIssueCode.custom,
2019
+ path: ["provinceCode"],
2020
+ message: "Selecciona una provincia"
2021
+ });
2022
+ }
2023
+ if (!data.districtCode.trim()) {
2024
+ ctx.addIssue({
2025
+ code: z.ZodIssueCode.custom,
2026
+ path: ["districtCode"],
2027
+ message: "Selecciona un distrito"
2028
+ });
2029
+ }
2030
+ } else {
2031
+ if (!data.city.trim()) {
2032
+ ctx.addIssue({
2033
+ code: z.ZodIssueCode.custom,
2034
+ path: ["city"],
2035
+ message: "La ciudad es requerida"
2036
+ });
2037
+ }
2038
+ if (!data.province.trim()) {
2039
+ ctx.addIssue({
2040
+ code: z.ZodIssueCode.custom,
2041
+ path: ["province"],
2042
+ message: "La regi\xF3n es requerida"
2043
+ });
2044
+ }
2045
+ }
2046
+ if (data.shippingOptionsCount > 0 && !data.selectedShippingKey?.trim()) {
2047
+ ctx.addIssue({
2048
+ code: z.ZodIssueCode.custom,
2049
+ path: ["selectedShippingKey"],
2050
+ message: "Selecciona un m\xE9todo de env\xEDo"
2051
+ });
2052
+ }
2053
+ if (data.paymentMethodsCount > 0 && !data.selectedPaymentCode?.trim()) {
2054
+ ctx.addIssue({
2055
+ code: z.ZodIssueCode.custom,
2056
+ path: ["selectedPaymentCode"],
2057
+ message: "Selecciona un m\xE9todo de pago"
2058
+ });
2059
+ }
2060
+ });
2061
+ }
2062
+ function checkoutValidationInputFromContext(ctx) {
2063
+ const { contact } = ctx;
2064
+ return {
2065
+ email: contact.email,
2066
+ firstName: contact.firstName,
2067
+ lastName: contact.lastName,
2068
+ countryCode: contact.countryCode,
2069
+ address: contact.address,
2070
+ phone: contact.phone,
2071
+ departmentCode: contact.departmentCode,
2072
+ provinceCode: contact.provinceCode,
2073
+ districtCode: contact.districtCode,
2074
+ city: contact.city,
2075
+ province: contact.province,
2076
+ selectedShippingKey: ctx.selectedShippingKey,
2077
+ shippingOptionsCount: ctx.shippingOptionsCount,
2078
+ selectedPaymentCode: ctx.selectedPaymentCode,
2079
+ paymentMethodsCount: ctx.paymentMethodsCount
2080
+ };
2081
+ }
2082
+ function mapZodIssuesToFieldErrors(error) {
2083
+ const out = {};
2084
+ for (const issue of error.issues) {
2085
+ const key = issue.path[0];
2086
+ if (typeof key !== "string") continue;
2087
+ const fieldId = zodPathToFieldId[key];
2088
+ if (!fieldId || out[fieldId]) continue;
2089
+ out[fieldId] = issue.message;
2090
+ }
2091
+ return out;
2092
+ }
2093
+ function firstInvalidFieldId(errors) {
2094
+ for (const id of CHECKOUT_FIELD_FOCUS_ORDER) {
2095
+ if (errors[id]) return id;
2096
+ }
2097
+ return null;
2098
+ }
2099
+ function focusCheckoutField(fieldId) {
2100
+ if (typeof document === "undefined") return;
2101
+ const el = document.getElementById(fieldId);
2102
+ if (el) {
2103
+ el.focus({ preventScroll: false });
2104
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
2105
+ return;
2106
+ }
2107
+ if (fieldId === "checkout-shipping-method") {
2108
+ const radio = document.querySelector(
2109
+ 'input[name="shipping"]'
2110
+ );
2111
+ radio?.focus();
2112
+ radio?.scrollIntoView({ behavior: "smooth", block: "center" });
2113
+ return;
2114
+ }
2115
+ if (fieldId === "checkout-payment-method") {
2116
+ const radio = document.querySelector(
2117
+ 'input[name="payment"]'
2118
+ );
2119
+ radio?.focus();
2120
+ radio?.scrollIntoView({ behavior: "smooth", block: "center" });
2121
+ }
2122
+ }
2123
+
2124
+ // src/react/pages/checkout-page/hooks/use-checkout-form-validation.ts
2125
+ function useCheckoutFormValidation(currency = "PEN") {
2126
+ const schema = useMemo(
2127
+ () => buildCheckoutFormValidationSchema(currency),
2128
+ [currency]
2129
+ );
2130
+ const [fieldErrors, setFieldErrors] = useState({});
2131
+ const [validationError, setValidationError] = useState(null);
2132
+ const clearFieldError = useCallback((fieldId) => {
2133
+ setFieldErrors((prev) => {
2134
+ if (!prev[fieldId]) return prev;
2135
+ const next = { ...prev };
2136
+ delete next[fieldId];
2137
+ return next;
2138
+ });
2139
+ setValidationError(null);
2140
+ }, []);
2141
+ const getFieldError = useCallback(
2142
+ (fieldId) => fieldErrors[fieldId],
2143
+ [fieldErrors]
2144
+ );
2145
+ const validateCheckoutForm = useCallback(
2146
+ (context) => {
2147
+ const result = schema.safeParse(
2148
+ checkoutValidationInputFromContext(context)
2149
+ );
2150
+ if (result.success) {
2151
+ setFieldErrors({});
2152
+ setValidationError(null);
2153
+ return true;
2154
+ }
2155
+ const errors = mapZodIssuesToFieldErrors(result.error);
2156
+ setFieldErrors(errors);
2157
+ const firstId = firstInvalidFieldId(errors);
2158
+ if (firstId) {
2159
+ focusCheckoutField(firstId);
2160
+ setValidationError(errors[firstId] ?? null);
2161
+ } else {
2162
+ setValidationError("Completa los campos requeridos.");
2163
+ }
2164
+ return false;
2165
+ },
2166
+ [schema]
2167
+ );
2168
+ return {
2169
+ fieldErrors,
2170
+ validationError,
2171
+ setValidationError,
2172
+ validateCheckoutForm,
2173
+ clearFieldError,
2174
+ getFieldError
2175
+ };
2176
+ }
2177
+
2178
+ // src/core/lib/storefront-geo-inei.ts
2179
+ function toGeoItems(data) {
2180
+ if (!Array.isArray(data)) return [];
2181
+ return data.map((raw) => {
2182
+ if (!raw || typeof raw !== "object") return null;
2183
+ const item = raw;
2184
+ return {
2185
+ code: String(item.code ?? ""),
2186
+ name: String(item.name ?? "")
2187
+ };
2188
+ }).filter((x) => !!x && !!x.code && !!x.name);
2189
+ }
2190
+ var departmentsCache = null;
2191
+ var departmentsRequest = null;
2192
+ function loadStorefrontGeoDepartments(headers) {
2193
+ if (departmentsCache) return Promise.resolve(departmentsCache);
2194
+ if (departmentsRequest) return departmentsRequest;
2195
+ departmentsRequest = fetch(
2196
+ `/api/store/geo/departments?countryCode=PE&source=inei&limit=200`,
2197
+ { cache: "no-store", headers }
2198
+ ).then((r) => r.json()).then((data) => {
2199
+ const items = toGeoItems(data);
2200
+ departmentsCache = items;
2201
+ return items;
2202
+ }).catch(() => {
2203
+ departmentsCache = [];
2204
+ return [];
2205
+ }).finally(() => {
2206
+ departmentsRequest = null;
2207
+ });
2208
+ return departmentsRequest;
2209
+ }
2210
+ async function fetchStorefrontGeoProvinces(headers, countryCode, departmentCode) {
2211
+ const res = await fetch(
2212
+ `/api/store/geo/provinces?countryCode=${encodeURIComponent(
2213
+ countryCode
2214
+ )}&departmentCode=${encodeURIComponent(departmentCode)}&source=inei&limit=200`,
2215
+ { headers }
2216
+ );
2217
+ const data = await res.json();
2218
+ return toGeoItems(data);
2219
+ }
2220
+ async function fetchStorefrontGeoDistricts(headers, countryCode, provinceCode) {
2221
+ const res = await fetch(
2222
+ `/api/store/geo/districts?countryCode=${encodeURIComponent(
2223
+ countryCode
2224
+ )}&provinceCode=${encodeURIComponent(provinceCode)}&source=inei`,
2225
+ { headers }
2226
+ );
2227
+ const data = await res.json();
2228
+ return toGeoItems(data);
2229
+ }
2230
+ async function resolveIneiCodesFromLabels(storeId, labels, countryCode = "PE") {
2231
+ const id = storeId.trim();
2232
+ if (!id) return null;
2233
+ const headers = { "X-Store-Id": id };
2234
+ const departments = await loadStorefrontGeoDepartments(headers);
2235
+ const dept = departments.find((d) => d.name.trim() === labels.department.trim());
2236
+ if (!dept) return null;
2237
+ const provinces = await fetchStorefrontGeoProvinces(headers, countryCode, dept.code);
2238
+ const prov = provinces.find((p) => p.name.trim() === labels.province.trim());
2239
+ if (!prov) {
2240
+ return { departmentCode: dept.code, provinceCode: "", districtCode: "" };
2241
+ }
2242
+ const districts = await fetchStorefrontGeoDistricts(headers, countryCode, prov.code);
2243
+ const dist = districts.find((d) => d.name.trim() === labels.district.trim());
2244
+ return {
2245
+ departmentCode: dept.code,
2246
+ provinceCode: prov.code,
2247
+ districtCode: dist?.code ?? ""
2248
+ };
2249
+ }
2250
+
2251
+ // src/react/pages/checkout-page/hooks/use-checkout-delivery-form.ts
2252
+ function useCheckoutDeliveryForm({
2253
+ storeId,
2254
+ contact,
2255
+ onContactChange
2256
+ }) {
2257
+ const [departments, setDepartments] = useState([]);
2258
+ const [provinces, setProvinces] = useState([]);
2259
+ const [districts, setDistricts] = useState([]);
2260
+ const [loadingDepartments, setLoadingDepartments] = useState(false);
2261
+ const [loadingProvinces, setLoadingProvinces] = useState(false);
2262
+ const [loadingDistricts, setLoadingDistricts] = useState(false);
2263
+ const prevDepartmentCode = useRef(void 0);
2264
+ const prevProvinceCode = useRef(void 0);
2265
+ const resolvedLabelsRef = useRef(false);
2266
+ const onChangeRef = useRef(onContactChange);
2267
+ onChangeRef.current = onContactChange;
2268
+ const patchContact = useCallback((patch) => {
2269
+ onChangeRef.current(patch);
2270
+ }, []);
2271
+ const countryCode = (contact.countryCode || "PE").toUpperCase();
2272
+ const isPeru = countryCode === "PE";
2273
+ const storeRequestHeaders = useMemo(() => {
2274
+ const id = storeId.trim();
2275
+ if (!id) return null;
2276
+ return { "X-Store-Id": id };
2277
+ }, [storeId]);
2278
+ useEffect(() => {
2279
+ if (!isPeru || !storeRequestHeaders) {
2280
+ setDepartments([]);
2281
+ setLoadingDepartments(false);
2282
+ return;
2283
+ }
2284
+ let active = true;
2285
+ setLoadingDepartments(true);
2286
+ loadStorefrontGeoDepartments(storeRequestHeaders).then((items) => {
2287
+ if (active) setDepartments(items);
2288
+ }).finally(() => {
2289
+ if (active) setLoadingDepartments(false);
2290
+ });
2291
+ return () => {
2292
+ active = false;
2293
+ };
2294
+ }, [isPeru, storeRequestHeaders]);
2295
+ useEffect(() => {
2296
+ if (!isPeru || !storeId.trim()) return;
2297
+ if (contact.departmentCode) return;
2298
+ if (resolvedLabelsRef.current) return;
2299
+ if (!contact.departmentName.trim()) return;
2300
+ if (!contact.province && !contact.city) return;
2301
+ resolvedLabelsRef.current = true;
2302
+ let cancelled = false;
2303
+ void resolveIneiCodesFromLabels(storeId, {
2304
+ department: contact.departmentName,
2305
+ province: contact.province,
2306
+ district: contact.city
2307
+ }).then((codes) => {
2308
+ if (cancelled || !codes) return;
2309
+ patchContact({
2310
+ departmentCode: codes.departmentCode,
2311
+ provinceCode: codes.provinceCode,
2312
+ districtCode: codes.districtCode
2313
+ });
2314
+ });
2315
+ return () => {
2316
+ cancelled = true;
2317
+ };
2318
+ }, [
2319
+ contact.city,
2320
+ contact.departmentCode,
2321
+ contact.departmentName,
2322
+ contact.province,
2323
+ isPeru,
2324
+ patchContact,
2325
+ storeId
2326
+ ]);
2327
+ useEffect(() => {
2328
+ const dept = contact.departmentCode;
2329
+ const prev = prevDepartmentCode.current;
2330
+ const departmentChanged = prev !== void 0 && prev !== dept;
2331
+ prevDepartmentCode.current = dept;
2332
+ if (!isPeru || !storeRequestHeaders) {
2333
+ setProvinces([]);
2334
+ if (!dept) {
2335
+ setDistricts([]);
2336
+ prevProvinceCode.current = "";
2337
+ }
2338
+ return;
2339
+ }
2340
+ if (!dept) {
2341
+ setProvinces([]);
2342
+ setDistricts([]);
2343
+ prevProvinceCode.current = "";
2344
+ return;
2345
+ }
2346
+ if (departmentChanged) {
2347
+ patchContact({
2348
+ provinceCode: "",
2349
+ provinceName: "",
2350
+ districtCode: "",
2351
+ districtName: "",
2352
+ province: "",
2353
+ city: "",
2354
+ postalCode: ""
2355
+ });
2356
+ setDistricts([]);
2357
+ prevProvinceCode.current = "";
2358
+ }
2359
+ const deptName = departments.find((d) => d.code === dept)?.name ?? "";
2360
+ if (deptName && deptName !== contact.departmentName) {
2361
+ patchContact({ departmentName: deptName });
2362
+ }
2363
+ let active = true;
2364
+ setLoadingProvinces(true);
2365
+ fetchStorefrontGeoProvinces(storeRequestHeaders, countryCode, dept).then((items) => {
2366
+ if (active) setProvinces(items);
2367
+ }).catch(() => {
2368
+ if (active) setProvinces([]);
2369
+ }).finally(() => {
2370
+ if (active) setLoadingProvinces(false);
2371
+ });
2372
+ return () => {
2373
+ active = false;
2374
+ };
2375
+ }, [
2376
+ contact.departmentCode,
2377
+ contact.departmentName,
2378
+ countryCode,
2379
+ departments,
2380
+ isPeru,
2381
+ patchContact,
2382
+ storeRequestHeaders
2383
+ ]);
2384
+ useEffect(() => {
2385
+ const prov = contact.provinceCode;
2386
+ const prev = prevProvinceCode.current;
2387
+ const provinceChanged = prev !== void 0 && prev !== prov;
2388
+ prevProvinceCode.current = prov;
2389
+ if (!isPeru || !storeRequestHeaders) {
2390
+ setDistricts([]);
2391
+ return;
2392
+ }
2393
+ if (!prov) {
2394
+ setDistricts([]);
2395
+ prevProvinceCode.current = "";
2396
+ return;
2397
+ }
2398
+ if (provinceChanged) {
2399
+ patchContact({
2400
+ districtCode: "",
2401
+ districtName: "",
2402
+ city: "",
2403
+ postalCode: ""
2404
+ });
2405
+ }
2406
+ const provName = provinces.find((p) => p.code === prov)?.name ?? "";
2407
+ if (provName && provName !== contact.provinceName) {
2408
+ patchContact({ provinceName: provName, province: provName });
2409
+ }
2410
+ let active = true;
2411
+ setLoadingDistricts(true);
2412
+ fetchStorefrontGeoDistricts(storeRequestHeaders, countryCode, prov).then((items) => {
2413
+ if (active) setDistricts(items);
2414
+ }).catch(() => {
2415
+ if (active) setDistricts([]);
2416
+ }).finally(() => {
2417
+ if (active) setLoadingDistricts(false);
2418
+ });
2419
+ return () => {
2420
+ active = false;
2421
+ };
2422
+ }, [
2423
+ contact.provinceCode,
2424
+ contact.provinceName,
2425
+ countryCode,
2426
+ isPeru,
2427
+ patchContact,
2428
+ provinces,
2429
+ storeRequestHeaders
2430
+ ]);
2431
+ useEffect(() => {
2432
+ if (!contact.districtCode) return;
2433
+ const distName = districts.find((d) => d.code === contact.districtCode)?.name ?? "";
2434
+ const patch = {};
2435
+ if (distName && distName !== contact.districtName) {
2436
+ patch.districtName = distName;
2437
+ patch.city = distName;
2438
+ }
2439
+ if (contact.postalCode !== contact.districtCode) {
2440
+ patch.postalCode = contact.districtCode;
2441
+ }
2442
+ if (Object.keys(patch).length > 0) patchContact(patch);
2443
+ }, [
2444
+ contact.districtCode,
2445
+ contact.districtName,
2446
+ contact.postalCode,
2447
+ districts,
2448
+ patchContact
2449
+ ]);
2450
+ const handleDepartmentChange = useCallback(
2451
+ (code) => {
2452
+ const name = departments.find((d) => d.code === code)?.name ?? "";
2453
+ prevDepartmentCode.current = code;
2454
+ prevProvinceCode.current = "";
2455
+ patchContact({
2456
+ departmentCode: code,
2457
+ departmentName: name,
2458
+ provinceCode: "",
2459
+ provinceName: "",
2460
+ districtCode: "",
2461
+ districtName: "",
2462
+ province: "",
2463
+ city: "",
2464
+ postalCode: ""
2465
+ });
2466
+ },
2467
+ [departments, patchContact]
2468
+ );
2469
+ const handleProvinceChange = useCallback(
2470
+ (code) => {
2471
+ const name = provinces.find((p) => p.code === code)?.name ?? "";
2472
+ prevProvinceCode.current = code;
2473
+ patchContact({
2474
+ provinceCode: code,
2475
+ provinceName: name,
2476
+ province: name,
2477
+ districtCode: "",
2478
+ districtName: "",
2479
+ city: "",
2480
+ postalCode: ""
2481
+ });
2482
+ },
2483
+ [patchContact, provinces]
2484
+ );
2485
+ const handleDistrictChange = useCallback(
2486
+ (code) => {
2487
+ const name = districts.find((d) => d.code === code)?.name ?? "";
2488
+ patchContact({
2489
+ districtCode: code,
2490
+ districtName: name,
2491
+ city: name,
2492
+ postalCode: code
2493
+ });
2494
+ },
2495
+ [districts, patchContact]
2496
+ );
2497
+ return {
2498
+ isPeru,
2499
+ departments,
2500
+ provinces,
2501
+ districts,
2502
+ loadingDepartments,
2503
+ loadingProvinces,
2504
+ loadingDistricts,
2505
+ handleDepartmentChange,
2506
+ handleProvinceChange,
2507
+ handleDistrictChange
2508
+ };
2509
+ }
2510
+ function CheckoutTextField({
2511
+ id,
2512
+ label,
2513
+ value,
2514
+ onChange,
2515
+ onClearError,
2516
+ error,
2517
+ type = "text",
2518
+ optional,
2519
+ half
2520
+ }) {
2521
+ return /* @__PURE__ */ jsxs(
2522
+ "label",
2523
+ {
2524
+ className: `ecomiq-checkout-page__field${half ? " ecomiq-checkout-page__field--half" : ""}`,
2525
+ children: [
2526
+ /* @__PURE__ */ jsxs("span", { className: "ecomiq-checkout-page__label", children: [
2527
+ label,
2528
+ optional ? " (optional)" : ""
2529
+ ] }),
2530
+ /* @__PURE__ */ jsx(
2531
+ "input",
2532
+ {
2533
+ id,
2534
+ type,
2535
+ className: `ecomiq-checkout-page__input${error ? " ecomiq-checkout-page__input--error" : ""}`,
2536
+ value,
2537
+ "aria-invalid": error ? true : void 0,
2538
+ "aria-describedby": error ? `${id}-error` : void 0,
2539
+ onChange: (e) => {
2540
+ onClearError?.();
2541
+ onChange(e.target.value);
2542
+ }
2543
+ }
2544
+ ),
2545
+ error ? /* @__PURE__ */ jsx("span", { id: `${id}-error`, className: "ecomiq-checkout-page__field-error-inline", role: "alert", children: error }) : null
2546
+ ]
2547
+ }
2548
+ );
2549
+ }
2550
+ function CheckoutSelectField({
2551
+ id,
2552
+ label,
2553
+ value,
2554
+ onChange,
2555
+ onClearError,
2556
+ error,
2557
+ disabled,
2558
+ children
2559
+ }) {
2560
+ return /* @__PURE__ */ jsxs("label", { className: "ecomiq-checkout-page__field", children: [
2561
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__label", children: label }),
2562
+ /* @__PURE__ */ jsx(
2563
+ "select",
2564
+ {
2565
+ id,
2566
+ className: `ecomiq-checkout-page__input${error ? " ecomiq-checkout-page__input--error" : ""}`,
2567
+ value,
2568
+ disabled,
2569
+ "aria-invalid": error ? true : void 0,
2570
+ "aria-describedby": error ? `${id}-error` : void 0,
2571
+ onChange: (e) => {
2572
+ onClearError?.();
2573
+ onChange(e.target.value);
2574
+ },
2575
+ children
2576
+ }
2577
+ ),
2578
+ error ? /* @__PURE__ */ jsx("span", { id: `${id}-error`, className: "ecomiq-checkout-page__field-error-inline", role: "alert", children: error }) : null
2579
+ ] });
2580
+ }
2581
+ function geoSelect(id, label, value, placeholder, disabled, options, onChange, error, onClearError) {
2582
+ return /* @__PURE__ */ jsxs(
2583
+ CheckoutSelectField,
2584
+ {
2585
+ id,
2586
+ label,
2587
+ value,
2588
+ error,
2589
+ disabled,
2590
+ onClearError,
2591
+ onChange,
2592
+ children: [
2593
+ /* @__PURE__ */ jsx("option", { value: "", children: placeholder }),
2594
+ options.map((item) => /* @__PURE__ */ jsx("option", { value: item.code, children: item.name }, item.code))
2595
+ ]
2596
+ }
2597
+ );
2598
+ }
2599
+ function CheckoutDeliveryForm({
2600
+ storeId,
2601
+ contact,
2602
+ onContactChange,
2603
+ getFieldError,
2604
+ clearFieldError
2605
+ }) {
2606
+ const {
2607
+ isPeru,
2608
+ departments,
2609
+ provinces,
2610
+ districts,
2611
+ loadingDepartments,
2612
+ loadingProvinces,
2613
+ loadingDistricts,
2614
+ handleDepartmentChange,
2615
+ handleProvinceChange,
2616
+ handleDistrictChange
2617
+ } = useCheckoutDeliveryForm({ storeId, contact, onContactChange });
2618
+ return /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
2619
+ /* @__PURE__ */ jsx("h2", { children: "Delivery" }),
2620
+ /* @__PURE__ */ jsxs(
2621
+ CheckoutSelectField,
2622
+ {
2623
+ id: "countryCode",
2624
+ label: "Country/Region",
2625
+ value: contact.countryCode,
2626
+ error: getFieldError("countryCode"),
2627
+ onClearError: () => clearFieldError("countryCode"),
2628
+ onChange: (v) => onContactChange({ countryCode: v }),
2629
+ children: [
2630
+ /* @__PURE__ */ jsx("option", { value: "PE", children: "Peru" }),
2631
+ /* @__PURE__ */ jsx("option", { value: "US", children: "United States" }),
2632
+ /* @__PURE__ */ jsx("option", { value: "MX", children: "Mexico" }),
2633
+ /* @__PURE__ */ jsx("option", { value: "CO", children: "Colombia" })
2634
+ ]
2635
+ }
2636
+ ),
2637
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__row", children: [
2638
+ /* @__PURE__ */ jsx(
2639
+ CheckoutTextField,
2640
+ {
2641
+ id: "firstName",
2642
+ label: "First name",
2643
+ half: true,
2644
+ value: contact.firstName,
2645
+ error: getFieldError("firstName"),
2646
+ onClearError: () => clearFieldError("firstName"),
2647
+ onChange: (v) => onContactChange({ firstName: v })
2648
+ }
2649
+ ),
2650
+ /* @__PURE__ */ jsx(
2651
+ CheckoutTextField,
2652
+ {
2653
+ id: "lastName",
2654
+ label: "Last name",
2655
+ half: true,
2656
+ value: contact.lastName,
2657
+ error: getFieldError("lastName"),
2658
+ onClearError: () => clearFieldError("lastName"),
2659
+ onChange: (v) => onContactChange({ lastName: v })
2660
+ }
2661
+ )
2662
+ ] }),
2663
+ /* @__PURE__ */ jsx(
2664
+ CheckoutTextField,
2665
+ {
2666
+ id: "address",
2667
+ label: "Address",
2668
+ value: contact.address,
2669
+ error: getFieldError("address"),
2670
+ onClearError: () => clearFieldError("address"),
2671
+ onChange: (v) => onContactChange({ address: v })
2672
+ }
2673
+ ),
2674
+ isPeru ? /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__row ecomiq-checkout-page__row--3", children: [
2675
+ geoSelect(
2676
+ "department",
2677
+ "Departamento",
2678
+ contact.departmentCode,
2679
+ loadingDepartments ? "Cargando\u2026" : "Selecciona",
2680
+ loadingDepartments || departments.length === 0,
2681
+ departments,
2682
+ handleDepartmentChange,
2683
+ getFieldError("department"),
2684
+ () => clearFieldError("department")
2685
+ ),
2686
+ geoSelect(
2687
+ "province-geo",
2688
+ "Provincia",
2689
+ contact.provinceCode,
2690
+ !contact.departmentCode ? "Selecciona depto." : loadingProvinces ? "Cargando\u2026" : "Selecciona",
2691
+ !contact.departmentCode || loadingProvinces || provinces.length === 0,
2692
+ provinces,
2693
+ handleProvinceChange,
2694
+ getFieldError("province-geo"),
2695
+ () => clearFieldError("province-geo")
2696
+ ),
2697
+ geoSelect(
2698
+ "district",
2699
+ "Distrito",
2700
+ contact.districtCode,
2701
+ !contact.provinceCode ? "Selecciona prov." : loadingDistricts ? "Cargando\u2026" : "Selecciona",
2702
+ !contact.provinceCode || loadingDistricts || districts.length === 0,
2703
+ districts,
2704
+ handleDistrictChange,
2705
+ getFieldError("district"),
2706
+ () => clearFieldError("district")
2707
+ )
2708
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__row ecomiq-checkout-page__row--3", children: [
2709
+ /* @__PURE__ */ jsx(
2710
+ CheckoutTextField,
2711
+ {
2712
+ id: "city",
2713
+ label: "City",
2714
+ value: contact.city,
2715
+ error: getFieldError("city"),
2716
+ onClearError: () => clearFieldError("city"),
2717
+ onChange: (v) => onContactChange({ city: v })
2718
+ }
2719
+ ),
2720
+ /* @__PURE__ */ jsx(
2721
+ CheckoutTextField,
2722
+ {
2723
+ id: "province-region",
2724
+ label: "Region",
2725
+ value: contact.province,
2726
+ error: getFieldError("province-region"),
2727
+ onClearError: () => clearFieldError("province-region"),
2728
+ onChange: (v) => onContactChange({ province: v })
2729
+ }
2730
+ )
2731
+ ] }),
2732
+ /* @__PURE__ */ jsx(
2733
+ CheckoutTextField,
2734
+ {
2735
+ id: "postalCode",
2736
+ label: "Postal code",
2737
+ optional: true,
2738
+ value: contact.postalCode,
2739
+ onChange: (v) => onContactChange({ postalCode: v })
2740
+ }
2741
+ ),
2742
+ /* @__PURE__ */ jsx(
2743
+ CheckoutTextField,
2744
+ {
2745
+ id: "phone",
2746
+ label: "Phone",
2747
+ type: "tel",
2748
+ value: contact.phone,
2749
+ error: getFieldError("phone"),
2750
+ onClearError: () => clearFieldError("phone"),
2751
+ onChange: (v) => onContactChange({ phone: v })
2752
+ }
2753
+ )
2754
+ ] });
2755
+ }
2756
+
2757
+ // src/react/components/checkout/payment-providers/checkout-payment-helpers.ts
2758
+ function getPaymentFromCheckout(checkout) {
2759
+ if (!checkout) return null;
2760
+ const raw = checkout.payment;
2761
+ if (!raw || typeof raw !== "object") return null;
2762
+ return raw;
2763
+ }
2764
+ function resolveStripeElementConfig(checkout) {
2765
+ if (!checkout) return null;
2766
+ const payment = getPaymentFromCheckout(checkout);
2767
+ const nestedPk = payment?.action?.publicConfiguration?.publishableKey;
2768
+ const nestedSecret = payment?.action?.clientSecret;
2769
+ const publicKey = (typeof nestedPk === "string" ? nestedPk : void 0) ?? checkout.stripePublicKey ?? checkout.publishableKey ?? checkout.publicKey ?? void 0;
2770
+ const clientSecret = (typeof nestedSecret === "string" ? nestedSecret : void 0) ?? checkout.clientSecret ?? checkout.intentClientSecret ?? void 0;
2771
+ if (!publicKey || !clientSecret) return null;
2772
+ return { publicKey, clientSecret };
2773
+ }
2774
+ function normalizeProviderId(raw) {
2775
+ return (raw ?? "").trim().toLowerCase();
2776
+ }
2777
+ function getProcessingReturnUrl() {
2778
+ if (typeof window === "undefined") return "";
2779
+ return `${window.location.origin}/store/checkout/processing`;
2780
+ }
2781
+ function RedirectPaymentButton({
2782
+ url,
2783
+ label
2784
+ }) {
2785
+ return /* @__PURE__ */ jsx(
2786
+ "a",
2787
+ {
2788
+ href: url,
2789
+ className: "ecomiq-payment-provider__redirect",
2790
+ target: "_blank",
2791
+ rel: "noopener noreferrer",
2792
+ children: label
2793
+ }
2794
+ );
2795
+ }
2796
+ function PaymentPanel({ children }) {
2797
+ return /* @__PURE__ */ jsx("div", { className: "ecomiq-payment-provider__panel", children });
2798
+ }
2799
+ function ExpiresNotice({ expiresAt }) {
2800
+ if (!expiresAt) return null;
2801
+ return /* @__PURE__ */ jsxs("p", { className: "ecomiq-payment-provider__hint ecomiq-payment-provider__hint--sm", children: [
2802
+ "Vence: ",
2803
+ /* @__PURE__ */ jsx("time", { dateTime: expiresAt, children: expiresAt })
2804
+ ] });
2805
+ }
2806
+ var PaymentSubmissionContext = createContext(null);
2807
+ function PaymentSubmissionProvider({ children }) {
2808
+ const submitRef = useRef(null);
2809
+ const [hasSubmitHandler, setHasSubmitHandler] = useState(false);
2810
+ const registerSubmit = useCallback((fn) => {
2811
+ submitRef.current = fn;
2812
+ setHasSubmitHandler(fn != null);
2813
+ }, []);
2814
+ const submitPayment = useCallback(async () => {
2815
+ const fn = submitRef.current;
2816
+ if (!fn) {
2817
+ return {
2818
+ kind: "error",
2819
+ code: "no_handler",
2820
+ message: "El m\xE9todo de pago a\xFAn no est\xE1 listo. Espera un momento e int\xE9ntalo de nuevo.",
2821
+ provider: "unknown"
2822
+ };
2823
+ }
2824
+ return fn();
2825
+ }, []);
2826
+ const value = useMemo(
2827
+ () => ({ registerSubmit, submitPayment, hasSubmitHandler }),
2828
+ [registerSubmit, submitPayment, hasSubmitHandler]
2829
+ );
2830
+ return /* @__PURE__ */ jsx(PaymentSubmissionContext.Provider, { value, children });
2831
+ }
2832
+ function usePaymentSubmission() {
2833
+ const ctx = useContext(PaymentSubmissionContext);
2834
+ if (!ctx) {
2835
+ throw new Error("usePaymentSubmission must be used within PaymentSubmissionProvider");
2836
+ }
2837
+ return ctx;
2838
+ }
2839
+ function useSyncPaymentSubmit(submit) {
2840
+ const { registerSubmit } = usePaymentSubmission();
2841
+ useEffect(() => {
2842
+ registerSubmit(submit);
2843
+ return () => registerSubmit(null);
2844
+ }, [registerSubmit, submit]);
2845
+ }
2846
+
2847
+ // src/react/components/checkout/payment-providers/payment-submit-by-provider.ts
2848
+ async function submitMercadoPagoPayment(payment) {
2849
+ const url = payment.action?.url;
2850
+ if (typeof url === "string" && url.length > 0) {
2851
+ return { kind: "redirect", url, provider: "mercadopago" };
2852
+ }
2853
+ return {
2854
+ kind: "error",
2855
+ code: "no_checkout_url",
2856
+ message: "No hay URL de pago de Mercado Pago. Vuelve a iniciar el checkout.",
2857
+ provider: "mercadopago"
2858
+ };
2859
+ }
2860
+ async function submitPaypalPayment(payment) {
2861
+ const url = payment.action?.url;
2862
+ if (typeof url === "string" && url.length > 0) {
2863
+ return { kind: "redirect", url, provider: "paypal" };
2864
+ }
2865
+ return {
2866
+ kind: "error",
2867
+ code: "no_approval_url",
2868
+ message: "No se recibi\xF3 la URL de PayPal.",
2869
+ provider: "paypal"
2870
+ };
2871
+ }
2872
+ async function submitCulqiPayment(payment) {
2873
+ const url = payment.action?.url;
2874
+ if (typeof url === "string" && url.length > 0) {
2875
+ return { kind: "redirect", url, provider: "culqi" };
2876
+ }
2877
+ return {
2878
+ kind: "error",
2879
+ code: "culqi_embedded",
2880
+ message: "Completa el pago con Culqi seg\xFAn las instrucciones mostradas; la confirmaci\xF3n embebida se integrar\xE1 aqu\xED cuando corresponda.",
2881
+ provider: "culqi"
2882
+ };
2883
+ }
2884
+ async function submitYapePayment(payment) {
2885
+ const qr = payment.action?.qrCode;
2886
+ if (typeof qr === "string" && qr.length > 0) {
2887
+ return {
2888
+ kind: "error",
2889
+ code: "manual_qr",
2890
+ message: "Escanea el c\xF3digo QR con Yape y, cuando el banco confirme, actualizaremos tu pedido autom\xE1ticamente.",
2891
+ provider: "yape"
2892
+ };
2893
+ }
2894
+ return {
2895
+ kind: "error",
2896
+ code: "no_qr",
2897
+ message: "No se recibi\xF3 QR de Yape.",
2898
+ provider: "yape"
2899
+ };
2900
+ }
2901
+ async function submitPagoEfectivoPayment(payment) {
2902
+ const ref = payment.reference ?? payment.transactionId;
2903
+ if (ref) {
2904
+ return {
2905
+ kind: "error",
2906
+ code: "manual_reference",
2907
+ message: "Paga en efectivo con el c\xF3digo indicado antes de la fecha l\xEDmite. Te avisaremos cuando registremos el pago.",
2908
+ provider: "pagoefectivo"
2909
+ };
2910
+ }
2911
+ return {
2912
+ kind: "error",
2913
+ code: "no_reference",
2914
+ message: "No hay c\xF3digo de pago en efectivo disponible.",
2915
+ provider: "pagoefectivo"
2916
+ };
2917
+ }
2918
+ async function submitGenericPayment(payment) {
2919
+ const url = payment.action?.url;
2920
+ if (typeof url === "string" && url.length > 0) {
2921
+ return {
2922
+ kind: "redirect",
2923
+ url,
2924
+ provider: normalizeId(payment.providerId) || "unknown"
2925
+ };
2926
+ }
2927
+ if (payment.actionType === "manual") {
2928
+ return {
2929
+ kind: "redirect",
2930
+ url: getProcessingReturnUrl(),
2931
+ provider: normalizeId(payment.providerId) || "unknown"
2932
+ };
2933
+ }
2934
+ return {
2935
+ kind: "error",
2936
+ code: "manual_or_unsupported",
2937
+ message: "Completa el pago con los datos mostrados arriba o elige otro m\xE9todo si est\xE1 disponible.",
2938
+ provider: normalizeId(payment.providerId) || "unknown"
2939
+ };
2940
+ }
2941
+ function normalizeId(id) {
2942
+ return (id ?? "").trim().toLowerCase();
2943
+ }
2944
+ function CulqiPaymentProvider({ payment }) {
2945
+ const submit = useCallback(() => submitCulqiPayment(payment), [payment]);
2946
+ useSyncPaymentSubmit(submit);
2947
+ const pk = payment.action?.publicConfiguration?.publishableKey;
2948
+ const url = payment.action?.url;
2949
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
2950
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Culqi" }),
2951
+ typeof url === "string" && url.length > 0 ? /* @__PURE__ */ jsx(RedirectPaymentButton, { url, label: "Pagar con Culqi" }) : pk ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Clave p\xFAblica recibida. Integra Culqi Checkout o JS seg\xFAn tu backend (embedded)." }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Configuraci\xF3n de Culqi incompleta." })
2952
+ ] });
2953
+ }
2954
+ function GenericPaymentProvider({ payment }) {
2955
+ const submit = useCallback(() => submitGenericPayment(payment), [payment]);
2956
+ useSyncPaymentSubmit(submit);
2957
+ const url = payment.action?.url;
2958
+ const qr = payment.action?.qrCode;
2959
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
2960
+ /* @__PURE__ */ jsxs("p", { className: "ecomiq-payment-provider__title", children: [
2961
+ "Pago ",
2962
+ payment.providerId ? `(${payment.providerId})` : ""
2963
+ ] }),
2964
+ payment.status ? /* @__PURE__ */ jsxs("p", { className: "ecomiq-payment-provider__hint ecomiq-payment-provider__hint--sm", children: [
2965
+ "Estado: ",
2966
+ payment.status
2967
+ ] }) : null,
2968
+ typeof url === "string" && url.length > 0 ? /* @__PURE__ */ jsx(RedirectPaymentButton, { url, label: "Abrir p\xE1gina de pago" }) : null,
2969
+ typeof qr === "string" && qr.length > 0 ? /* @__PURE__ */ jsx("div", { className: "ecomiq-payment-provider__qr-wrap", children: /* @__PURE__ */ jsx("img", { src: qr, alt: "C\xF3digo QR", className: "ecomiq-payment-provider__qr" }) }) : null,
2970
+ payment.reference ? /* @__PURE__ */ jsx("p", { className: "ecomiq-payment-provider__hint ecomiq-payment-provider__hint--sm ecomiq-payment-provider__mono", children: payment.reference }) : null,
2971
+ /* @__PURE__ */ jsx(ExpiresNotice, { expiresAt: payment.action?.expiresAt }),
2972
+ /* @__PURE__ */ jsxs("details", { className: "ecomiq-payment-provider__details", children: [
2973
+ /* @__PURE__ */ jsx("summary", { children: "Detalle t\xE9cnico" }),
2974
+ /* @__PURE__ */ jsx("pre", { children: JSON.stringify(payment, null, 2) })
2975
+ ] })
2976
+ ] });
2977
+ }
2978
+ function MercadoPagoPaymentProvider({ payment }) {
2979
+ const submit = useCallback(() => submitMercadoPagoPayment(payment), [payment]);
2980
+ useSyncPaymentSubmit(submit);
2981
+ const url = payment.action?.url;
2982
+ const mode = payment.action?.publicConfiguration?.checkoutMode;
2983
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
2984
+ /* @__PURE__ */ jsx("p", { className: "ecomiq-payment-provider__title", children: "Mercado Pago" }),
2985
+ mode ? /* @__PURE__ */ jsxs("p", { className: "ecomiq-payment-provider__hint ecomiq-payment-provider__hint--sm", children: [
2986
+ "Modo: ",
2987
+ mode
2988
+ ] }) : null,
2989
+ typeof url === "string" && url.length > 0 ? /* @__PURE__ */ jsx(RedirectPaymentButton, { url, label: "Pagar con Mercado Pago" }) : /* @__PURE__ */ jsx("p", { className: "ecomiq-payment-provider__hint", children: "Completa el pago cuando el backend env\xEDe la URL de checkout." }),
2990
+ payment.reference ? /* @__PURE__ */ jsxs("p", { className: "ecomiq-payment-provider__hint ecomiq-payment-provider__hint--sm ecomiq-payment-provider__mono", children: [
2991
+ "Ref.: ",
2992
+ payment.reference
2993
+ ] }) : null
2994
+ ] });
2995
+ }
2996
+ function PagoEfectivoPaymentProvider({ payment }) {
2997
+ const submit = useCallback(() => submitPagoEfectivoPayment(payment), [payment]);
2998
+ useSyncPaymentSubmit(submit);
2999
+ const reference = payment.reference ?? payment.transactionId;
3000
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
3001
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Pago en efectivo" }),
3002
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Usa el c\xF3digo de pago en una agencia o app autorizada antes de que venza." }),
3003
+ reference ? /* @__PURE__ */ jsx("div", { className: "rounded-md bg-muted px-3 py-2 font-mono text-sm break-all", children: reference }) : null,
3004
+ payment.amount != null ? /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
3005
+ "Monto a pagar: ",
3006
+ /* @__PURE__ */ jsx("strong", { children: payment.amount })
3007
+ ] }) : null,
3008
+ /* @__PURE__ */ jsx(ExpiresNotice, { expiresAt: payment.action?.expiresAt })
3009
+ ] });
3010
+ }
3011
+ function PaypalPaymentProvider({ payment }) {
3012
+ const submit = useCallback(() => submitPaypalPayment(payment), [payment]);
3013
+ useSyncPaymentSubmit(submit);
3014
+ const url = payment.action?.url;
3015
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
3016
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "PayPal" }),
3017
+ typeof url === "string" && url.length > 0 ? /* @__PURE__ */ jsx(RedirectPaymentButton, { url, label: "Continuar a PayPal" }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Esperando URL de aprobaci\xF3n de PayPal desde el servidor." })
3018
+ ] });
3019
+ }
3020
+ async function confirmStripePaymentWithElements(params) {
3021
+ const { stripe, elements, returnUrl } = params;
3022
+ const result = await stripe.confirmPayment({
3023
+ elements,
3024
+ confirmParams: {
3025
+ return_url: returnUrl,
3026
+ payment_method_data: {}
3027
+ },
3028
+ redirect: "if_required"
3029
+ });
3030
+ if (result.error) {
3031
+ return {
3032
+ kind: "error",
3033
+ code: result.error.code ?? "stripe_error",
3034
+ message: result.error.message ?? "Error al procesar el pago",
3035
+ provider: "stripe",
3036
+ raw: result.error
3037
+ };
3038
+ }
3039
+ const paymentIntent = result.paymentIntent;
3040
+ if (paymentIntent?.status === "succeeded") {
3041
+ return {
3042
+ kind: "success",
3043
+ transactionId: paymentIntent.id,
3044
+ provider: "stripe",
3045
+ raw: paymentIntent
3046
+ };
3047
+ }
3048
+ return {
3049
+ kind: "error",
3050
+ code: "pending",
3051
+ message: "El pago est\xE1 pendiente.",
3052
+ provider: "stripe",
3053
+ raw: paymentIntent
3054
+ };
3055
+ }
3056
+ function StripePaymentProvider({ checkout }) {
3057
+ const stripeMountRef = useRef(null);
3058
+ const stripePaymentElementRef = useRef(null);
3059
+ const stripeRef = useRef(null);
3060
+ const elementsRef = useRef(null);
3061
+ const { registerSubmit } = usePaymentSubmission();
3062
+ const stripeConfig = resolveStripeElementConfig(checkout);
3063
+ useEffect(() => {
3064
+ if (!stripeConfig) {
3065
+ stripePaymentElementRef.current?.unmount?.();
3066
+ stripePaymentElementRef.current = null;
3067
+ stripeRef.current = null;
3068
+ elementsRef.current = null;
3069
+ registerSubmit(null);
3070
+ return;
3071
+ }
3072
+ let cancelled = false;
3073
+ const ensureStripeScript = () => new Promise((resolve, reject) => {
3074
+ const maybeStripe = globalThis.Stripe;
3075
+ if (maybeStripe) return resolve();
3076
+ const existing = document.querySelector('script[src="https://js.stripe.com/v3/"]');
3077
+ if (existing) {
3078
+ existing.addEventListener("load", () => resolve(), { once: true });
3079
+ existing.addEventListener(
3080
+ "error",
3081
+ () => reject(new Error("Stripe script failed to load")),
3082
+ { once: true }
3083
+ );
3084
+ return;
3085
+ }
3086
+ const script = document.createElement("script");
3087
+ script.src = "https://js.stripe.com/v3/";
3088
+ script.async = true;
3089
+ script.addEventListener("load", () => resolve(), { once: true });
3090
+ script.addEventListener(
3091
+ "error",
3092
+ () => reject(new Error("Stripe script failed to load")),
3093
+ { once: true }
3094
+ );
3095
+ document.head.appendChild(script);
3096
+ });
3097
+ const mountStripePaymentElement = async () => {
3098
+ await ensureStripeScript();
3099
+ if (cancelled) return;
3100
+ const StripeCtor = globalThis.Stripe;
3101
+ if (!StripeCtor) throw new Error("Stripe is not available");
3102
+ const stripeJs = StripeCtor(stripeConfig.publicKey);
3103
+ stripeRef.current = stripeJs;
3104
+ const elements = stripeJs.elements({ clientSecret: stripeConfig.clientSecret });
3105
+ stripePaymentElementRef.current?.unmount?.();
3106
+ stripePaymentElementRef.current = null;
3107
+ const paymentElement = elements.create("payment");
3108
+ const mountNode = stripeMountRef.current;
3109
+ if (!mountNode) return;
3110
+ paymentElement.mount(mountNode);
3111
+ stripePaymentElementRef.current = paymentElement;
3112
+ elementsRef.current = elements;
3113
+ registerSubmit(async () => {
3114
+ const s = stripeRef.current;
3115
+ const el = elementsRef.current;
3116
+ if (!s || !el) {
3117
+ return {
3118
+ kind: "error",
3119
+ code: "stripe_not_ready",
3120
+ message: "Stripe no est\xE1 listo. Espera un momento e int\xE9ntalo de nuevo.",
3121
+ provider: "stripe"
3122
+ };
3123
+ }
3124
+ const returnUrl = getProcessingReturnUrl();
3125
+ return confirmStripePaymentWithElements({
3126
+ stripe: s,
3127
+ elements: el,
3128
+ returnUrl
3129
+ });
3130
+ });
3131
+ };
3132
+ mountStripePaymentElement().catch(() => {
3133
+ registerSubmit(null);
3134
+ });
3135
+ return () => {
3136
+ cancelled = true;
3137
+ stripePaymentElementRef.current?.unmount?.();
3138
+ stripePaymentElementRef.current = null;
3139
+ stripeRef.current = null;
3140
+ elementsRef.current = null;
3141
+ registerSubmit(null);
3142
+ };
3143
+ }, [stripeConfig?.publicKey, stripeConfig?.clientSecret, registerSubmit]);
3144
+ if (!stripeConfig) {
3145
+ return /* @__PURE__ */ jsx(PaymentPanel, { children: /* @__PURE__ */ jsx("p", { className: "ecomiq-payment-provider__hint", children: "No se recibi\xF3 la configuraci\xF3n de Stripe (publishable key / client secret)." }) });
3146
+ }
3147
+ return /* @__PURE__ */ jsx(PaymentPanel, { children: /* @__PURE__ */ jsx("div", { ref: stripeMountRef }) });
3148
+ }
3149
+ function YapePaymentProvider({ payment }) {
3150
+ const submit = useCallback(() => submitYapePayment(payment), [payment]);
3151
+ useSyncPaymentSubmit(submit);
3152
+ const qr = payment.action?.qrCode;
3153
+ return /* @__PURE__ */ jsxs(PaymentPanel, { children: [
3154
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Yape" }),
3155
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Escanea el c\xF3digo QR con la app Yape para completar el pago." }),
3156
+ typeof qr === "string" && qr.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
3157
+ "img",
3158
+ {
3159
+ src: qr,
3160
+ alt: "C\xF3digo QR Yape",
3161
+ className: "max-w-[220px] rounded-md border bg-white p-2"
3162
+ }
3163
+ ) }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: "No se recibi\xF3 QR en la respuesta." }),
3164
+ payment.amount != null ? /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
3165
+ "Monto: ",
3166
+ /* @__PURE__ */ jsx("strong", { children: payment.amount })
3167
+ ] }) : null,
3168
+ /* @__PURE__ */ jsx(ExpiresNotice, { expiresAt: payment.action?.expiresAt })
3169
+ ] });
3170
+ }
3171
+ var REGISTRY = {
3172
+ stripe: StripePaymentProvider,
3173
+ mercadopago: MercadoPagoPaymentProvider,
3174
+ mercado_pago: MercadoPagoPaymentProvider,
3175
+ paypal: PaypalPaymentProvider,
3176
+ culqi: CulqiPaymentProvider,
3177
+ yape: YapePaymentProvider,
3178
+ pagoefectivo: PagoEfectivoPaymentProvider,
3179
+ pago_efectivo: PagoEfectivoPaymentProvider
3180
+ };
3181
+ function PaymentProviderRouter({ checkout }) {
3182
+ const payment = useMemo(() => getPaymentFromCheckout(checkout), [checkout]);
3183
+ if (!payment) {
3184
+ return null;
3185
+ }
3186
+ const key = normalizeProviderId(payment.providerId);
3187
+ const Provider = key ? REGISTRY[key] : void 0;
3188
+ if (Provider) {
3189
+ return /* @__PURE__ */ jsx(Provider, { payment, checkout });
3190
+ }
3191
+ return /* @__PURE__ */ jsx(GenericPaymentProvider, { payment, checkout });
3192
+ }
3193
+
3194
+ // src/react/pages/checkout-page/lib/checkout-payment-method.ts
3195
+ var PROVIDER_CHECKOUT_UI = /* @__PURE__ */ new Set(["stripe", "mercadopago", "mercado_pago"]);
3196
+ function normalizeProviderKey(raw) {
3197
+ return raw.trim().toLowerCase().replace(/[\s-]+/g, "_");
3198
+ }
3199
+ function methodUsesProviderCheckoutUi(method) {
3200
+ if (method.isManual) return false;
3201
+ const keys = [method.providerMethodCode, method.kind, method.code].filter(
3202
+ Boolean
3203
+ );
3204
+ return keys.some((key) => {
3205
+ const normalized = normalizeProviderKey(key);
3206
+ return PROVIDER_CHECKOUT_UI.has(normalized) || normalized.includes("stripe") || normalized.includes("mercado");
3207
+ });
3208
+ }
3209
+
3210
+ // src/react/pages/checkout-page/hooks/use-checkout-payment.ts
3211
+ function useCheckoutPayment({
3212
+ paymentMethods,
3213
+ selectedPaymentCode,
3214
+ selectPaymentMethod,
3215
+ providerPaymentCompleted,
3216
+ setProviderPaymentCompleted,
3217
+ checkoutResponse,
3218
+ checkoutMethodCode,
3219
+ loadingCheckout,
3220
+ checkoutError,
3221
+ onUploadReceipt,
3222
+ onPaymentSubmissionResult,
3223
+ onCanProceedToPayChange,
3224
+ clearFieldError
3225
+ }) {
3226
+ const { submitPayment, hasSubmitHandler } = usePaymentSubmission();
3227
+ const activeMethods = useMemo(
3228
+ () => paymentMethods.filter((m) => m.isActive).slice().sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)),
3229
+ [paymentMethods]
3230
+ );
3231
+ const selectedMethod = useMemo(
3232
+ () => activeMethods.find((m) => m.code === selectedPaymentCode) ?? null,
3233
+ [activeMethods, selectedPaymentCode]
3234
+ );
3235
+ const requiresProviderUi = Boolean(
3236
+ selectedMethod && methodUsesProviderCheckoutUi(selectedMethod)
3237
+ );
3238
+ const effectiveCheckout = checkoutMethodCode && checkoutMethodCode === selectedMethod?.code ? checkoutResponse ?? null : null;
3239
+ const activeLoadingCheckout = !!checkoutMethodCode && checkoutMethodCode === selectedMethod?.code && loadingCheckout;
3240
+ const activeCheckoutError = checkoutMethodCode && checkoutMethodCode === selectedMethod?.code ? checkoutError : null;
3241
+ const manualPaymentDetails = useMemo(() => {
3242
+ if (!selectedMethod?.isManual) return null;
3243
+ const action = getPaymentFromCheckout(effectiveCheckout)?.action ?? null;
3244
+ const publicConfiguration = action?.publicConfiguration ?? {};
3245
+ const phoneNumber = selectedMethod.phoneNumber ?? publicConfiguration.phoneNumber ?? null;
3246
+ const accountHolder = selectedMethod.accountHolder ?? publicConfiguration.accountHolder ?? null;
3247
+ const qrImageUrl = action?.qrCode ?? selectedMethod.qrImageUrl ?? publicConfiguration.qrImageUrl ?? null;
3248
+ if (!phoneNumber && !accountHolder && !qrImageUrl) return null;
3249
+ return { phoneNumber, accountHolder, qrImageUrl };
3250
+ }, [selectedMethod, effectiveCheckout]);
3251
+ const needsReceipt = Boolean(selectedMethod?.isManual && manualPaymentDetails);
3252
+ const showProviderPanel = requiresProviderUi && !!selectedMethod && !!effectiveCheckout && !activeLoadingCheckout && !activeCheckoutError;
3253
+ const [receiptFile, setReceiptFile] = useState(null);
3254
+ const [receiptUrl, setReceiptUrl] = useState(null);
3255
+ const [receiptError, setReceiptError] = useState(null);
3256
+ const [confirmingProvider, setConfirmingProvider] = useState(false);
3257
+ const receiptPreviewUrl = useMemo(
3258
+ () => receiptFile ? URL.createObjectURL(receiptFile) : null,
3259
+ [receiptFile]
3260
+ );
3261
+ useEffect(() => {
3262
+ return () => {
3263
+ if (receiptPreviewUrl) URL.revokeObjectURL(receiptPreviewUrl);
3264
+ };
3265
+ }, [receiptPreviewUrl]);
3266
+ useEffect(() => {
3267
+ setReceiptFile(null);
3268
+ setReceiptUrl(null);
3269
+ setReceiptError(null);
3270
+ }, [selectedMethod?.code]);
3271
+ const selectPayment = useCallback(
3272
+ (code) => {
3273
+ clearFieldError?.("checkout-payment-method");
3274
+ selectPaymentMethod(code);
3275
+ },
3276
+ [clearFieldError, selectPaymentMethod]
3277
+ );
3278
+ const handleReceiptChange = useCallback((event) => {
3279
+ const file = event.target.files?.[0] ?? null;
3280
+ setReceiptUrl(null);
3281
+ setReceiptError(null);
3282
+ if (!file) {
3283
+ setReceiptFile(null);
3284
+ return;
3285
+ }
3286
+ if (!file.type.startsWith("image/")) {
3287
+ setReceiptFile(null);
3288
+ setReceiptError("Adjunta una imagen del comprobante.");
3289
+ return;
3290
+ }
3291
+ setReceiptFile(file);
3292
+ }, []);
3293
+ const confirmProviderPayment = useCallback(async () => {
3294
+ if (!showProviderPanel) return;
3295
+ setConfirmingProvider(true);
3296
+ try {
3297
+ const result = await submitPayment();
3298
+ if (result.kind === "redirect") {
3299
+ onPaymentSubmissionResult?.(result);
3300
+ return;
3301
+ }
3302
+ if (result.kind === "success") {
3303
+ setProviderPaymentCompleted(true);
3304
+ return;
3305
+ }
3306
+ onPaymentSubmissionResult?.(result);
3307
+ } catch {
3308
+ setReceiptError("No se pudo completar el pago. Int\xE9ntalo de nuevo.");
3309
+ } finally {
3310
+ setConfirmingProvider(false);
3311
+ }
3312
+ }, [
3313
+ onPaymentSubmissionResult,
3314
+ setProviderPaymentCompleted,
3315
+ showProviderPanel,
3316
+ submitPayment
3317
+ ]);
3318
+ const runPreCheckoutSteps = useCallback(async () => {
3319
+ if (!selectedMethod) return { ok: false };
3320
+ setReceiptError(null);
3321
+ try {
3322
+ if (needsReceipt) {
3323
+ let nextReceiptUrl = receiptUrl;
3324
+ if (!nextReceiptUrl) {
3325
+ if (!receiptFile) {
3326
+ setReceiptError("Adjunta el comprobante para completar la orden.");
3327
+ return { ok: false };
3328
+ }
3329
+ const uploaded = await onUploadReceipt(receiptFile);
3330
+ nextReceiptUrl = uploaded.url;
3331
+ setReceiptUrl(nextReceiptUrl);
3332
+ }
3333
+ return { ok: true, receiptUrl: nextReceiptUrl ?? void 0 };
3334
+ }
3335
+ if (requiresProviderUi) {
3336
+ if (!providerPaymentCompleted) {
3337
+ setReceiptError(
3338
+ "Confirma el pago con Stripe o Mercado Pago antes de finalizar el pedido."
3339
+ );
3340
+ return { ok: false };
3341
+ }
3342
+ return { ok: true, finalizeOnly: true };
3343
+ }
3344
+ return { ok: true };
3345
+ } catch {
3346
+ setReceiptError("No se pudo completar el pago. Int\xE9ntalo de nuevo.");
3347
+ return { ok: false };
3348
+ }
3349
+ }, [
3350
+ needsReceipt,
3351
+ onUploadReceipt,
3352
+ providerPaymentCompleted,
3353
+ receiptFile,
3354
+ receiptUrl,
3355
+ requiresProviderUi,
3356
+ selectedMethod
3357
+ ]);
3358
+ const canProceedToPay = useMemo(() => {
3359
+ if (!selectedMethod) return false;
3360
+ if (activeLoadingCheckout || activeCheckoutError) return false;
3361
+ if (requiresProviderUi) {
3362
+ return providerPaymentCompleted;
3363
+ }
3364
+ return (!needsReceipt || !!receiptFile || !!receiptUrl) && (!showProviderPanel || hasSubmitHandler);
3365
+ }, [
3366
+ activeCheckoutError,
3367
+ activeLoadingCheckout,
3368
+ hasSubmitHandler,
3369
+ needsReceipt,
3370
+ providerPaymentCompleted,
3371
+ receiptFile,
3372
+ receiptUrl,
3373
+ requiresProviderUi,
3374
+ selectedMethod,
3375
+ showProviderPanel
3376
+ ]);
3377
+ useEffect(() => {
3378
+ onCanProceedToPayChange?.(canProceedToPay);
3379
+ }, [canProceedToPay, onCanProceedToPayChange]);
3380
+ const providerConfirmLabel = useMemo(() => {
3381
+ if (!selectedMethod) return "Confirmar pago";
3382
+ const key = (selectedMethod.providerMethodCode ?? selectedMethod.kind ?? "").toLowerCase().replace(/[\s-]+/g, "_");
3383
+ if (key.includes("mercado")) return "Ir a Mercado Pago";
3384
+ if (key.includes("stripe")) return "Confirmar pago con tarjeta";
3385
+ return "Confirmar pago";
3386
+ }, [selectedMethod]);
3387
+ return {
3388
+ activeMethods,
3389
+ selectedMethod,
3390
+ effectiveCheckout,
3391
+ activeLoadingCheckout,
3392
+ activeCheckoutError,
3393
+ manualPaymentDetails,
3394
+ needsReceipt,
3395
+ requiresProviderUi,
3396
+ showProviderPanel,
3397
+ providerPaymentCompleted,
3398
+ confirmingProvider,
3399
+ providerConfirmLabel,
3400
+ receiptFile,
3401
+ receiptUrl,
3402
+ receiptError,
3403
+ receiptPreviewUrl,
3404
+ selectPayment,
3405
+ handleReceiptChange,
3406
+ confirmProviderPayment,
3407
+ runPreCheckoutSteps,
3408
+ canProceedToPay,
3409
+ hasSubmitHandler
3410
+ };
3411
+ }
3412
+ function CheckoutPaymentSectionInner({
3413
+ paymentRef,
3414
+ getFieldError,
3415
+ clearFieldError,
3416
+ ...paymentArgs
3417
+ }) {
3418
+ const payment = useCheckoutPayment({
3419
+ ...paymentArgs,
3420
+ clearFieldError
3421
+ });
3422
+ useImperativeHandle(
3423
+ paymentRef,
3424
+ () => ({
3425
+ runPreCheckoutSteps: payment.runPreCheckoutSteps,
3426
+ canProceedToPay: payment.canProceedToPay
3427
+ }),
3428
+ [payment.canProceedToPay, payment.runPreCheckoutSteps]
3429
+ );
3430
+ const paymentFieldError = getFieldError?.("checkout-payment-method");
3431
+ return /* @__PURE__ */ jsxs(
3432
+ "section",
3433
+ {
3434
+ className: "ecomiq-checkout-page__section",
3435
+ id: "checkout-payment-method",
3436
+ children: [
3437
+ /* @__PURE__ */ jsx("h2", { children: "Payment" }),
3438
+ /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "All transactions are secure and encrypted." }),
3439
+ paymentFieldError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error-inline", role: "alert", children: paymentFieldError }) : null,
3440
+ /* @__PURE__ */ jsx(
3441
+ "div",
3442
+ {
3443
+ className: `ecomiq-checkout-page__options${paymentFieldError ? " ecomiq-checkout-page__options--error" : ""}`,
3444
+ children: payment.activeMethods.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "No payment methods available." }) : payment.activeMethods.map((method) => /* @__PURE__ */ jsxs(
3445
+ "label",
3446
+ {
3447
+ className: `ecomiq-checkout-page__option${paymentArgs.selectedPaymentCode === method.code ? " is-selected" : ""}`,
3448
+ children: [
3449
+ /* @__PURE__ */ jsx(
3450
+ "input",
3451
+ {
3452
+ type: "radio",
3453
+ name: "payment",
3454
+ checked: paymentArgs.selectedPaymentCode === method.code,
3455
+ onChange: () => payment.selectPayment(method.code)
3456
+ }
3457
+ ),
3458
+ /* @__PURE__ */ jsxs("span", { className: "ecomiq-checkout-page__option-body", children: [
3459
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-title", children: method.name }),
3460
+ method.description ? /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-sub", children: method.description }) : null
3461
+ ] })
3462
+ ]
3463
+ },
3464
+ method.code
3465
+ ))
3466
+ }
3467
+ ),
3468
+ payment.activeLoadingCheckout ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "Cargando configuraci\xF3n del m\xE9todo de pago\u2026" }) : null,
3469
+ payment.activeCheckoutError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error", role: "alert", children: payment.activeCheckoutError }) : null,
3470
+ payment.selectedMethod && payment.manualPaymentDetails ? /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__manual-payment", children: /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__manual-payment-body", children: [
3471
+ payment.manualPaymentDetails.qrImageUrl ? /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__manual-payment-qr", children: /* @__PURE__ */ jsx(
3472
+ "img",
3473
+ {
3474
+ src: payment.manualPaymentDetails.qrImageUrl,
3475
+ alt: `${payment.selectedMethod.name} QR`
3476
+ }
3477
+ ) }) : null,
3478
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__manual-payment-info", children: [
3479
+ /* @__PURE__ */ jsxs("p", { className: "ecomiq-checkout-page__manual-payment-title", children: [
3480
+ "Pay with ",
3481
+ payment.selectedMethod.name
3482
+ ] }),
3483
+ /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "Send the payment and keep your receipt. The order will stay pending until it is reviewed." }),
3484
+ payment.manualPaymentDetails.phoneNumber ? /* @__PURE__ */ jsxs("p", { className: "ecomiq-checkout-page__manual-payment-row", children: [
3485
+ /* @__PURE__ */ jsx("span", { children: "Cell phone" }),
3486
+ /* @__PURE__ */ jsx("strong", { children: payment.manualPaymentDetails.phoneNumber })
3487
+ ] }) : null,
3488
+ payment.manualPaymentDetails.accountHolder ? /* @__PURE__ */ jsxs("p", { className: "ecomiq-checkout-page__manual-payment-row", children: [
3489
+ /* @__PURE__ */ jsx("span", { children: "Holder" }),
3490
+ /* @__PURE__ */ jsx("strong", { children: payment.manualPaymentDetails.accountHolder })
3491
+ ] }) : null,
3492
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__receipt-upload", children: [
3493
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__label", children: "Payment receipt" }),
3494
+ /* @__PURE__ */ jsxs("label", { className: "ecomiq-checkout-page__receipt-label", children: [
3495
+ /* @__PURE__ */ jsx(
3496
+ "input",
3497
+ {
3498
+ type: "file",
3499
+ accept: "image/*",
3500
+ className: "ecomiq-checkout-page__receipt-input",
3501
+ onChange: payment.handleReceiptChange
3502
+ }
3503
+ ),
3504
+ /* @__PURE__ */ jsx("span", { children: payment.receiptFile?.name ?? (payment.receiptUrl ? "Receipt attached" : "Upload receipt") })
3505
+ ] }),
3506
+ payment.receiptPreviewUrl ? /* @__PURE__ */ jsx(
3507
+ "img",
3508
+ {
3509
+ src: payment.receiptPreviewUrl,
3510
+ alt: "Payment receipt",
3511
+ className: "ecomiq-checkout-page__receipt-preview"
3512
+ }
3513
+ ) : null,
3514
+ payment.receiptError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error-inline", role: "alert", children: payment.receiptError }) : null
3515
+ ] })
3516
+ ] })
3517
+ ] }) }) : null,
3518
+ payment.showProviderPanel && payment.effectiveCheckout ? /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__payment-provider", children: [
3519
+ /* @__PURE__ */ jsx(PaymentProviderRouter, { checkout: payment.effectiveCheckout }),
3520
+ !payment.providerPaymentCompleted ? /* @__PURE__ */ jsx(
3521
+ "button",
3522
+ {
3523
+ type: "button",
3524
+ className: "ecomiq-checkout-page__provider-confirm",
3525
+ disabled: payment.confirmingProvider || !payment.hasSubmitHandler,
3526
+ onClick: () => void payment.confirmProviderPayment(),
3527
+ children: payment.confirmingProvider ? "Procesando pago\u2026" : payment.providerConfirmLabel
3528
+ }
3529
+ ) : /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", role: "status", children: "Pago confirmado. Pulsa Pay now para finalizar tu pedido." })
3530
+ ] }) : null,
3531
+ payment.requiresProviderUi && !payment.showProviderPanel && !payment.activeLoadingCheckout && !payment.activeCheckoutError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "Espera a que cargue la configuraci\xF3n del m\xE9todo de pago." }) : null
3532
+ ]
3533
+ }
3534
+ );
3535
+ }
3536
+ var CheckoutPaymentSection = forwardRef(function CheckoutPaymentSection2(props, ref) {
3537
+ return /* @__PURE__ */ jsx(PaymentSubmissionProvider, { children: /* @__PURE__ */ jsx(CheckoutPaymentSectionInner, { paymentRef: ref, ...props }) });
3538
+ });
3539
+ function CheckoutMainForm({
3540
+ storeId,
3541
+ contact,
3542
+ onContactChange,
3543
+ billingChoice,
3544
+ onBillingChange,
3545
+ shippingOptions,
3546
+ shippingLoading,
3547
+ shippingError,
3548
+ selectedShippingKey,
3549
+ onSelectShipping,
3550
+ paymentMethods,
3551
+ selectedPaymentCode,
3552
+ selectPaymentMethod,
3553
+ providerPaymentCompleted,
3554
+ setProviderPaymentCompleted,
3555
+ checkoutPaymentResponse,
3556
+ checkoutPaymentMethodCode,
3557
+ checkoutPaymentLoading,
3558
+ checkoutPaymentError,
3559
+ onUploadReceipt,
3560
+ onPaymentSubmissionResult,
3561
+ currency,
3562
+ formError,
3563
+ isSaving,
3564
+ onPayNow,
3565
+ signInHref,
3566
+ Link
3567
+ }) {
3568
+ const paymentRef = useRef(null);
3569
+ const [canProceedToPay, setCanProceedToPay] = useState(false);
3570
+ const {
3571
+ validationError,
3572
+ validateCheckoutForm,
3573
+ clearFieldError,
3574
+ getFieldError
3575
+ } = useCheckoutFormValidation(currency);
3576
+ const displayError = validationError ?? formError;
3577
+ const handlePayClick = async () => {
3578
+ const valid = validateCheckoutForm({
3579
+ contact,
3580
+ selectedShippingKey,
3581
+ shippingOptionsCount: shippingOptions.length,
3582
+ selectedPaymentCode,
3583
+ paymentMethodsCount: paymentMethods.length
3584
+ });
3585
+ if (!valid) return;
3586
+ const prep = await paymentRef.current?.runPreCheckoutSteps();
3587
+ if (!prep?.ok) return;
3588
+ await onPayNow({ receiptUrl: prep.receiptUrl });
3589
+ };
3590
+ return /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__form", children: [
3591
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3592
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__section-head", children: [
3593
+ /* @__PURE__ */ jsx("h2", { children: "Contact" }),
3594
+ signInHref ? /* @__PURE__ */ jsx(Link, { href: signInHref, className: "ecomiq-checkout-page__link", children: "Sign in" }) : null
3595
+ ] }),
3596
+ /* @__PURE__ */ jsx(
3597
+ CheckoutTextField,
3598
+ {
3599
+ id: "email",
3600
+ label: "Email",
3601
+ type: "email",
3602
+ value: contact.email,
3603
+ error: getFieldError("email"),
3604
+ onClearError: () => clearFieldError("email"),
3605
+ onChange: (v) => onContactChange({ email: v })
3606
+ }
3607
+ ),
3608
+ /* @__PURE__ */ jsxs("label", { className: "ecomiq-checkout-page__checkbox", children: [
3609
+ /* @__PURE__ */ jsx(
3610
+ "input",
3611
+ {
3612
+ type: "checkbox",
3613
+ checked: contact.marketingOptIn,
3614
+ onChange: (e) => onContactChange({ marketingOptIn: e.target.checked })
3615
+ }
3616
+ ),
3617
+ /* @__PURE__ */ jsx("span", { children: "Email me with news and offers" })
3618
+ ] })
3619
+ ] }),
3620
+ /* @__PURE__ */ jsx(
3621
+ CheckoutDeliveryForm,
3622
+ {
3623
+ storeId,
3624
+ contact,
3625
+ onContactChange,
3626
+ getFieldError,
3627
+ clearFieldError
3628
+ }
3629
+ ),
3630
+ /* @__PURE__ */ jsxs(
3631
+ "section",
3632
+ {
3633
+ className: "ecomiq-checkout-page__section",
3634
+ id: "checkout-shipping-method",
3635
+ children: [
3636
+ /* @__PURE__ */ jsx("h2", { children: "Shipping method" }),
3637
+ getFieldError("checkout-shipping-method") ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error-inline", role: "alert", children: getFieldError("checkout-shipping-method") }) : null,
3638
+ shippingLoading ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "Loading shipping options\u2026" }) : shippingError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error", children: shippingError }) : shippingOptions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__hint", children: "Enter your postal code to see shipping rates." }) : /* @__PURE__ */ jsx(
3639
+ "div",
3640
+ {
3641
+ className: `ecomiq-checkout-page__options${getFieldError("checkout-shipping-method") ? " ecomiq-checkout-page__options--error" : ""}`,
3642
+ children: shippingOptions.map((opt) => /* @__PURE__ */ jsxs(
3643
+ "label",
3644
+ {
3645
+ className: `ecomiq-checkout-page__option${selectedShippingKey === opt.key ? " is-selected" : ""}`,
3646
+ children: [
3647
+ /* @__PURE__ */ jsx(
3648
+ "input",
3649
+ {
3650
+ type: "radio",
3651
+ name: "shipping",
3652
+ checked: selectedShippingKey === opt.key,
3653
+ onChange: () => {
3654
+ clearFieldError("checkout-shipping-method");
3655
+ onSelectShipping(opt.key);
3656
+ }
3657
+ }
3658
+ ),
3659
+ /* @__PURE__ */ jsxs("span", { className: "ecomiq-checkout-page__option-body", children: [
3660
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-title", children: opt.title }),
3661
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-sub", children: opt.subtitle })
3662
+ ] }),
3663
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-price", children: formatCurrency(opt.price, currency) })
3664
+ ]
3665
+ },
3666
+ opt.key
3667
+ ))
3668
+ }
3669
+ )
3670
+ ]
3671
+ }
3672
+ ),
3673
+ /* @__PURE__ */ jsx(
3674
+ CheckoutPaymentSection,
3675
+ {
3676
+ ref: paymentRef,
3677
+ paymentMethods,
3678
+ selectedPaymentCode,
3679
+ selectPaymentMethod,
3680
+ providerPaymentCompleted,
3681
+ setProviderPaymentCompleted,
3682
+ checkoutResponse: checkoutPaymentResponse,
3683
+ onCanProceedToPayChange: setCanProceedToPay,
3684
+ checkoutMethodCode: checkoutPaymentMethodCode,
3685
+ loadingCheckout: checkoutPaymentLoading,
3686
+ checkoutError: checkoutPaymentError,
3687
+ onUploadReceipt,
3688
+ onPaymentSubmissionResult,
3689
+ getFieldError,
3690
+ clearFieldError
3691
+ }
3692
+ ),
3693
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3694
+ /* @__PURE__ */ jsx("h2", { children: "Billing address" }),
3695
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__options", children: [
3696
+ /* @__PURE__ */ jsxs(
3697
+ "label",
3698
+ {
3699
+ className: `ecomiq-checkout-page__option${billingChoice === "same_as_shipping" ? " is-selected" : ""}`,
3700
+ children: [
3701
+ /* @__PURE__ */ jsx(
3702
+ "input",
3703
+ {
3704
+ type: "radio",
3705
+ name: "billing",
3706
+ checked: billingChoice === "same_as_shipping",
3707
+ onChange: () => onBillingChange("same_as_shipping")
3708
+ }
3709
+ ),
3710
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-body", children: /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-title", children: "Same as shipping address" }) })
3711
+ ]
3712
+ }
3713
+ ),
3714
+ /* @__PURE__ */ jsxs(
3715
+ "label",
3716
+ {
3717
+ className: `ecomiq-checkout-page__option${billingChoice === "different" ? " is-selected" : ""}`,
3718
+ children: [
3719
+ /* @__PURE__ */ jsx(
3720
+ "input",
3721
+ {
3722
+ type: "radio",
3723
+ name: "billing",
3724
+ checked: billingChoice === "different",
3725
+ onChange: () => onBillingChange("different")
3726
+ }
3727
+ ),
3728
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-body", children: /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__option-title", children: "Use a different billing address" }) })
3729
+ ]
3730
+ }
3731
+ )
3732
+ ] })
3733
+ ] }),
3734
+ displayError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error", role: "alert", children: displayError }) : null,
3735
+ /* @__PURE__ */ jsx(
3736
+ "button",
3737
+ {
3738
+ type: "button",
3739
+ className: "ecomiq-checkout-page__pay",
3740
+ disabled: isSaving || !canProceedToPay,
3741
+ onClick: () => void handlePayClick(),
3742
+ children: isSaving ? "Processing\u2026" : "Pay now"
3743
+ }
3744
+ ),
3745
+ /* @__PURE__ */ jsxs("nav", { className: "ecomiq-checkout-page__policies", "aria-label": "Policies", children: [
3746
+ /* @__PURE__ */ jsx("a", { href: "#", children: "Refund policy" }),
3747
+ /* @__PURE__ */ jsx("a", { href: "#", children: "Shipping" }),
3748
+ /* @__PURE__ */ jsx("a", { href: "#", children: "Privacy policy" }),
3749
+ /* @__PURE__ */ jsx("a", { href: "#", children: "Terms of service" })
3750
+ ] })
3751
+ ] });
3752
+ }
3753
+ function CheckoutOrderSummary({
3754
+ items,
3755
+ currency,
3756
+ subtotal,
3757
+ shipping,
3758
+ discount,
3759
+ tax,
3760
+ total,
3761
+ couponCodes,
3762
+ couponCode,
3763
+ couponError,
3764
+ couponBusy,
3765
+ onCouponCodeChange,
3766
+ onApplyCoupon,
3767
+ onRemoveCoupon
3768
+ }) {
3769
+ const onCouponSubmit = (e) => {
3770
+ e.preventDefault();
3771
+ onApplyCoupon();
3772
+ };
3773
+ return /* @__PURE__ */ jsxs("aside", { className: "ecomiq-checkout-page__summary", children: [
3774
+ /* @__PURE__ */ jsx("ul", { className: "ecomiq-checkout-page__summary-items", children: items.map((item) => /* @__PURE__ */ jsxs("li", { className: "ecomiq-checkout-page__summary-item", children: [
3775
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__summary-thumb", children: [
3776
+ /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__summary-thumb-image", children: item.image ? /* @__PURE__ */ jsx("img", { src: item.image, alt: "" }) : /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__summary-thumb-ph" }) }),
3777
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__summary-qty", children: item.quantity })
3778
+ ] }),
3779
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__summary-item-body", children: [
3780
+ /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__summary-item-title", children: item.title }),
3781
+ (item.variantLabel || item.size) && /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__summary-item-meta", children: item.variantLabel ?? item.size })
3782
+ ] }),
3783
+ /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__summary-item-price", children: formatCurrency(item.price * item.quantity, currency) })
3784
+ ] }, item.id)) }),
3785
+ /* @__PURE__ */ jsxs("form", { className: "ecomiq-checkout-page__discount", onSubmit: onCouponSubmit, children: [
3786
+ /* @__PURE__ */ jsx(
3787
+ "input",
3788
+ {
3789
+ type: "text",
3790
+ className: "ecomiq-checkout-page__input",
3791
+ placeholder: "Discount code or gift card",
3792
+ value: couponCode,
3793
+ onChange: (e) => onCouponCodeChange(e.target.value),
3794
+ "aria-label": "Discount code"
3795
+ }
3796
+ ),
3797
+ /* @__PURE__ */ jsx(
3798
+ "button",
3799
+ {
3800
+ type: "submit",
3801
+ className: "ecomiq-checkout-page__discount-apply",
3802
+ disabled: !couponCode.trim() || couponBusy,
3803
+ children: "Apply"
3804
+ }
3805
+ )
3806
+ ] }),
3807
+ couponError ? /* @__PURE__ */ jsx("p", { className: "ecomiq-checkout-page__field-error", children: couponError }) : null,
3808
+ couponCodes.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "ecomiq-checkout-page__coupon-tags", children: couponCodes.map((code) => /* @__PURE__ */ jsxs("li", { children: [
3809
+ /* @__PURE__ */ jsx("span", { children: code }),
3810
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => onRemoveCoupon(code), "aria-label": `Remove ${code}`, children: "\xD7" })
3811
+ ] }, code)) }) : null,
3812
+ /* @__PURE__ */ jsxs("dl", { className: "ecomiq-checkout-page__totals", children: [
3813
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__totals-row", children: [
3814
+ /* @__PURE__ */ jsx("dt", { children: "Subtotal" }),
3815
+ /* @__PURE__ */ jsx("dd", { children: formatCurrency(subtotal, currency) })
3816
+ ] }),
3817
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__totals-row", children: [
3818
+ /* @__PURE__ */ jsx("dt", { children: "Shipping" }),
3819
+ /* @__PURE__ */ jsx("dd", { children: shipping > 0 ? formatCurrency(shipping, currency) : shipping === 0 ? "Free" : "\u2014" })
3820
+ ] }),
3821
+ discount > 0 ? /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__totals-row", children: [
3822
+ /* @__PURE__ */ jsx("dt", { children: "Discount" }),
3823
+ /* @__PURE__ */ jsxs("dd", { children: [
3824
+ "-",
3825
+ formatCurrency(discount, currency)
3826
+ ] })
3827
+ ] }) : null,
3828
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__totals-row", children: [
3829
+ /* @__PURE__ */ jsx("dt", { children: "Taxes" }),
3830
+ /* @__PURE__ */ jsx("dd", { children: tax > 0 ? formatCurrency(tax, currency) : "\u2014" })
3831
+ ] }),
3832
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__totals-row ecomiq-checkout-page__totals-row--total", children: [
3833
+ /* @__PURE__ */ jsx("dt", { children: "Total" }),
3834
+ /* @__PURE__ */ jsxs("dd", { children: [
3835
+ /* @__PURE__ */ jsx("span", { className: "ecomiq-checkout-page__total-currency", children: currency }),
3836
+ formatCurrency(total, currency)
3837
+ ] })
3838
+ ] })
3839
+ ] })
3840
+ ] });
3841
+ }
3842
+ function Block({
3843
+ className = "",
3844
+ style
3845
+ }) {
3846
+ return /* @__PURE__ */ jsx(
3847
+ "div",
3848
+ {
3849
+ className: `ecomiq-checkout-page__skeleton-block${className ? ` ${className}` : ""}`,
3850
+ style,
3851
+ "aria-hidden": true
3852
+ }
3853
+ );
3854
+ }
3855
+ function CheckoutPageSkeleton({ header }) {
3856
+ return /* @__PURE__ */ jsxs(
3857
+ "div",
3858
+ {
3859
+ className: "ecomiq-checkout-page ecomiq-checkout-page--skeleton",
3860
+ "aria-busy": "true",
3861
+ "aria-label": "Loading checkout",
3862
+ children: [
3863
+ header,
3864
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__layout", children: [
3865
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__main-wrap", children: [
3866
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3867
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__section-head", children: [
3868
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-title" }),
3869
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-link" })
3870
+ ] }),
3871
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" }),
3872
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-checkbox" })
3873
+ ] }),
3874
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3875
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-title" }),
3876
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" }),
3877
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-row", children: [
3878
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field ecomiq-checkout-page__skeleton-field--half" }),
3879
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field ecomiq-checkout-page__skeleton-field--half" })
3880
+ ] }),
3881
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" }),
3882
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" }),
3883
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" }),
3884
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-row", children: [
3885
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field ecomiq-checkout-page__skeleton-field--third" }),
3886
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field ecomiq-checkout-page__skeleton-field--third" }),
3887
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field ecomiq-checkout-page__skeleton-field--third" })
3888
+ ] }),
3889
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-field" })
3890
+ ] }),
3891
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3892
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-title" }),
3893
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-option" }),
3894
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-option" })
3895
+ ] }),
3896
+ /* @__PURE__ */ jsxs("section", { className: "ecomiq-checkout-page__section", children: [
3897
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-title" }),
3898
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-option" }),
3899
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-option" })
3900
+ ] }),
3901
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-button" })
3902
+ ] }),
3903
+ /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__summary-wrap", children: /* @__PURE__ */ jsxs("aside", { className: "ecomiq-checkout-page__summary", children: [
3904
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-summary-item", children: [
3905
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-thumb" }),
3906
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-summary-body", children: [
3907
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line" }),
3908
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line ecomiq-checkout-page__skeleton-line--short" })
3909
+ ] }),
3910
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-price" })
3911
+ ] }),
3912
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-coupon", children: [
3913
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-coupon-input" }),
3914
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-coupon-btn" })
3915
+ ] }),
3916
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-totals", children: [
3917
+ Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-total-row", children: [
3918
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line ecomiq-checkout-page__skeleton-line--short" }),
3919
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line ecomiq-checkout-page__skeleton-line--xs" })
3920
+ ] }, i)),
3921
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__skeleton-total-row ecomiq-checkout-page__skeleton-total-row--final", children: [
3922
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line" }),
3923
+ /* @__PURE__ */ jsx(Block, { className: "ecomiq-checkout-page__skeleton-line ecomiq-checkout-page__skeleton-line--price" })
3924
+ ] })
3925
+ ] })
3926
+ ] }) })
3927
+ ] })
3928
+ ]
3929
+ }
3930
+ );
3931
+ }
3932
+
3933
+ // src/react/pages/checkout-page/lib/cart-mappers.ts
3934
+ function mapApiItemsToCartItems(items) {
3935
+ if (!items?.length) return [];
3936
+ return items.map((raw) => {
3937
+ const item = raw;
3938
+ const price = Number(item.unitPrice);
3939
+ const quantity = Number(item.quantity);
3940
+ const variantId = String(item.variantId ?? "");
3941
+ if (!Number.isFinite(price) || !Number.isFinite(quantity) || !variantId) return null;
3942
+ return {
3943
+ id: item.id,
3944
+ title: item.title,
3945
+ image: String(item.thumbnail ?? ""),
3946
+ size: String(item.variantLabel ?? "\u2014"),
3947
+ price,
3948
+ quantity,
3949
+ variantId,
3950
+ variantSku: item.variantSku ?? void 0,
3951
+ variantLabel: item.variantLabel ?? void 0
3952
+ };
3953
+ }).filter(Boolean);
3954
+ }
3955
+ function shippingValuesFromCartAddress(cartData) {
3956
+ const addr = cartData.shippingAddress;
3957
+ if (!addr) return void 0;
3958
+ const geo = addr.geo;
3959
+ return {
3960
+ address: addr.address1,
3961
+ zipCode: addr.postalCode ?? "",
3962
+ countryCode: addr.countryCode ?? "PE",
3963
+ departmentCode: geo?.departmentCode ?? "",
3964
+ departmentName: "",
3965
+ provinceCode: geo?.provinceCode ?? "",
3966
+ provinceName: addr.province ?? "",
3967
+ districtCode: geo?.districtCode ?? "",
3968
+ districtName: addr.district ?? addr.city ?? ""
3969
+ };
3970
+ }
3971
+
3972
+ // src/react/pages/checkout-page/lib/cart-sync.ts
3973
+ var checkoutReadQueryKey = (cartId) => ["storefront", "cart", cartId, "checkout"];
3974
+ function cartItemsSignature(items) {
3975
+ return items.map((i) => `${i.variantId ?? i.id}:${i.quantity}`).sort().join("|");
3976
+ }
3977
+ function apiCartItemsFromResponse(cart) {
3978
+ return mapApiItemsToCartItems(cart?.items);
3979
+ }
3980
+ function groupCartQuantitiesByVariant(items) {
3981
+ const map = /* @__PURE__ */ new Map();
3982
+ for (const item of items) {
3983
+ const variantId = item.variantId ?? item.id;
3984
+ map.set(variantId, (map.get(variantId) ?? 0) + Math.max(0, item.quantity));
3985
+ }
3986
+ return map;
3987
+ }
3988
+ function groupApiLinesByVariant(items) {
3989
+ const map = /* @__PURE__ */ new Map();
3990
+ for (const item of items) {
3991
+ const variantId = item.variantId ?? item.id;
3992
+ const lines = map.get(variantId) ?? [];
3993
+ lines.push(item);
3994
+ map.set(variantId, lines);
3995
+ }
3996
+ return map;
3997
+ }
3998
+ function findCartReconciliationActions(local, api) {
3999
+ const actions = [];
4000
+ const localQty = groupCartQuantitiesByVariant(local);
4001
+ const apiLinesByVariant = groupApiLinesByVariant(api);
4002
+ const variantIds = /* @__PURE__ */ new Set([
4003
+ ...localQty.keys(),
4004
+ ...apiLinesByVariant.keys()
4005
+ ]);
4006
+ for (const variantId of variantIds) {
4007
+ const targetQty = localQty.get(variantId) ?? 0;
4008
+ const apiLines = apiLinesByVariant.get(variantId) ?? [];
4009
+ const apiQty = apiLines.reduce((sum, line) => sum + line.quantity, 0);
4010
+ if (targetQty > apiQty) {
4011
+ actions.push({
4012
+ action: "add",
4013
+ variantId,
4014
+ quantity: targetQty - apiQty
4015
+ });
4016
+ continue;
4017
+ }
4018
+ if (targetQty >= apiQty) continue;
4019
+ let excess = apiQty - targetQty;
4020
+ for (const line of [...apiLines].reverse()) {
4021
+ if (excess <= 0) break;
4022
+ if (line.quantity <= excess) {
4023
+ actions.push({ action: "remove", itemId: line.id });
4024
+ excess -= line.quantity;
4025
+ } else {
4026
+ actions.push({
4027
+ action: "update",
4028
+ itemId: line.id,
4029
+ quantity: line.quantity - excess
4030
+ });
4031
+ excess = 0;
4032
+ }
4033
+ }
4034
+ }
4035
+ return actions;
4036
+ }
4037
+ function areCartSignaturesEqual(a, b) {
4038
+ return cartItemsSignature(a) === cartItemsSignature(b);
4039
+ }
4040
+ function cartSessionSignature(cartTokenId, items) {
4041
+ return `${cartTokenId ?? ""}|${cartItemsSignature(items)}`;
4042
+ }
4043
+ function readCartCheckoutStatus(cart) {
4044
+ if (!cart) return null;
4045
+ const status = cart.status ?? null;
4046
+ return typeof status === "string" && status.trim() ? status.trim() : null;
4047
+ }
4048
+ function isCheckoutCartAlreadyPurchased(cart, localCartItemCount) {
4049
+ if (localCartItemCount > 0) return false;
4050
+ const status = readCartCheckoutStatus(cart);
4051
+ if (!status) return false;
4052
+ return status.toLowerCase() === "inprogress";
4053
+ }
4054
+ function useCartListener({
4055
+ cartId,
4056
+ enabled,
4057
+ isReconciling,
4058
+ checkoutReady
4059
+ }) {
4060
+ const localCart = useCart((s) => s.cart);
4061
+ const cartTokenId = useCart((s) => s.cartTokenId);
4062
+ const [cartChangedExternally, setCartChangedExternally] = useState(false);
4063
+ const baselineRef = useRef(null);
4064
+ useEffect(() => {
4065
+ baselineRef.current = null;
4066
+ setCartChangedExternally(false);
4067
+ }, [cartId]);
4068
+ useEffect(() => {
4069
+ if (!enabled || !checkoutReady || isReconciling) return;
4070
+ const sig = cartSessionSignature(cartTokenId ?? cartId, localCart);
4071
+ if (baselineRef.current === null) {
4072
+ baselineRef.current = sig;
4073
+ return;
4074
+ }
4075
+ if (sig !== baselineRef.current) {
4076
+ setCartChangedExternally(true);
4077
+ }
4078
+ }, [
4079
+ cartId,
4080
+ cartTokenId,
4081
+ checkoutReady,
4082
+ enabled,
4083
+ isReconciling,
4084
+ localCart
4085
+ ]);
4086
+ const reloadCheckout = useCallback(() => {
4087
+ if (typeof window !== "undefined") {
4088
+ window.location.reload();
4089
+ }
4090
+ }, []);
4091
+ return {
4092
+ cartChangedExternally,
4093
+ reloadCheckout
4094
+ };
4095
+ }
4096
+
4097
+ // src/react/pages/checkout-page/hooks/use-checkout-session.ts
4098
+ function useCheckoutSession(cartId) {
4099
+ const queryClient = useQueryClient();
4100
+ const storeId = useStore((s) => s.data?.store?.id ?? "");
4101
+ const currency = useStore((s) => s.data?.store?.currency ?? "PEN");
4102
+ const { setCartTokenId, clearCartSession, cart: localCart } = useCart(
4103
+ useShallow((s) => ({
4104
+ setCartTokenId: s.setCartTokenId,
4105
+ clearCartSession: s.clearCartSession,
4106
+ cart: s.cart
4107
+ }))
4108
+ );
4109
+ const [checkoutAlreadyPurchased, setCheckoutAlreadyPurchased] = useState(false);
4110
+ const skipCartTokenBindRef = useRef(false);
4111
+ useEffect(() => {
4112
+ skipCartTokenBindRef.current = false;
4113
+ setCheckoutAlreadyPurchased(false);
4114
+ }, [cartId]);
4115
+ const {
4116
+ useGetCartCheckout,
4117
+ useUpdateCartBuyer,
4118
+ useUpdateCartAddresses,
4119
+ useGetShippingOptions,
4120
+ usePutCartShippingMethod,
4121
+ useCheckoutCart,
4122
+ useAddCartCoupon,
4123
+ useRemoveCartCoupon,
4124
+ useAddCartItem,
4125
+ useUpdateCartItem,
4126
+ useDeleteCartItem,
4127
+ useUploadPaymentReceipt
4128
+ } = useStoreCart();
4129
+ const checkoutQuery = useGetCartCheckout(cartId);
4130
+ const updateBuyer = useUpdateCartBuyer();
4131
+ const updateAddresses = useUpdateCartAddresses();
4132
+ const putShippingMethod = usePutCartShippingMethod();
4133
+ const checkoutCartMutation = useCheckoutCart();
4134
+ const addCartCouponMutation = useAddCartCoupon();
4135
+ const removeCartCouponMutation = useRemoveCartCoupon();
4136
+ const addCartItemMutation = useAddCartItem();
4137
+ const updateCartItemMutation = useUpdateCartItem();
4138
+ const deleteCartItemMutation = useDeleteCartItem();
4139
+ const uploadPaymentReceiptMutation = useUploadPaymentReceipt();
4140
+ const cartData = checkoutQuery.data?.cart;
4141
+ const paymentMethods = checkoutQuery.data?.paymentMethods?.methods ?? [];
4142
+ useEffect(() => {
4143
+ if (!checkoutQuery.isSuccess || !cartData) return;
4144
+ if (!isCheckoutCartAlreadyPurchased(cartData, localCart.length)) return;
4145
+ if (skipCartTokenBindRef.current) return;
4146
+ skipCartTokenBindRef.current = true;
4147
+ setCheckoutAlreadyPurchased(true);
4148
+ clearCartSession();
4149
+ }, [
4150
+ cartData,
4151
+ checkoutQuery.isSuccess,
4152
+ clearCartSession,
4153
+ localCart.length
4154
+ ]);
4155
+ useEffect(() => {
4156
+ if (skipCartTokenBindRef.current) return;
4157
+ setCartTokenId(cartId);
4158
+ }, [cartId, setCartTokenId]);
4159
+ const [contact, setContact] = useState({
4160
+ email: "",
4161
+ marketingOptIn: true,
4162
+ firstName: "",
4163
+ lastName: "",
4164
+ company: "",
4165
+ address: "",
4166
+ address2: "",
4167
+ city: "",
4168
+ province: "",
4169
+ postalCode: "",
4170
+ phone: "",
4171
+ countryCode: "PE",
4172
+ departmentCode: "",
4173
+ departmentName: "",
4174
+ provinceCode: "",
4175
+ provinceName: "",
4176
+ districtCode: "",
4177
+ districtName: ""
4178
+ });
4179
+ const [billingChoice, setBillingChoice] = useState("same_as_shipping");
4180
+ const [selectedShippingKey, setSelectedShippingKey] = useState(null);
4181
+ const [selectedPaymentCode, setSelectedPaymentCode] = useState(null);
4182
+ const [providerPaymentCompleted, setProviderPaymentCompleted] = useState(false);
4183
+ const [couponCode, setCouponCode] = useState("");
4184
+ const [couponError, setCouponError] = useState(null);
4185
+ const [formError, setFormError] = useState(null);
4186
+ const [isReconciling, setIsReconciling] = useState(false);
4187
+ const hydratedRef = useRef(false);
4188
+ useEffect(() => {
4189
+ if (!cartData || hydratedRef.current) return;
4190
+ hydratedRef.current = true;
4191
+ const ship = shippingValuesFromCartAddress(cartData);
4192
+ setContact((c) => ({
4193
+ ...c,
4194
+ email: cartData.email ?? c.email,
4195
+ firstName: cartData.firstName ?? c.firstName,
4196
+ lastName: cartData.lastName ?? c.lastName,
4197
+ phone: cartData.phone ?? c.phone,
4198
+ address: ship?.address ?? c.address,
4199
+ postalCode: ship?.zipCode ?? c.postalCode,
4200
+ province: ship?.provinceName ?? c.province,
4201
+ city: ship?.districtName ?? c.city,
4202
+ countryCode: ship?.countryCode ?? c.countryCode,
4203
+ departmentCode: ship?.departmentCode ?? c.departmentCode,
4204
+ departmentName: ship?.departmentName ?? c.departmentName,
4205
+ provinceCode: ship?.provinceCode ?? c.provinceCode,
4206
+ provinceName: ship?.provinceName ?? c.provinceName,
4207
+ districtCode: ship?.districtCode ?? c.districtCode,
4208
+ districtName: ship?.districtName ?? c.districtName
4209
+ }));
4210
+ }, [cartData]);
4211
+ const postalCodeForRates = contact.postalCode.trim();
4212
+ const shippingOptionsQuery = useGetShippingOptions(
4213
+ cartId,
4214
+ postalCodeForRates || void 0,
4215
+ !!postalCodeForRates
4216
+ );
4217
+ const shippingFlat = useMemo(() => {
4218
+ const out = [];
4219
+ for (const group of shippingOptionsQuery.data?.groups ?? []) {
4220
+ for (const rate of group.rates ?? []) {
4221
+ out.push({
4222
+ key: `${group.sellerId ?? ""}::${rate.rateId}`,
4223
+ group,
4224
+ rate
4225
+ });
4226
+ }
4227
+ }
4228
+ return out;
4229
+ }, [shippingOptionsQuery.data?.groups]);
4230
+ const apiCartItems = useMemo(
4231
+ () => apiCartItemsFromResponse(cartData),
4232
+ [cartData]
4233
+ );
4234
+ const cartsReconciled = useMemo(
4235
+ () => areCartSignaturesEqual(localCart, apiCartItems),
4236
+ [localCart, apiCartItems]
4237
+ );
4238
+ const uiCartItems = useMemo(() => {
4239
+ if (cartsReconciled && apiCartItems.length > 0) return apiCartItems;
4240
+ if (localCart.length > 0) return localCart;
4241
+ return apiCartItems;
4242
+ }, [apiCartItems, cartsReconciled, localCart]);
4243
+ const reconcileAttemptRef = useRef(null);
4244
+ const isReconcilingRef = useRef(false);
4245
+ const localSubtotal = useMemo(
4246
+ () => localCart.reduce((sum, item) => sum + item.price * item.quantity, 0),
4247
+ [localCart]
4248
+ );
4249
+ const subtotal = cartsReconciled ? cartData?.totals?.subtotal ?? localSubtotal : localSubtotal;
4250
+ const shipping = cartsReconciled ? cartData?.totals?.shippingTotal ?? 0 : 0;
4251
+ const discount = cartsReconciled ? cartData?.totals?.discountTotal ?? 0 : 0;
4252
+ const tax = cartsReconciled ? cartData?.totals?.taxTotal ?? 0 : 0;
4253
+ const total = cartsReconciled ? cartData?.totals?.total ?? subtotal + shipping + tax - discount : localSubtotal;
4254
+ const mergeCartIntoCheckoutCache = useCallback(
4255
+ (next) => {
4256
+ queryClient.setQueryData(
4257
+ checkoutReadQueryKey(cartId),
4258
+ (prev) => !prev ? { cart: next, paymentMethods: { methods: [] } } : { ...prev, cart: next }
4259
+ );
4260
+ },
4261
+ [queryClient, cartId]
4262
+ );
4263
+ useEffect(() => {
4264
+ reconcileAttemptRef.current = null;
4265
+ }, [cartId]);
4266
+ useEffect(() => {
4267
+ if (!checkoutQuery.isSuccess || !cartData) return;
4268
+ if (isReconcilingRef.current) return;
4269
+ const apiItems = apiCartItemsFromResponse(cartData);
4270
+ if (localCart.length === 0 && apiItems.length === 0) return;
4271
+ if (areCartSignaturesEqual(localCart, apiItems)) return;
4272
+ const reconcileActions = findCartReconciliationActions(localCart, apiItems);
4273
+ if (reconcileActions.length === 0) return;
4274
+ const attemptKey = `${cartId}::${cartItemsSignature(localCart)}::${cartItemsSignature(apiItems)}`;
4275
+ if (reconcileAttemptRef.current === attemptKey) return;
4276
+ reconcileAttemptRef.current = attemptKey;
4277
+ isReconcilingRef.current = true;
4278
+ setIsReconciling(true);
4279
+ void (async () => {
4280
+ try {
4281
+ const applyCartResponse = (updatedCart) => {
4282
+ mergeCartIntoCheckoutCache(updatedCart);
4283
+ };
4284
+ for (const action of reconcileActions) {
4285
+ if (action.action === "remove" || action.action === "update") {
4286
+ try {
4287
+ const updatedCart = action.action === "remove" ? await deleteCartItemMutation.mutateAsync({
4288
+ cartId,
4289
+ itemId: action.itemId
4290
+ }) : await updateCartItemMutation.mutateAsync({
4291
+ cartId,
4292
+ itemId: action.itemId,
4293
+ data: { quantity: action.quantity }
4294
+ });
4295
+ applyCartResponse(updatedCart);
4296
+ } catch {
4297
+ }
4298
+ }
4299
+ }
4300
+ for (const action of reconcileActions) {
4301
+ if (action.action !== "add") continue;
4302
+ try {
4303
+ const updatedCart = await addCartItemMutation.mutateAsync({
4304
+ cartId,
4305
+ variantId: action.variantId,
4306
+ quantity: action.quantity
4307
+ });
4308
+ applyCartResponse(updatedCart);
4309
+ } catch {
4310
+ }
4311
+ }
4312
+ await checkoutQuery.refetch();
4313
+ } finally {
4314
+ isReconcilingRef.current = false;
4315
+ setIsReconciling(false);
4316
+ }
4317
+ })();
4318
+ }, [
4319
+ addCartItemMutation,
4320
+ cartData,
4321
+ cartId,
4322
+ checkoutQuery,
4323
+ deleteCartItemMutation,
4324
+ localCart,
4325
+ mergeCartIntoCheckoutCache,
4326
+ updateCartItemMutation
4327
+ ]);
4328
+ const saveContactAndDelivery = useCallback(async () => {
4329
+ setFormError(null);
4330
+ const buyerCart = await updateBuyer.mutateAsync({
4331
+ cartId,
4332
+ data: {
4333
+ email: contact.email,
4334
+ firstName: contact.firstName,
4335
+ lastName: contact.lastName,
4336
+ phone: contact.phone
4337
+ }
4338
+ });
4339
+ mergeCartIntoCheckoutCache(buyerCart);
4340
+ const countryCode = (contact.countryCode || "PE").toUpperCase();
4341
+ const districtName = contact.districtName || contact.city;
4342
+ const provinceName = contact.provinceName || contact.province;
4343
+ const baseAddress = {
4344
+ name: contact.address,
4345
+ address1: contact.address,
4346
+ city: districtName,
4347
+ countryCode,
4348
+ company: contact.company || null,
4349
+ address2: contact.address2 || null,
4350
+ province: provinceName,
4351
+ postalCode: contact.postalCode,
4352
+ district: districtName,
4353
+ phone: contact.phone || null,
4354
+ latitude: null,
4355
+ longitude: null,
4356
+ geo: {
4357
+ departmentCode: contact.departmentCode || "",
4358
+ provinceCode: contact.provinceCode || "",
4359
+ districtCode: contact.districtCode || ""
4360
+ }
4361
+ };
4362
+ const updatedCart = await updateAddresses.mutateAsync({
4363
+ cartId,
4364
+ data: {
4365
+ shippingAddress: baseAddress,
4366
+ billingAddress: billingChoice === "same_as_shipping" ? baseAddress : baseAddress
4367
+ }
4368
+ });
4369
+ mergeCartIntoCheckoutCache(updatedCart);
4370
+ await checkoutQuery.refetch();
4371
+ }, [
4372
+ billingChoice,
4373
+ cartId,
4374
+ contact,
4375
+ mergeCartIntoCheckoutCache,
4376
+ updateAddresses,
4377
+ updateBuyer,
4378
+ checkoutQuery
4379
+ ]);
4380
+ const confirmShipping = useCallback(
4381
+ async (selection) => {
4382
+ const updatedCart = await putShippingMethod.mutateAsync({
4383
+ cartId,
4384
+ data: {
4385
+ rateId: selection.rate.rateId,
4386
+ shippingMethodId: selection.rate.shippingMethodId,
4387
+ serviceCode: selection.rate.serviceCode ?? null,
4388
+ sellerId: selection.group.sellerId ?? null,
4389
+ shippingProfileId: selection.group.shippingProfileId ?? null,
4390
+ locationId: null,
4391
+ pickupPointId: null,
4392
+ scheduledDate: null,
4393
+ scheduledTime: null
4394
+ }
4395
+ });
4396
+ mergeCartIntoCheckoutCache(updatedCart);
4397
+ },
4398
+ [cartId, mergeCartIntoCheckoutCache, putShippingMethod]
4399
+ );
4400
+ const handleApplyCoupon = useCallback(async () => {
4401
+ const code = couponCode.trim();
4402
+ if (!code) return;
4403
+ setCouponError(null);
4404
+ try {
4405
+ const nextCart = await addCartCouponMutation.mutateAsync({ cartId, data: { code } });
4406
+ mergeCartIntoCheckoutCache(nextCart);
4407
+ setCouponCode("");
4408
+ } catch (error) {
4409
+ setCouponError(error instanceof Error ? error.message : "No se pudo aplicar el cup\xF3n.");
4410
+ }
4411
+ }, [addCartCouponMutation, cartId, couponCode, mergeCartIntoCheckoutCache]);
4412
+ const handleRemoveCoupon = useCallback(
4413
+ async (code) => {
4414
+ setCouponError(null);
4415
+ try {
4416
+ const nextCart = await removeCartCouponMutation.mutateAsync({ cartId, code });
4417
+ mergeCartIntoCheckoutCache(nextCart);
4418
+ } catch (error) {
4419
+ setCouponError(error instanceof Error ? error.message : "No se pudo remover el cup\xF3n.");
4420
+ }
4421
+ },
4422
+ [cartId, mergeCartIntoCheckoutCache, removeCartCouponMutation]
4423
+ );
4424
+ const externalRef = `checkout-${cartId}`;
4425
+ const checkoutCartMutate = checkoutCartMutation.mutate;
4426
+ const checkoutCartMutateAsync = checkoutCartMutation.mutateAsync;
4427
+ const checkoutPaymentInitKeyRef = useRef(null);
4428
+ useEffect(() => {
4429
+ checkoutPaymentInitKeyRef.current = null;
4430
+ }, [cartId]);
4431
+ const initProviderCheckout = useCallback(
4432
+ (paymentMethodCode) => {
4433
+ const method = paymentMethods.find((m) => m.code === paymentMethodCode);
4434
+ if (!method || !methodUsesProviderCheckoutUi(method)) return;
4435
+ const dedupeKey = `${cartId}:${paymentMethodCode}`;
4436
+ if (checkoutPaymentInitKeyRef.current === dedupeKey) return;
4437
+ checkoutPaymentInitKeyRef.current = dedupeKey;
4438
+ checkoutCartMutate({
4439
+ cartId,
4440
+ data: { paymentMethodCode, externalRef }
4441
+ });
4442
+ },
4443
+ [cartId, checkoutCartMutate, externalRef, paymentMethods]
4444
+ );
4445
+ const selectPaymentMethod = useCallback(
4446
+ (paymentMethodCode) => {
4447
+ setSelectedPaymentCode(paymentMethodCode);
4448
+ setProviderPaymentCompleted(false);
4449
+ initProviderCheckout(paymentMethodCode);
4450
+ },
4451
+ [initProviderCheckout]
4452
+ );
4453
+ const payNow = useCallback(
4454
+ async (options) => {
4455
+ setFormError(null);
4456
+ try {
4457
+ await saveContactAndDelivery();
4458
+ if (selectedShippingKey) {
4459
+ const picked = shippingFlat.find((o) => o.key === selectedShippingKey);
4460
+ if (picked) await confirmShipping({ group: picked.group, rate: picked.rate });
4461
+ }
4462
+ const code = selectedPaymentCode ?? paymentMethods[0]?.code;
4463
+ if (!code) {
4464
+ setFormError("Selecciona un m\xE9todo de pago.");
4465
+ return;
4466
+ }
4467
+ const method = paymentMethods.find((m) => m.code === code);
4468
+ const usesProviderUi = method ? methodUsesProviderCheckoutUi(method) : false;
4469
+ if (usesProviderUi) {
4470
+ if (!providerPaymentCompleted) {
4471
+ setFormError("Completa el pago con Stripe o Mercado Pago antes de continuar.");
4472
+ return;
4473
+ }
4474
+ const existing = checkoutCartMutation.data;
4475
+ const postedCode = checkoutCartMutation.variables?.data.paymentMethodCode ?? null;
4476
+ if (existing && postedCode === code) {
4477
+ return existing;
4478
+ }
4479
+ }
4480
+ const result = await checkoutCartMutateAsync({
4481
+ cartId,
4482
+ data: {
4483
+ paymentMethodCode: code,
4484
+ externalRef,
4485
+ ...options?.receiptUrl ? { receiptUrl: options.receiptUrl } : {}
4486
+ }
4487
+ });
4488
+ return result;
4489
+ } catch (error) {
4490
+ setFormError(error instanceof Error ? error.message : "No se pudo completar el pago.");
4491
+ throw error;
4492
+ }
4493
+ },
4494
+ [
4495
+ checkoutCartMutation.data,
4496
+ checkoutCartMutation.variables?.data.paymentMethodCode,
4497
+ confirmShipping,
4498
+ checkoutCartMutateAsync,
4499
+ cartId,
4500
+ externalRef,
4501
+ paymentMethods,
4502
+ providerPaymentCompleted,
4503
+ saveContactAndDelivery,
4504
+ selectedPaymentCode,
4505
+ selectedShippingKey,
4506
+ shippingFlat
4507
+ ]
4508
+ );
4509
+ const checkoutReady = checkoutQuery.isSuccess && !checkoutQuery.isLoading && !isReconciling;
4510
+ const { cartChangedExternally, reloadCheckout } = useCartListener({
4511
+ cartId,
4512
+ enabled: Boolean(cartId.trim()),
4513
+ isReconciling,
4514
+ checkoutReady
4515
+ });
4516
+ return {
4517
+ storeId,
4518
+ currency,
4519
+ cartId,
4520
+ checkoutQuery,
4521
+ cartData,
4522
+ uiCartItems,
4523
+ cartsReconciled,
4524
+ isReconciling,
4525
+ cartChangedExternally,
4526
+ checkoutAlreadyPurchased,
4527
+ reloadCheckout,
4528
+ contact,
4529
+ setContact,
4530
+ billingChoice,
4531
+ setBillingChoice,
4532
+ selectedShippingKey,
4533
+ setSelectedShippingKey,
4534
+ selectedPaymentCode,
4535
+ setSelectedPaymentCode,
4536
+ selectPaymentMethod,
4537
+ providerPaymentCompleted,
4538
+ setProviderPaymentCompleted,
4539
+ payNow,
4540
+ couponCode,
4541
+ setCouponCode,
4542
+ couponError,
4543
+ formError,
4544
+ handleApplyCoupon,
4545
+ handleRemoveCoupon,
4546
+ shippingOptionsQuery,
4547
+ shippingFlat,
4548
+ paymentMethods,
4549
+ subtotal,
4550
+ shipping,
4551
+ discount,
4552
+ tax,
4553
+ total,
4554
+ checkoutCartMutation,
4555
+ checkoutPaymentResponse: checkoutCartMutation.data,
4556
+ checkoutPaymentMethodCode: checkoutCartMutation.variables?.data.paymentMethodCode ?? null,
4557
+ checkoutPaymentLoading: checkoutCartMutation.isPending,
4558
+ checkoutPaymentError: checkoutCartMutation.isError ? "Tuvimos problemas al cargar el m\xE9todo de pago. Int\xE9ntalo de nuevo." : null,
4559
+ uploadPaymentReceipt: uploadPaymentReceiptMutation.mutateAsync,
4560
+ addCartCouponMutation,
4561
+ removeCartCouponMutation,
4562
+ clearCartSession,
4563
+ saveContactAndDelivery,
4564
+ isSaving: isReconciling || updateBuyer.isPending || updateAddresses.isPending || putShippingMethod.isPending || uploadPaymentReceiptMutation.isPending || checkoutCartMutation.isPending
4565
+ };
4566
+ }
4567
+ function DefaultLink({ href, className, children }) {
4568
+ return /* @__PURE__ */ jsx("a", { href, className, children });
4569
+ }
4570
+ function CheckoutPage({
4571
+ cartId,
4572
+ storeName: storeNameProp,
4573
+ logoUrl,
4574
+ logoHref = "/",
4575
+ signInHref,
4576
+ homeHref = "/",
4577
+ onPaymentSuccess,
4578
+ getProcessingUrl,
4579
+ Link: LinkComponent = DefaultLink
4580
+ }) {
4581
+ const Link = LinkComponent;
4582
+ const brandingName = useStore((s) => s.data?.store?.name);
4583
+ const logoFromCms = useStore(
4584
+ (s) => s.data?.cms?.settings?.branding?.logoUrl
4585
+ );
4586
+ const storeName = storeNameProp ?? brandingName ?? "Store";
4587
+ const resolvedLogo = logoUrl ?? logoFromCms;
4588
+ const session = useCheckoutSession(cartId);
4589
+ const {
4590
+ shippingFlat,
4591
+ selectedShippingKey,
4592
+ setSelectedShippingKey,
4593
+ paymentMethods,
4594
+ selectedPaymentCode,
4595
+ selectPaymentMethod
4596
+ } = session;
4597
+ useEffect(() => {
4598
+ if (!shippingFlat.length || selectedShippingKey) return;
4599
+ setSelectedShippingKey(shippingFlat[0].key);
4600
+ }, [shippingFlat, selectedShippingKey, setSelectedShippingKey]);
4601
+ useEffect(() => {
4602
+ if (!paymentMethods.length || selectedPaymentCode) return;
4603
+ const first = paymentMethods.find((m) => m.isDefault) ?? paymentMethods[0];
4604
+ if (first) selectPaymentMethod(first.code);
4605
+ }, [paymentMethods, selectedPaymentCode, selectPaymentMethod]);
4606
+ const shippingOptions = useMemo(
4607
+ () => session.shippingFlat.map((o) => ({
4608
+ key: o.key,
4609
+ title: o.rate.name ?? "Shipping",
4610
+ subtitle: o.rate.description ?? (o.rate.estimatedDeliveryDays != null ? `${o.rate.estimatedDeliveryDays} business days` : "Standard delivery"),
4611
+ price: Number(o.rate.price) || 0
4612
+ })),
4613
+ [session.shippingFlat]
4614
+ );
4615
+ const handlePaymentSubmissionResult = useCallback(
4616
+ (result) => {
4617
+ if (result.kind === "success") {
4618
+ session.clearCartSession();
4619
+ const url = getProcessingUrl?.(cartId, result.transactionId);
4620
+ if (url && typeof window !== "undefined") {
4621
+ window.location.assign(url);
4622
+ }
4623
+ return;
4624
+ }
4625
+ if (result.kind === "redirect") {
4626
+ session.clearCartSession();
4627
+ window.location.assign(result.url);
4628
+ return;
4629
+ }
4630
+ toast.error(result.message);
4631
+ },
4632
+ [cartId, getProcessingUrl, session]
4633
+ );
4634
+ const handlePayNow = async (options) => {
4635
+ try {
4636
+ const result = await session.payNow(options);
4637
+ if (!result) return;
4638
+ session.clearCartSession();
4639
+ if (onPaymentSuccess) {
4640
+ onPaymentSuccess(result);
4641
+ return;
4642
+ }
4643
+ const url = getProcessingUrl?.(
4644
+ cartId,
4645
+ result.payment?.transactionId ?? void 0
4646
+ );
4647
+ if (url && typeof window !== "undefined") {
4648
+ window.location.assign(url);
4649
+ }
4650
+ } catch {
4651
+ }
4652
+ };
4653
+ if (!cartId.trim()) {
4654
+ return /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page", children: /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__state", children: [
4655
+ /* @__PURE__ */ jsx("h1", { children: "Invalid checkout" }),
4656
+ /* @__PURE__ */ jsx("p", { children: "Missing cart ID in the URL." })
4657
+ ] }) });
4658
+ }
4659
+ const checkoutHeader = /* @__PURE__ */ jsx("header", { className: "ecomiq-checkout-page__top", children: /* @__PURE__ */ jsx(Link, { href: logoHref, className: "ecomiq-checkout-page__logo", children: resolvedLogo ? /* @__PURE__ */ jsx("img", { src: resolvedLogo, alt: storeName }) : storeName }) });
4660
+ if (session.checkoutQuery.isLoading || session.isReconciling) {
4661
+ return /* @__PURE__ */ jsx(CheckoutPageSkeleton, { header: checkoutHeader });
4662
+ }
4663
+ if (session.checkoutQuery.isError) {
4664
+ return /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page", children: [
4665
+ checkoutHeader,
4666
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__state", children: [
4667
+ /* @__PURE__ */ jsx("h1", { children: "Checkout unavailable" }),
4668
+ /* @__PURE__ */ jsx("p", { children: session.checkoutQuery.error?.message ?? "Could not load this cart. It may have expired." }),
4669
+ /* @__PURE__ */ jsx(Link, { href: homeHref, className: "ecomiq-checkout-page__link", children: "Return to store" })
4670
+ ] })
4671
+ ] });
4672
+ }
4673
+ if (session.checkoutAlreadyPurchased) {
4674
+ return /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page", children: [
4675
+ checkoutHeader,
4676
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__state", children: [
4677
+ /* @__PURE__ */ jsx("h1", { children: "Pedido ya realizado" }),
4678
+ /* @__PURE__ */ jsx("p", { children: "Este checkout ya fue completado. Tu bolsa se ha reiniciado para que puedas seguir comprando." }),
4679
+ /* @__PURE__ */ jsx(Link, { href: homeHref, className: "ecomiq-checkout-page__link", children: "Volver a la tienda" })
4680
+ ] })
4681
+ ] });
4682
+ }
4683
+ return /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page", "data-ecomiq-checkout-page": true, children: [
4684
+ checkoutHeader,
4685
+ session.cartChangedExternally ? /* @__PURE__ */ jsxs(
4686
+ "div",
4687
+ {
4688
+ className: "ecomiq-checkout-page__external-cart-banner",
4689
+ role: "alert",
4690
+ "aria-live": "polite",
4691
+ children: [
4692
+ /* @__PURE__ */ jsx("p", { children: "Tu carrito se acaba de actualizar." }),
4693
+ /* @__PURE__ */ jsx(
4694
+ "button",
4695
+ {
4696
+ type: "button",
4697
+ className: "ecomiq-checkout-page__external-cart-reload",
4698
+ onClick: session.reloadCheckout,
4699
+ children: "Recargar checkout"
4700
+ }
4701
+ )
4702
+ ]
4703
+ }
4704
+ ) : null,
4705
+ /* @__PURE__ */ jsxs("div", { className: "ecomiq-checkout-page__layout", children: [
4706
+ /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__main-wrap", children: /* @__PURE__ */ jsx(
4707
+ CheckoutMainForm,
4708
+ {
4709
+ storeId: session.storeId,
4710
+ contact: session.contact,
4711
+ onContactChange: (patch) => session.setContact((c) => ({ ...c, ...patch })),
4712
+ billingChoice: session.billingChoice,
4713
+ onBillingChange: session.setBillingChoice,
4714
+ shippingOptions,
4715
+ shippingLoading: session.shippingOptionsQuery.isLoading,
4716
+ shippingError: session.shippingOptionsQuery.isError ? session.shippingOptionsQuery.error?.message ?? "Could not load shipping options." : null,
4717
+ selectedShippingKey: session.selectedShippingKey,
4718
+ onSelectShipping: session.setSelectedShippingKey,
4719
+ paymentMethods: session.paymentMethods,
4720
+ selectedPaymentCode: session.selectedPaymentCode,
4721
+ selectPaymentMethod: session.selectPaymentMethod,
4722
+ providerPaymentCompleted: session.providerPaymentCompleted,
4723
+ setProviderPaymentCompleted: session.setProviderPaymentCompleted,
4724
+ checkoutPaymentResponse: session.checkoutPaymentResponse,
4725
+ checkoutPaymentMethodCode: session.checkoutPaymentMethodCode,
4726
+ checkoutPaymentLoading: session.checkoutPaymentLoading,
4727
+ checkoutPaymentError: session.checkoutPaymentError,
4728
+ onUploadReceipt: async (file) => {
4729
+ const uploaded = await session.uploadPaymentReceipt({ cartId, file });
4730
+ return { url: uploaded.url };
4731
+ },
4732
+ onPaymentSubmissionResult: handlePaymentSubmissionResult,
4733
+ currency: session.currency,
4734
+ formError: session.formError,
4735
+ isSaving: session.isSaving || session.cartChangedExternally,
4736
+ onPayNow: handlePayNow,
4737
+ signInHref,
4738
+ Link
4739
+ }
4740
+ ) }),
4741
+ /* @__PURE__ */ jsx("div", { className: "ecomiq-checkout-page__summary-wrap", children: /* @__PURE__ */ jsx(
4742
+ CheckoutOrderSummary,
4743
+ {
4744
+ items: session.uiCartItems,
4745
+ currency: session.currency,
4746
+ subtotal: session.subtotal,
4747
+ shipping: session.shipping,
4748
+ discount: session.discount,
4749
+ tax: session.tax,
4750
+ total: session.total,
4751
+ couponCodes: session.cartData?.promotionCodes ?? [],
4752
+ couponCode: session.couponCode,
4753
+ couponError: session.couponError,
4754
+ couponBusy: session.addCartCouponMutation.isPending || session.removeCartCouponMutation.isPending,
4755
+ onCouponCodeChange: session.setCouponCode,
4756
+ onApplyCoupon: () => void session.handleApplyCoupon(),
4757
+ onRemoveCoupon: (code) => void session.handleRemoveCoupon(code)
4758
+ }
4759
+ ) })
4760
+ ] })
4761
+ ] });
4762
+ }
1916
4763
  function buildOptionGroups(variants) {
1917
4764
  const map = /* @__PURE__ */ new Map();
1918
4765
  for (const v of variants) {
@@ -2022,6 +4869,6 @@ function ProductVariantSelector({
2022
4869
  ] });
2023
4870
  }
2024
4871
 
2025
- export { CustomerAddressSchema, CustomerAddressUpsertSchema, CustomerMeSchema, CustomerOrderDetailSchema, CustomerOrderListItemSchema, CustomerProfilePatchSchema, CustomerRegisterRequestSchema, EcomiqProvider, ProductVariantSelector, QueryProvider, StoreApiClient, StorefrontAuthProvider, addCartCoupon, checkoutCart, createCart, createCustomerAddress, createStoreApiClient, customerMeToProfilePatch, deleteCustomerAddress, ecomiqOAuthPasswordClient, getCart, getCartCheckout, getCartPaymentMethods, getCustomerAddresses, getCustomerMe, getCustomerOrder, getCustomerOrders, getSharedOrderDraft, getShippingOptions, getStoreApiBaseUrl, getStoreApiClient, getStorefrontCollectionBySlug, getStorefrontCollections, getStorefrontPageBySlug, getStorefrontPagePreview, getStorefrontPages, getStorefrontProductBySlug, getStorefrontProducts, isCartNotActiveApiError, patchCartAddresses, patchCartBuyer, patchCustomer, putCartShippingMethod, registerCustomer, removeCartCoupon, setClientStoreId, setServerRequestOrigin, setServerStoreId, signInWithEcomiqCredentials, storeApiClient, storefrontAccessTokenNeedsRefresh, storefrontSessionEndsSoon, updateCustomerAddress, uploadPaymentReceipt, useCart, useStore, useStoreCart, useStoreCollections, useStorePages, useStoreProducts, useStorefrontAuthClient, useStorefrontSession };
4872
+ export { CheckoutPage, CustomerAddressSchema, CustomerAddressUpsertSchema, CustomerMeSchema, CustomerOrderDetailSchema, CustomerOrderListItemSchema, CustomerProfilePatchSchema, CustomerRegisterRequestSchema, EcomiqProvider, ProductVariantSelector, QueryProvider, StoreApiClient, StorefrontAuthProvider, addCartCoupon, checkoutCart, createCart, createCustomerAddress, createStoreApiClient, customerMeToProfilePatch, deleteCustomerAddress, ecomiqOAuthPasswordClient, getCart, getCartCheckout, getCartPaymentMethods, getCustomerAddresses, getCustomerMe, getCustomerOrder, getCustomerOrders, getSharedOrderDraft, getShippingOptions, getStoreApiBaseUrl, getStoreApiClient, getStorefrontCollectionBySlug, getStorefrontCollections, getStorefrontPageBySlug, getStorefrontPagePreview, getStorefrontPages, getStorefrontProductBySlug, getStorefrontProducts, isCartNotActiveApiError, patchCartAddresses, patchCartBuyer, patchCustomer, putCartShippingMethod, registerCustomer, removeCartCoupon, setClientStoreId, setServerRequestOrigin, setServerStoreId, signInWithEcomiqCredentials, storeApiClient, storefrontAccessTokenNeedsRefresh, storefrontSessionEndsSoon, updateCustomerAddress, uploadPaymentReceipt, useCart, useCheckoutSession, useStore, useStoreCart, useStoreCollections, useStorePages, useStoreProducts, useStorefrontAuthClient, useStorefrontSession };
2026
4873
  //# sourceMappingURL=client.js.map
2027
4874
  //# sourceMappingURL=client.js.map