@ecomiq/storefront 2.1.4 → 3.0.0
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.
- package/LICENSE +21 -0
- package/README.md +150 -103
- package/dist/account-Dx4e3syi.js +258 -0
- package/dist/account-forms-AVk71ko7.js +39 -0
- package/dist/account-forms.d.ts +13 -0
- package/dist/account.d.ts +240 -0
- package/dist/address-defaults-BqjRhS82.js +14 -0
- package/dist/address-defaults.d.ts +11 -0
- package/dist/analytics/analytics-CG1Qagwl.js +148 -0
- package/dist/analytics/analytics.d.ts +1 -0
- package/dist/analytics/config-DJr-GRhs.js +62 -0
- package/dist/analytics/config.d.ts +22 -0
- package/dist/analytics/consent-B13rBpBs.js +57 -0
- package/dist/analytics/consent-banner-9QvRRy8v.js +239 -0
- package/dist/analytics/consent-banner.d.ts +20 -0
- package/dist/analytics/cookies-pLozllyB.js +100 -0
- package/dist/analytics/cookies.d.ts +6 -0
- package/dist/analytics/destinations-iECrlLIr.js +144 -0
- package/dist/analytics/events-Dt81tIp1.js +102 -0
- package/dist/analytics/events.d.ts +51 -0
- package/dist/analytics/tracker-p4yaoOyk.js +51 -0
- package/dist/api-cache-DsuIn5hX.js +159 -0
- package/dist/bank-accounts-DlEczQQ5.js +81 -0
- package/dist/bank-accounts.d.ts +4 -0
- package/dist/captcha-DAqaIx8m.js +117 -0
- package/dist/captcha.d.ts +34 -0
- package/dist/cart-D7DxZ2lD.js +30 -0
- package/dist/cart-actions-Bsub_FFG.js +116 -0
- package/dist/cart-actions.d.ts +15 -0
- package/dist/cart-drawer-B7PPsR69.js +22 -0
- package/dist/cart-drawer.d.ts +9 -0
- package/dist/cart-form-y9P1r_EX.js +81 -0
- package/dist/cart-form.d.ts +24 -0
- package/dist/cart-summary-ur2VWKr-.js +89 -0
- package/dist/cart-summary.d.ts +31 -0
- package/dist/cart.d.ts +4 -0
- package/dist/catalog-7gJ-l5hW.js +67 -0
- package/dist/catalog-hooks-B7ZP4wYY.js +312 -0
- package/dist/catalog-hooks.d.ts +111 -0
- package/dist/catalog.d.ts +5 -0
- package/dist/checkout-DVWSXANi.js +474 -0
- package/dist/checkout-form-CbOIdENC.js +131 -0
- package/dist/checkout-form.d.ts +20 -0
- package/dist/checkout.d.ts +86 -0
- package/dist/complaint-book-BvwLvfx0.js +117 -0
- package/dist/complaint-book.d.ts +62 -0
- package/dist/culqi-authentication-BGr20vAJ.js +204 -0
- package/dist/culqi-authentication.d.ts +15 -0
- package/dist/culqi-checkout-CTXpKgp_.js +55 -0
- package/dist/culqi-three-ds-HP3mfrvV.js +33 -0
- package/dist/culqi-three-ds.d.ts +29 -0
- package/dist/customer-avatar-CJXSDroK.js +12 -0
- package/dist/customer-avatar.d.ts +5 -0
- package/dist/customer-cookies-DHOgFAMV.js +45 -0
- package/dist/customer-csrf-C1oDX-Py.js +17 -0
- package/dist/customer-csrf.d.ts +3 -0
- package/dist/customer-document-fields-C1K-_DAD.js +70 -0
- package/dist/customer-document-fields.d.ts +9 -0
- package/dist/customer-login-form-C7AC6vXd.js +144 -0
- package/dist/customer-login-form.d.ts +17 -0
- package/dist/customer-registration-form-BEm_NEfP.js +93 -0
- package/dist/customer-registration-form.d.ts +8 -0
- package/dist/document-url-CGsAl5Tf.js +9 -0
- package/dist/documents-T1mzc_j8.js +38 -0
- package/dist/documents.d.ts +16 -0
- package/dist/entries/account.d.ts +11 -0
- package/dist/entries/account.js +10 -0
- package/dist/entries/analytics.d.ts +6 -0
- package/dist/entries/analytics.js +5 -0
- package/dist/entries/cart.d.ts +8 -0
- package/dist/entries/cart.js +7 -0
- package/dist/entries/checkout.d.ts +12 -0
- package/dist/entries/checkout.js +11 -0
- package/dist/entries/order.d.ts +11 -0
- package/dist/entries/order.js +11 -0
- package/dist/favicon-YpyhVJ9H.js +28 -0
- package/dist/favicon.d.ts +4 -0
- package/dist/form-BtQcbXlJ.js +18 -0
- package/dist/form-contracts-BNpHaTGJ.js +166 -0
- package/dist/form-contracts.d.ts +42 -0
- package/dist/form.d.ts +3 -0
- package/dist/hidden-CCWtOWKR.js +3 -0
- package/dist/hidden.d.ts +4 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +50 -0
- package/dist/invoice-fields-BG0HjL6T.js +103 -0
- package/dist/invoice-fields.d.ts +39 -0
- package/dist/links-kFxBZfdb.js +96 -0
- package/dist/links.d.ts +21 -0
- package/dist/mercadopago-checkout-DC7RXa8k.js +27 -0
- package/dist/mercadopago-dialog-UTQev0MG.js +180 -0
- package/dist/mercadopago-dialog.d.ts +21 -0
- package/dist/money-DtGOtDri.js +32 -0
- package/dist/money.d.ts +1 -0
- package/dist/optimistic-cart-BveVOHuh.js +53 -0
- package/dist/optimistic-cart.d.ts +16 -0
- package/dist/order-display-DTt5WBbc.js +112 -0
- package/dist/order-display.d.ts +20 -0
- package/dist/order-draft-DxV1Uhm3.js +38 -0
- package/dist/order-draft.d.ts +16 -0
- package/dist/order-pages-Dm6l5m0m.js +38 -0
- package/dist/order-pages.d.ts +12 -0
- package/dist/order-payment-continuation-D_d5PGA4.js +212 -0
- package/dist/order-payment-continuation.d.ts +10 -0
- package/dist/order-payment-in-review-x4gdLFHZ.js +65 -0
- package/dist/order-payment-in-review.d.ts +5 -0
- package/dist/order-status-BJXLJwxq.js +162 -0
- package/dist/order-status.d.ts +89 -0
- package/dist/order-view-9IlBg5AF.js +62 -0
- package/dist/order-view.d.ts +12 -0
- package/dist/page-action-Ctkf4xC6.js +7 -0
- package/dist/page-seo-a5FJl8x5.js +262 -0
- package/dist/page-seo.d.ts +34 -0
- package/dist/pages-Ca_Gt6mq.js +150 -0
- package/dist/pages.d.ts +45 -0
- package/dist/payment-dialog-frame-B-Q_xQ94.js +57 -0
- package/dist/payment-logo-BoPaGJc_.js +46 -0
- package/dist/payment-logo-svgs-By9lDTLK.js +20 -0
- package/dist/payment-logo.d.ts +11 -0
- package/dist/payment-logos-BYvdwYyJ.js +23 -0
- package/dist/payment-methods-B8ocTgFZ.js +73 -0
- package/dist/payment-methods.d.ts +58 -0
- package/dist/payment-return-5cjypwIw.js +7 -0
- package/dist/place-CmW4hBWY.js +13 -0
- package/dist/place.d.ts +4 -0
- package/dist/preview-BiIBif3C.js +427 -0
- package/dist/preview-address-Cf0sJ-9p.js +21 -0
- package/dist/preview-cart-Dg2CVktS.js +376 -0
- package/dist/product-preview-BspMAecJ.js +51 -0
- package/dist/product-preview.d.ts +5 -0
- package/dist/product-variants-BNDHvs1y.js +46 -0
- package/dist/product-variants.d.ts +12 -0
- package/dist/public-pages-XtwlaLwt.js +194 -0
- package/dist/public-pages.d.ts +67 -0
- package/dist/registration-CpDcv8ql.js +91 -0
- package/dist/registration.d.ts +12 -0
- package/dist/request-security-CRsRMgwj.js +76 -0
- package/dist/rich-text-M-Ju8RL4.js +9 -0
- package/dist/rich-text.d.ts +5 -0
- package/dist/route-text-DcJw2SsK.js +9 -0
- package/dist/route-text.d.ts +4 -0
- package/dist/section-preview-CmsMl3yu.js +83 -0
- package/dist/section-preview.d.ts +12 -0
- package/dist/sections/account-addresses.d.ts +18 -0
- package/dist/sections/account-addresses.js +375 -0
- package/dist/sections/account-order.d.ts +12 -0
- package/dist/sections/account-order.js +592 -0
- package/dist/sections/account-orders.d.ts +8 -0
- package/dist/sections/account-orders.js +359 -0
- package/dist/sections/account-profile.d.ts +16 -0
- package/dist/sections/account-profile.js +123 -0
- package/dist/sections/checkout.d.ts +24 -0
- package/dist/sections/checkout.js +963 -0
- package/dist/sections/complaint-book.d.ts +8 -0
- package/dist/sections/complaint-book.js +538 -0
- package/dist/sections/design-system.d.ts +1 -0
- package/dist/sections/design-system.js +310 -0
- package/dist/sections/draft-invoice.d.ts +20 -0
- package/dist/sections/draft-invoice.js +158 -0
- package/dist/sections/order-tracking.d.ts +19 -0
- package/dist/sections/order-tracking.js +141 -0
- package/dist/sections-CNUMWTF_.js +77 -0
- package/dist/sections.d.ts +19 -0
- package/dist/seo-GpDRhAAA.js +78 -0
- package/dist/session-CKvmFJyg.js +379 -0
- package/dist/session.d.ts +24 -0
- package/dist/settings-B0NO2A6Y.js +78 -0
- package/dist/settings.d.ts +51 -0
- package/dist/source-marker-DhqSkW7n.js +4 -0
- package/dist/sources-B-3JFJfb.js +46 -0
- package/dist/sources.d.ts +7 -0
- package/dist/store-8Q-_LFrQ.js +152 -0
- package/dist/store-contact--hY6CoFb.js +19 -0
- package/dist/store-contact.d.ts +6 -0
- package/dist/store.d.ts +17 -0
- package/dist/storefront-language-DrMjVbmk.js +29 -0
- package/dist/storefront-language.d.ts +14 -0
- package/dist/storefront-text-D25ae1qf.js +11 -0
- package/dist/storefront-text-en-ljjjSS4q.js +1030 -0
- package/dist/storefront-text-pt-BtHaJLcp.js +1030 -0
- package/dist/storefront-text.d.ts +4 -0
- package/dist/stripe-dialog-Ev9s3Z62.js +396 -0
- package/dist/stripe-dialog.d.ts +30 -0
- package/dist/telemetry-HuZXWBPi.js +114 -0
- package/dist/telemetry.d.ts +10 -0
- package/dist/templates-CAqoNyTW.js +40 -0
- package/dist/templates.d.ts +15 -0
- package/dist/urls-CpGQPxvf.js +71 -0
- package/dist/urls.d.ts +18 -0
- package/dist/use-checkout-CZcxXJXi.js +42 -0
- package/dist/use-checkout-payment-9R-zacrJ.js +80 -0
- package/dist/use-checkout-payment.d.ts +18 -0
- package/dist/use-checkout.d.ts +36 -0
- package/dist/use-culqi-checkout-CrjLAipU.js +109 -0
- package/dist/use-order-payment-BKIz_IO0.js +45 -0
- package/dist/use-order-payment.d.ts +18 -0
- package/dist/use-payment-token-CErx-tN-.js +105 -0
- package/dist/vite-payment-logos-kziu7wKb.js +27 -0
- package/dist/vite-payment-logos.d.ts +24 -0
- package/dist/vite-public-assets-DW2fgtVb.js +209 -0
- package/dist/vite-public-assets.d.ts +29 -0
- package/dist/vite-sections-DTBr0-Kg.js +464 -0
- package/dist/vite-sections.d.ts +21 -0
- package/dist/vite-theme-ui-BMO-CDi3.js +41 -0
- package/dist/vite-theme-ui.d.ts +10 -0
- package/dist/vite.d.ts +36 -0
- package/dist/vite.js +127 -0
- package/dist/voucher-payment-CVFDZ1L8.js +66 -0
- package/dist/worker-CNi-gzCu.js +86 -0
- package/dist/worker.d.ts +27 -0
- package/package.json +100 -76
- package/src/sections/account-addresses.tsx +215 -0
- package/src/sections/account-order.tsx +424 -0
- package/src/sections/account-orders.tsx +259 -0
- package/src/sections/account-profile.tsx +70 -0
- package/src/sections/checkout.tsx +586 -0
- package/src/sections/complaint-book.tsx +325 -0
- package/src/sections/design-system.tsx +146 -0
- package/src/sections/draft-invoice.tsx +105 -0
- package/src/sections/order-tracking.tsx +81 -0
- package/src/vite-client.d.ts +4 -0
- package/bin/ecomiq.mjs +0 -179
- package/public/design-bridge.js +0 -318
- package/src/api-proxy.ts +0 -194
- package/src/auth/create-storefront-auth.ts +0 -94
- package/src/auth/ecomiq-oauth-password-client.ts +0 -26
- package/src/auth/ecomiq-oauth-password-constants.ts +0 -24
- package/src/auth/ecomiq-oauth-password-plugin.ts +0 -294
- package/src/auth/ecomiq-oauth-password-types.ts +0 -24
- package/src/auth/ecomiq-storefront-sign-in.ts +0 -44
- package/src/auth/env.ts +0 -7
- package/src/auth/secure-cookies.ts +0 -23
- package/src/auth/storefront-auth-base-url.ts +0 -117
- package/src/auth/storefront-auth.ts +0 -7
- package/src/cart-session.ts +0 -239
- package/src/client.ts +0 -48
- package/src/codegen.mjs +0 -801
- package/src/components/account/customer-addresses-panel.tsx +0 -678
- package/src/components/account/customer-order-detail-panel.tsx +0 -285
- package/src/components/account/customer-orders-panel.tsx +0 -192
- package/src/components/account/customer-profile-panel.tsx +0 -379
- package/src/components/checkout/cart-sync.ts +0 -143
- package/src/components/checkout/checkout-contact-section.tsx +0 -76
- package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
- package/src/components/checkout/checkout-form-controls.tsx +0 -139
- package/src/components/checkout/checkout-line-items.tsx +0 -43
- package/src/components/checkout/checkout-order-summary.tsx +0 -165
- package/src/components/checkout/checkout-payment-section.tsx +0 -212
- package/src/components/checkout/checkout-session-view.tsx +0 -564
- package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
- package/src/components/checkout/checkout-shipping-section.tsx +0 -98
- package/src/components/checkout/checkout-states.tsx +0 -73
- package/src/components/checkout/checkout-step-card.tsx +0 -101
- package/src/components/checkout/checkout-steps.ts +0 -111
- package/src/components/checkout/form-schema.ts +0 -281
- package/src/components/checkout/format.ts +0 -15
- package/src/components/checkout/index.ts +0 -5
- package/src/components/checkout/map-customer-to-checkout.ts +0 -188
- package/src/components/checkout/types.ts +0 -41
- package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
- package/src/components/checkout/use-checkout-geo.ts +0 -50
- package/src/components/checkout/use-checkout-session.ts +0 -640
- package/src/components/hero.tsx +0 -291
- package/src/config.d.ts +0 -94
- package/src/config.mjs +0 -146
- package/src/format-money.ts +0 -31
- package/src/health.ts +0 -90
- package/src/hooks/index.ts +0 -9
- package/src/hooks/recently-viewed.ts +0 -125
- package/src/index.ts +0 -349
- package/src/link.tsx +0 -2
- package/src/pages/account/account-page-skeleton.tsx +0 -69
- package/src/pages/account/account-page-view.tsx +0 -270
- package/src/pages/account/account-shell.tsx +0 -101
- package/src/pages/account/parse-account-route.ts +0 -36
- package/src/pages/account.tsx +0 -16
- package/src/pages/api.$.ts +0 -20
- package/src/pages/api.auth.$.ts +0 -16
- package/src/pages/checkout.$checkoutId.tsx +0 -60
- package/src/pages/checkout.tsx +0 -31
- package/src/pages/pages.$pageSlug.tsx +0 -74
- package/src/pages/thank-you.tsx +0 -53
- package/src/providers/auth.tsx +0 -96
- package/src/providers/cart.tsx +0 -275
- package/src/providers/ecomiq.ts +0 -137
- package/src/providers/index.ts +0 -26
- package/src/proxy-api.ts +0 -20
- package/src/public-config.ts +0 -24
- package/src/review-submission.ts +0 -89
- package/src/runtime/context.ts +0 -2
- package/src/runtime/default-layout.tsx +0 -64
- package/src/runtime/head.ts +0 -149
- package/src/runtime/page.tsx +0 -143
- package/src/runtime/postcss-browser-stub.mjs +0 -5
- package/src/server-config-store.ts +0 -35
- package/src/server.ts +0 -286
- package/src/styles.css +0 -76
- package/src/ui/badge.tsx +0 -32
- package/src/ui/button.tsx +0 -31
- package/src/ui/card.tsx +0 -31
- package/src/ui/carousel.tsx +0 -218
- package/src/ui/cn.ts +0 -6
- package/src/ui/index.ts +0 -8
- package/src/ui/separator.tsx +0 -6
- package/src/ui/skeleton.tsx +0 -6
- package/src/ui/storefront-error.tsx +0 -49
- package/src/utils.ts +0 -36
- package/src/vite-inline.mjs +0 -263
- package/templates/__root.tsx +0 -83
- package/templates/router.tsx +0 -19
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { CustomerCsrfField } from "./customer-csrf-C1oDX-Py.js";
|
|
2
|
+
import { usePageAction } from "./page-action-Ctkf4xC6.js";
|
|
3
|
+
import { Form, useFetcher, useSubmit } from "react-router";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
// src/checkout-form.tsx
|
|
7
|
+
const CHECKOUT_ACTION = "/checkout";
|
|
8
|
+
const AUTOSAVE_MS = 700;
|
|
9
|
+
const GATHERED = /* @__PURE__ */ new Set([
|
|
10
|
+
"contact",
|
|
11
|
+
"delivery",
|
|
12
|
+
"shipping"
|
|
13
|
+
]);
|
|
14
|
+
function gathered(own) {
|
|
15
|
+
const data = new FormData(own);
|
|
16
|
+
for (const form of document.querySelectorAll("form[data-checkout-intent]")) {
|
|
17
|
+
if (form === own || !GATHERED.has(form.dataset.checkoutIntent ?? "")) continue;
|
|
18
|
+
if (!form.reportValidity()) return null;
|
|
19
|
+
for (const [key, value] of new FormData(form)) if (key !== "intent" && !data.has(key)) data.append(key, value);
|
|
20
|
+
}
|
|
21
|
+
data.set("intent", "checkout");
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
function CheckoutForm({ intent, single = false, children, onChange, onClick, onSubmit, ...props }) {
|
|
25
|
+
const action = usePageAction(CHECKOUT_ACTION);
|
|
26
|
+
const fetcher = useFetcher();
|
|
27
|
+
const submit = useSubmit();
|
|
28
|
+
const timer = useRef(void 0);
|
|
29
|
+
useEffect(() => () => window.clearTimeout(timer.current), []);
|
|
30
|
+
const autosave = single && (intent === "delivery" || intent === "shipping");
|
|
31
|
+
const schedule = (form) => {
|
|
32
|
+
if (!autosave) return;
|
|
33
|
+
window.clearTimeout(timer.current);
|
|
34
|
+
timer.current = window.setTimeout(() => {
|
|
35
|
+
if (form.checkValidity()) fetcher.submit(form, {
|
|
36
|
+
method: "post",
|
|
37
|
+
action,
|
|
38
|
+
preventScrollReset: true
|
|
39
|
+
});
|
|
40
|
+
}, intent === "shipping" ? 0 : AUTOSAVE_MS);
|
|
41
|
+
};
|
|
42
|
+
const changed = (event) => {
|
|
43
|
+
onChange?.(event);
|
|
44
|
+
schedule(event.currentTarget);
|
|
45
|
+
};
|
|
46
|
+
const clicked = (event) => {
|
|
47
|
+
onClick?.(event);
|
|
48
|
+
if (event.target instanceof HTMLInputElement && event.target.type === "radio") schedule(event.currentTarget);
|
|
49
|
+
};
|
|
50
|
+
const sent = (event) => {
|
|
51
|
+
onSubmit?.(event);
|
|
52
|
+
if (!single || intent !== "pay" || event.defaultPrevented) return;
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
const data = gathered(event.currentTarget);
|
|
55
|
+
if (data === null) return;
|
|
56
|
+
submit(data, {
|
|
57
|
+
method: "post",
|
|
58
|
+
action,
|
|
59
|
+
encType: "multipart/form-data"
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
return /* @__PURE__ */ jsxs(Form, {
|
|
63
|
+
method: "post",
|
|
64
|
+
action,
|
|
65
|
+
encType: intent === "pay" ? "multipart/form-data" : void 0,
|
|
66
|
+
"data-checkout-intent": intent,
|
|
67
|
+
onChange: changed,
|
|
68
|
+
onClick: clicked,
|
|
69
|
+
onSubmit: sent,
|
|
70
|
+
...props,
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ jsx(CustomerCsrfField, {}),
|
|
73
|
+
/* @__PURE__ */ jsx("input", {
|
|
74
|
+
type: "hidden",
|
|
75
|
+
name: "intent",
|
|
76
|
+
value: intent
|
|
77
|
+
}),
|
|
78
|
+
children
|
|
79
|
+
]
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function OrderBumpForm({ bump, children, ...props }) {
|
|
83
|
+
const action = usePageAction(CHECKOUT_ACTION);
|
|
84
|
+
return /* @__PURE__ */ jsxs(Form, {
|
|
85
|
+
method: "post",
|
|
86
|
+
action,
|
|
87
|
+
...props,
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx(CustomerCsrfField, {}),
|
|
90
|
+
/* @__PURE__ */ jsx("input", {
|
|
91
|
+
type: "hidden",
|
|
92
|
+
name: "intent",
|
|
93
|
+
value: "bump"
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ jsx("input", {
|
|
96
|
+
type: "hidden",
|
|
97
|
+
name: "bumpId",
|
|
98
|
+
value: bump.id
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ jsx("input", {
|
|
101
|
+
type: "hidden",
|
|
102
|
+
name: "variantId",
|
|
103
|
+
value: bump.variantId
|
|
104
|
+
}),
|
|
105
|
+
children
|
|
106
|
+
]
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function PromoCodeForm({ remove, children, ...props }) {
|
|
110
|
+
const action = usePageAction(CHECKOUT_ACTION);
|
|
111
|
+
return /* @__PURE__ */ jsxs(Form, {
|
|
112
|
+
method: "post",
|
|
113
|
+
action,
|
|
114
|
+
...props,
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsx(CustomerCsrfField, {}),
|
|
117
|
+
/* @__PURE__ */ jsx("input", {
|
|
118
|
+
type: "hidden",
|
|
119
|
+
name: "intent",
|
|
120
|
+
value: remove === void 0 ? "promo" : "promo-remove"
|
|
121
|
+
}),
|
|
122
|
+
remove === void 0 ? null : /* @__PURE__ */ jsx("input", {
|
|
123
|
+
type: "hidden",
|
|
124
|
+
name: "code",
|
|
125
|
+
value: remove
|
|
126
|
+
}),
|
|
127
|
+
children
|
|
128
|
+
]
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
export { CHECKOUT_ACTION, CheckoutForm, OrderBumpForm, PromoCodeForm, gathered };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CheckoutIntent } from "./form-contracts.js";
|
|
2
|
+
import { FetcherFormProps } from "react-router";
|
|
3
|
+
type FormProps = Omit<FetcherFormProps, "action" | "method" | "encType">;
|
|
4
|
+
export type CheckoutFormProps = FormProps & {
|
|
5
|
+
intent: Exclude<CheckoutIntent, "bump" | "promo" | "promo-remove" | "checkout">;
|
|
6
|
+
single?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type OrderBumpFormProps = FormProps & {
|
|
9
|
+
bump: {
|
|
10
|
+
id: string;
|
|
11
|
+
variantId: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export type PromoCodeFormProps = FormProps & {
|
|
15
|
+
remove?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function CheckoutForm({ intent, single, children, onChange, onClick, onSubmit, ...props }: CheckoutFormProps): import("react").JSX.Element;
|
|
18
|
+
export declare function OrderBumpForm({ bump, children, ...props }: OrderBumpFormProps): import("react").JSX.Element;
|
|
19
|
+
export declare function PromoCodeForm({ remove, children, ...props }: PromoCodeFormProps): import("react").JSX.Element;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AddressDefaults } from "./address-defaults.js";
|
|
2
|
+
import { PageAnalytics } from "./analytics/events.js";
|
|
3
|
+
import { readCountries } from "./store.js";
|
|
4
|
+
import { RouterContextProvider, ShouldRevalidateFunctionArgs } from "react-router";
|
|
5
|
+
import { CartCheckoutReadResponse, CustomerAddress, CustomerMe, ShippingOptionGroup, ShippingRate, StorefrontCart } from "@ecomiq/core";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
export type CheckoutStep = "contact" | "delivery" | "shipping" | "payment";
|
|
8
|
+
export type CheckoutRate = ShippingRate & {
|
|
9
|
+
value: string;
|
|
10
|
+
};
|
|
11
|
+
export type CheckoutShippingGroup = Omit<ShippingOptionGroup, "rates"> & {
|
|
12
|
+
field: string;
|
|
13
|
+
rates: CheckoutRate[];
|
|
14
|
+
};
|
|
15
|
+
export type CheckoutPaymentMethod = CartCheckoutReadResponse["paymentMethods"]["methods"][number];
|
|
16
|
+
export type CheckoutData = {
|
|
17
|
+
countryCode: string;
|
|
18
|
+
documentCountries: {
|
|
19
|
+
code: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}[];
|
|
22
|
+
language: string;
|
|
23
|
+
cart: StorefrontCart;
|
|
24
|
+
methods: CheckoutPaymentMethod[];
|
|
25
|
+
bumps: CartCheckoutReadResponse["orderBumps"];
|
|
26
|
+
signedIn: boolean;
|
|
27
|
+
me: CustomerMe | null;
|
|
28
|
+
address: CustomerAddress | null;
|
|
29
|
+
countries: Awaited<ReturnType<typeof readCountries>>;
|
|
30
|
+
shipping: CheckoutShippingGroup[];
|
|
31
|
+
analytics: PageAnalytics;
|
|
32
|
+
};
|
|
33
|
+
declare const CheckoutAuthenticationSchema: z.ZodObject<{
|
|
34
|
+
authentication: z.ZodObject<{
|
|
35
|
+
payment: z.ZodObject<{
|
|
36
|
+
actionUrl: z.ZodNullable<z.ZodString>;
|
|
37
|
+
isCaptured: z.ZodBoolean;
|
|
38
|
+
transactionId: z.ZodNullable<z.ZodString>;
|
|
39
|
+
externalId: z.ZodNullable<z.ZodString>;
|
|
40
|
+
actionKind: z.ZodEnum<{
|
|
41
|
+
embedded: "embedded";
|
|
42
|
+
none: "none";
|
|
43
|
+
qrCode: "qrCode";
|
|
44
|
+
redirect: "redirect";
|
|
45
|
+
threeDS: "threeDS";
|
|
46
|
+
voucher: "voucher";
|
|
47
|
+
}>;
|
|
48
|
+
providerId: z.ZodNullable<z.ZodString>;
|
|
49
|
+
publicConfiguration: z.ZodObject<{
|
|
50
|
+
publishableKey: z.ZodOptional<z.ZodString>;
|
|
51
|
+
publicKey: z.ZodOptional<z.ZodString>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
clientSecret: z.ZodNullable<z.ZodString>;
|
|
54
|
+
qrCode: z.ZodNullable<z.ZodString>;
|
|
55
|
+
receiptUrl: z.ZodNullable<z.ZodString>;
|
|
56
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
57
|
+
paymentMethodCode: z.ZodNullable<z.ZodString>;
|
|
58
|
+
amount: z.ZodNullable<z.ZodNumber>;
|
|
59
|
+
currencyCode: z.ZodNullable<z.ZodString>;
|
|
60
|
+
voucherCode: z.ZodNullable<z.ZodString>;
|
|
61
|
+
qrImageUrl: z.ZodNullable<z.ZodString>;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
orderStatusUrl: z.ZodString;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type CheckoutAuthenticationData = z.infer<typeof CheckoutAuthenticationSchema>;
|
|
67
|
+
export type CheckoutActionData = {
|
|
68
|
+
error: string;
|
|
69
|
+
promo: boolean;
|
|
70
|
+
code?: string;
|
|
71
|
+
traceId?: string;
|
|
72
|
+
} | CheckoutAuthenticationData;
|
|
73
|
+
export type CheckoutAddressDefaults = AddressDefaults;
|
|
74
|
+
export declare function shouldRevalidateCheckout({ actionResult, defaultShouldRevalidate }: ShouldRevalidateFunctionArgs): boolean;
|
|
75
|
+
export declare function needsShipping(cart: StorefrontCart): boolean;
|
|
76
|
+
export declare function checkoutProgress(cart: StorefrontCart): {
|
|
77
|
+
contact: boolean;
|
|
78
|
+
delivery: boolean;
|
|
79
|
+
shipping: boolean;
|
|
80
|
+
};
|
|
81
|
+
export declare function checkoutStep(cart: StorefrontCart, edit: string | null): CheckoutStep;
|
|
82
|
+
export declare function checkoutAddressDefaults(cart: StorefrontCart, address: CustomerAddress | null, countryCode: string): CheckoutAddressDefaults;
|
|
83
|
+
export declare function defaultPaymentMethod(cart: StorefrontCart, methods: CheckoutPaymentMethod[]): string | undefined;
|
|
84
|
+
export declare function loadCheckout(request: Request, context: Readonly<RouterContextProvider>): Promise<CheckoutData>;
|
|
85
|
+
export declare function checkoutAction(request: Request, context: Readonly<RouterContextProvider>): Promise<import("react-router").UNSAFE_DataWithResponseInit<CheckoutActionData> | Response>;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { captchaResponse } from "./captcha-DAqaIx8m.js";
|
|
2
|
+
import { COMPLAINT_DOCUMENT_TYPES, identityDocumentError } from "./documents-T1mzc_j8.js";
|
|
3
|
+
import { optional, text } from "./form-BtQcbXlJ.js";
|
|
4
|
+
import { rejectCrossOriginAction } from "./request-security-CRsRMgwj.js";
|
|
5
|
+
import { found, readDocumentCountries, store } from "./store-8Q-_LFrQ.js";
|
|
6
|
+
import { data } from "react-router";
|
|
7
|
+
import { ApiError, COMPLAINT_BOOK_ATTACHMENT_TYPES, COMPLAINT_BOOK_MAX_ATTACHMENTS, COMPLAINT_BOOK_MAX_ATTACHMENT_BYTES, ComplaintBookEntryInputSchema } from "@ecomiq/core";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
// src/complaint-book.ts
|
|
10
|
+
const TOO_MANY_ATTACHMENTS = "Adjunta hasta 3 archivos.";
|
|
11
|
+
const INVALID_ATTACHMENT = "Adjunta fotos (JPG, PNG o WebP) o PDF de hasta 5 MB.";
|
|
12
|
+
const COMPLAINT_BOOK_ERRORS = {
|
|
13
|
+
"ComplaintBook.Captcha": "Completa la verificación de seguridad.",
|
|
14
|
+
"ComplaintBook.Unavailable": "El Libro de Reclamaciones no está disponible en esta tienda.",
|
|
15
|
+
"ComplaintBook.TooManyAttachments": TOO_MANY_ATTACHMENTS,
|
|
16
|
+
"ComplaintBook.InvalidAttachment": INVALID_ATTACHMENT,
|
|
17
|
+
"ComplaintBook.AttachmentUploadFailed": "No pudimos guardar los adjuntos. Intenta de nuevo o envía sin ellos."
|
|
18
|
+
};
|
|
19
|
+
const ValidationProblemSchema = z.object({ fieldErrors: z.record(z.string(), z.array(z.string())) });
|
|
20
|
+
function complaintBookLinks(settings) {
|
|
21
|
+
if (settings.store.countryCode !== "PE") return [];
|
|
22
|
+
return [{
|
|
23
|
+
label: "Libro de Reclamaciones",
|
|
24
|
+
url: "/libro-de-reclamaciones"
|
|
25
|
+
}];
|
|
26
|
+
}
|
|
27
|
+
function complaintBookNumber(number) {
|
|
28
|
+
return `N.° ${String(number).padStart(6, "0")}`;
|
|
29
|
+
}
|
|
30
|
+
function complaintBookAttachmentError(files) {
|
|
31
|
+
if (files.length > COMPLAINT_BOOK_MAX_ATTACHMENTS) return TOO_MANY_ATTACHMENTS;
|
|
32
|
+
if (files.some((file) => file.size === 0 || file.size > COMPLAINT_BOOK_MAX_ATTACHMENT_BYTES || !COMPLAINT_BOOK_ATTACHMENT_TYPES.includes(file.type))) return INVALID_ATTACHMENT;
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
async function loadComplaintBook(context) {
|
|
36
|
+
const client = store(context);
|
|
37
|
+
const [book, settings] = await Promise.all([found(client.getComplaintBook()), client.getSettings()]);
|
|
38
|
+
return {
|
|
39
|
+
book,
|
|
40
|
+
countryCode: settings.store.countryCode,
|
|
41
|
+
language: settings.store.language,
|
|
42
|
+
timeZone: settings.store.timeZone,
|
|
43
|
+
countries: await readDocumentCountries(client)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function failure(error, status = 400) {
|
|
47
|
+
return data({ error }, { status });
|
|
48
|
+
}
|
|
49
|
+
function person(form, prefix) {
|
|
50
|
+
return {
|
|
51
|
+
name: text(form, `${prefix}Name`),
|
|
52
|
+
address: text(form, `${prefix}Address`),
|
|
53
|
+
phone: text(form, `${prefix}Phone`),
|
|
54
|
+
email: text(form, `${prefix}Email`)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function complaintEntry(form) {
|
|
58
|
+
if (form.get("confirmed") !== "on") return "Confirma que los datos son verdaderos.";
|
|
59
|
+
const amount = optional(form, "itemAmount");
|
|
60
|
+
const parsed = ComplaintBookEntryInputSchema.safeParse({
|
|
61
|
+
type: text(form, "type"),
|
|
62
|
+
consumer: {
|
|
63
|
+
...person(form, "consumer"),
|
|
64
|
+
documentType: text(form, "documentType"),
|
|
65
|
+
documentNumber: text(form, "documentNumber"),
|
|
66
|
+
documentCountryCode: text(form, "documentCountryCode")
|
|
67
|
+
},
|
|
68
|
+
guardian: form.get("minor") === "on" ? person(form, "guardian") : null,
|
|
69
|
+
item: {
|
|
70
|
+
kind: text(form, "itemKind"),
|
|
71
|
+
description: text(form, "itemDescription"),
|
|
72
|
+
amount: amount === null ? null : Number(amount)
|
|
73
|
+
},
|
|
74
|
+
orderNumber: optional(form, "orderNumber"),
|
|
75
|
+
detail: text(form, "detail"),
|
|
76
|
+
request: text(form, "request"),
|
|
77
|
+
confirmed: true
|
|
78
|
+
});
|
|
79
|
+
if (!parsed.success) return "Completa los datos obligatorios.";
|
|
80
|
+
const { documentType, documentNumber, documentCountryCode } = parsed.data.consumer;
|
|
81
|
+
const documentError = identityDocumentError(COMPLAINT_DOCUMENT_TYPES[documentType], documentCountryCode, documentNumber);
|
|
82
|
+
if (documentError !== null) return documentError;
|
|
83
|
+
return parsed.data;
|
|
84
|
+
}
|
|
85
|
+
function apiErrorMessage(error) {
|
|
86
|
+
const problem = ValidationProblemSchema.safeParse(error.body);
|
|
87
|
+
const codes = problem.success ? Object.values(problem.data.fieldErrors).flat() : [];
|
|
88
|
+
if (error.code !== void 0) codes.unshift(error.code);
|
|
89
|
+
return codes.flatMap((code) => COMPLAINT_BOOK_ERRORS[code] ?? [])[0];
|
|
90
|
+
}
|
|
91
|
+
async function complaintBookAction(request, context) {
|
|
92
|
+
const rejected = rejectCrossOriginAction(request);
|
|
93
|
+
if (rejected) return rejected;
|
|
94
|
+
const client = store(context);
|
|
95
|
+
const form = await request.formData();
|
|
96
|
+
const book = await found(client.getComplaintBook());
|
|
97
|
+
const token = captchaResponse(form, book.captcha.provider);
|
|
98
|
+
if (!token) return failure("Completa la verificación de seguridad.");
|
|
99
|
+
const sheet = complaintEntry(form);
|
|
100
|
+
if (typeof sheet === "string") return failure(sheet);
|
|
101
|
+
const files = form.getAll("files").filter((file) => file instanceof File && file.size > 0);
|
|
102
|
+
const attachmentError = complaintBookAttachmentError(files);
|
|
103
|
+
if (attachmentError) return failure(attachmentError);
|
|
104
|
+
try {
|
|
105
|
+
return {
|
|
106
|
+
entry: await client.createComplaintBookEntry(sheet, files, token),
|
|
107
|
+
sheet,
|
|
108
|
+
attachments: files.map((file) => file.name)
|
|
109
|
+
};
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (!(error instanceof ApiError) || error.status === 0 || error.status >= 500) return failure("No pudimos registrar tu reclamo. Intenta de nuevo.", 503);
|
|
112
|
+
let message = "Revisa los datos e intenta de nuevo.";
|
|
113
|
+
if (error.status === 429) message = "Espera un momento antes de volver a intentar.";
|
|
114
|
+
return failure(apiErrorMessage(error) ?? message, error.status);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export { complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, loadComplaintBook };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { RouterContextProvider } from "react-router";
|
|
2
|
+
import { ComplaintBook, ComplaintBookEntry, ComplaintBookEntryInput, StorefrontSettings } from "@ecomiq/core";
|
|
3
|
+
export type ComplaintBookLink = {
|
|
4
|
+
label: string;
|
|
5
|
+
url: string;
|
|
6
|
+
};
|
|
7
|
+
export type ComplaintBookData = {
|
|
8
|
+
book: ComplaintBook;
|
|
9
|
+
countryCode: string;
|
|
10
|
+
language: string;
|
|
11
|
+
timeZone: string;
|
|
12
|
+
countries: {
|
|
13
|
+
code: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
export type ComplaintBookActionData = {
|
|
18
|
+
error: string;
|
|
19
|
+
} | {
|
|
20
|
+
entry: ComplaintBookEntry;
|
|
21
|
+
sheet: ComplaintBookEntryInput;
|
|
22
|
+
attachments: string[];
|
|
23
|
+
};
|
|
24
|
+
export declare function complaintBookLinks(settings: StorefrontSettings): ComplaintBookLink[];
|
|
25
|
+
export declare function complaintBookNumber(number: number): string;
|
|
26
|
+
export declare function complaintBookAttachmentError(files: readonly File[]): string | null;
|
|
27
|
+
export declare function loadComplaintBook(context: Readonly<RouterContextProvider>): Promise<ComplaintBookData>;
|
|
28
|
+
export declare function complaintBookAction(request: Request, context: Readonly<RouterContextProvider>): Promise<import("react-router").UNSAFE_DataWithResponseInit<ComplaintBookActionData> | Response | {
|
|
29
|
+
entry: {
|
|
30
|
+
number: number;
|
|
31
|
+
filedOn: string;
|
|
32
|
+
responseDueOn: string;
|
|
33
|
+
};
|
|
34
|
+
sheet: {
|
|
35
|
+
type: "claim" | "complaint";
|
|
36
|
+
consumer: {
|
|
37
|
+
name: string;
|
|
38
|
+
address: string;
|
|
39
|
+
phone: string;
|
|
40
|
+
email: string;
|
|
41
|
+
documentType: "foreignId" | "nationalId" | "passport" | "taxId";
|
|
42
|
+
documentNumber: string;
|
|
43
|
+
documentCountryCode: string;
|
|
44
|
+
};
|
|
45
|
+
guardian: {
|
|
46
|
+
name: string;
|
|
47
|
+
address: string;
|
|
48
|
+
phone: string;
|
|
49
|
+
email: string;
|
|
50
|
+
} | null;
|
|
51
|
+
item: {
|
|
52
|
+
kind: "product" | "service";
|
|
53
|
+
description: string;
|
|
54
|
+
amount: number | null;
|
|
55
|
+
};
|
|
56
|
+
orderNumber: string | null;
|
|
57
|
+
detail: string;
|
|
58
|
+
request: string;
|
|
59
|
+
confirmed: true;
|
|
60
|
+
};
|
|
61
|
+
attachments: string[];
|
|
62
|
+
}>;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { useStorefrontLocale, useStorefrontText } from "./storefront-language-DrMjVbmk.js";
|
|
2
|
+
import { useCustomerCsrfToken } from "./customer-csrf-C1oDX-Py.js";
|
|
3
|
+
import { CulqiPaymentSourceSchema, culqiSourceKey, loadCulqiThreeDS } from "./culqi-three-ds-HP3mfrvV.js";
|
|
4
|
+
import { useNavigate, useSubmit } from "react-router";
|
|
5
|
+
import { PaymentAuthentication3DSSchema } from "@ecomiq/core";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { useEffect, useRef, useState } from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
// src/culqi-authentication.tsx
|
|
10
|
+
const StoredSourceSchema = CulqiPaymentSourceSchema.extend({
|
|
11
|
+
expiresAt: z.string().datetime({ offset: true }),
|
|
12
|
+
orderStatusUrl: z.string()
|
|
13
|
+
});
|
|
14
|
+
const AuthenticationMessageSchema = z.union([z.object({ parameters3DS: PaymentAuthentication3DSSchema }), z.object({ error: z.string() })]);
|
|
15
|
+
function useOrderAuthentication({ result, payment, orderStatusUrl }) {
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
let storage;
|
|
18
|
+
try {
|
|
19
|
+
storage = window.sessionStorage;
|
|
20
|
+
} catch {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
for (let index = storage.length - 1; index >= 0; index--) {
|
|
24
|
+
const key = storage.key(index);
|
|
25
|
+
if (key === null || !key.startsWith("ecomiq:culqi:")) continue;
|
|
26
|
+
let stored;
|
|
27
|
+
try {
|
|
28
|
+
stored = JSON.parse(storage.getItem(key) ?? "null");
|
|
29
|
+
} catch {
|
|
30
|
+
storage.removeItem(key);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const source = StoredSourceSchema.safeParse(stored);
|
|
34
|
+
if (!source.success || Date.parse(source.data.expiresAt) <= Date.now() || source.data.orderStatusUrl === orderStatusUrl && (payment?.actionKind !== "threeDS" || key !== culqiSourceKey(payment.transactionId ?? ""))) storage.removeItem(key);
|
|
35
|
+
}
|
|
36
|
+
if (result?.authenticatedTransactionId) storage.removeItem(culqiSourceKey(result.authenticatedTransactionId));
|
|
37
|
+
}, [
|
|
38
|
+
result?.authenticatedTransactionId,
|
|
39
|
+
payment?.actionKind,
|
|
40
|
+
payment?.transactionId,
|
|
41
|
+
orderStatusUrl
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
function CulqiAuthentication({ payment, orderStatusUrl, email, source, result }) {
|
|
45
|
+
const storefrontTranslate = useStorefrontText();
|
|
46
|
+
const { locale, timeZone } = useStorefrontLocale();
|
|
47
|
+
const expiry = new Intl.DateTimeFormat(locale, {
|
|
48
|
+
dateStyle: "medium",
|
|
49
|
+
timeStyle: "short",
|
|
50
|
+
timeZone
|
|
51
|
+
});
|
|
52
|
+
const submit = useSubmit();
|
|
53
|
+
const navigate = useNavigate();
|
|
54
|
+
const csrf = useCustomerCsrfToken();
|
|
55
|
+
const [error, setError] = useState(null);
|
|
56
|
+
const [retryable, setRetryable] = useState(false);
|
|
57
|
+
const [attempt, setAttempt] = useState(0);
|
|
58
|
+
const authenticationSubmission = useRef(null);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
authenticationSubmission.current = null;
|
|
61
|
+
let active = true;
|
|
62
|
+
let sent = false;
|
|
63
|
+
let reset;
|
|
64
|
+
let timer;
|
|
65
|
+
let receive;
|
|
66
|
+
const transactionId = payment.transactionId;
|
|
67
|
+
async function authenticate() {
|
|
68
|
+
if (transactionId === null || payment.expiresAt === null) throw new Error("No pudimos iniciar la autenticación de este pago.");
|
|
69
|
+
const key = culqiSourceKey(transactionId);
|
|
70
|
+
if (source !== null) window.sessionStorage.setItem(key, JSON.stringify({
|
|
71
|
+
...source,
|
|
72
|
+
expiresAt: payment.expiresAt,
|
|
73
|
+
orderStatusUrl
|
|
74
|
+
}));
|
|
75
|
+
let storedValue;
|
|
76
|
+
try {
|
|
77
|
+
storedValue = JSON.parse(window.sessionStorage.getItem(key) ?? "null");
|
|
78
|
+
} catch {
|
|
79
|
+
storedValue = null;
|
|
80
|
+
}
|
|
81
|
+
const stored = StoredSourceSchema.safeParse(storedValue);
|
|
82
|
+
if (!stored.success || stored.data.orderStatusUrl !== orderStatusUrl) throw new Error("La sesión de tu tarjeta terminó. Espera a que venza esta autenticación y vuelve al estado del pedido para intentar el pago.");
|
|
83
|
+
const remaining = Date.parse(stored.data.expiresAt) - Date.now();
|
|
84
|
+
if (remaining <= 0) {
|
|
85
|
+
window.sessionStorage.removeItem(key);
|
|
86
|
+
throw new Error("La autenticación venció. Vuelve al pedido para consultar las opciones de pago.");
|
|
87
|
+
}
|
|
88
|
+
if (window.location.pathname !== new URL(orderStatusUrl, window.location.href).pathname) {
|
|
89
|
+
navigate(orderStatusUrl, { replace: true });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!payment.publicConfiguration.publicKey || payment.amount === null || payment.currencyCode === null || !email) throw new Error("No pudimos iniciar la autenticación de este pago.");
|
|
93
|
+
setRetryable(true);
|
|
94
|
+
timer = window.setTimeout(() => {
|
|
95
|
+
active = false;
|
|
96
|
+
window.sessionStorage.removeItem(key);
|
|
97
|
+
reset?.();
|
|
98
|
+
setRetryable(false);
|
|
99
|
+
setError("La autenticación venció. Vuelve al pedido para consultar las opciones de pago.");
|
|
100
|
+
}, remaining);
|
|
101
|
+
const sdk = await loadCulqiThreeDS();
|
|
102
|
+
if (!active) return;
|
|
103
|
+
sdk.reset();
|
|
104
|
+
reset = () => sdk.reset();
|
|
105
|
+
sdk.publicKey = payment.publicConfiguration.publicKey;
|
|
106
|
+
sdk.settings = {
|
|
107
|
+
charge: {
|
|
108
|
+
totalAmount: Math.round(payment.amount * 100),
|
|
109
|
+
currency: payment.currencyCode,
|
|
110
|
+
returnUrl: window.location.href
|
|
111
|
+
},
|
|
112
|
+
card: { email }
|
|
113
|
+
};
|
|
114
|
+
receive = (event) => {
|
|
115
|
+
if (!active || sent || event.origin !== window.location.origin) return;
|
|
116
|
+
const response = AuthenticationMessageSchema.safeParse(event.data);
|
|
117
|
+
if (!response.success) return;
|
|
118
|
+
if ("error" in response.data) {
|
|
119
|
+
setError("No pudimos autenticar tu tarjeta. Intenta nuevamente.");
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
sent = true;
|
|
123
|
+
const form = new FormData();
|
|
124
|
+
form.set("intent", "authenticate");
|
|
125
|
+
form.set("transactionId", transactionId);
|
|
126
|
+
form.set("token", stored.data.token);
|
|
127
|
+
form.set("deviceSessionId", stored.data.deviceSessionId);
|
|
128
|
+
form.set("authentication3DS", JSON.stringify(response.data.parameters3DS));
|
|
129
|
+
if (csrf) form.set("__customer_csrf", csrf);
|
|
130
|
+
authenticationSubmission.current = form;
|
|
131
|
+
submit(form, {
|
|
132
|
+
method: "post",
|
|
133
|
+
action: orderStatusUrl,
|
|
134
|
+
encType: "multipart/form-data"
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
window.addEventListener("message", receive);
|
|
138
|
+
sdk.initAuthentication(stored.data.token);
|
|
139
|
+
}
|
|
140
|
+
setError(null);
|
|
141
|
+
setRetryable(false);
|
|
142
|
+
authenticate().catch((error) => {
|
|
143
|
+
if (active) setError(error instanceof Error ? error.message : "No pudimos autenticar tu tarjeta.");
|
|
144
|
+
});
|
|
145
|
+
return () => {
|
|
146
|
+
active = false;
|
|
147
|
+
window.clearTimeout(timer);
|
|
148
|
+
if (receive) window.removeEventListener("message", receive);
|
|
149
|
+
reset?.();
|
|
150
|
+
};
|
|
151
|
+
}, [
|
|
152
|
+
payment.transactionId,
|
|
153
|
+
payment.expiresAt,
|
|
154
|
+
payment.publicConfiguration.publicKey,
|
|
155
|
+
payment.amount,
|
|
156
|
+
payment.currencyCode,
|
|
157
|
+
orderStatusUrl,
|
|
158
|
+
email,
|
|
159
|
+
source,
|
|
160
|
+
csrf,
|
|
161
|
+
submit,
|
|
162
|
+
navigate,
|
|
163
|
+
attempt
|
|
164
|
+
]);
|
|
165
|
+
const failure = error ?? (result?.ok === false ? result.message : null);
|
|
166
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
167
|
+
className: "flex flex-col gap-4 rounded-lg border p-6",
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ jsx("p", {
|
|
170
|
+
role: "status",
|
|
171
|
+
children: storefrontTranslate("Confirma el pago con tu banco para completar el pedido.")
|
|
172
|
+
}),
|
|
173
|
+
payment.expiresAt ? /* @__PURE__ */ jsxs("p", { children: [
|
|
174
|
+
storefrontTranslate("La autenticación dura hasta 15 minutos y vence el"),
|
|
175
|
+
" ",
|
|
176
|
+
expiry.format(new Date(payment.expiresAt)),
|
|
177
|
+
"."
|
|
178
|
+
] }) : null,
|
|
179
|
+
failure ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
|
|
180
|
+
role: "alert",
|
|
181
|
+
children: failure
|
|
182
|
+
}), retryable ? /* @__PURE__ */ jsx("button", {
|
|
183
|
+
type: "button",
|
|
184
|
+
onClick: () => {
|
|
185
|
+
const form = authenticationSubmission.current;
|
|
186
|
+
if (form !== null) submit(form, {
|
|
187
|
+
method: "post",
|
|
188
|
+
action: orderStatusUrl,
|
|
189
|
+
encType: "multipart/form-data"
|
|
190
|
+
});
|
|
191
|
+
else setAttempt((value) => value + 1);
|
|
192
|
+
},
|
|
193
|
+
className: "underline",
|
|
194
|
+
children: authenticationSubmission.current === null ? "Reintentar autenticación" : "Reintentar confirmación"
|
|
195
|
+
}) : null] }) : null,
|
|
196
|
+
/* @__PURE__ */ jsx("a", {
|
|
197
|
+
href: orderStatusUrl,
|
|
198
|
+
className: "underline",
|
|
199
|
+
children: storefrontTranslate("Ver estado del pedido")
|
|
200
|
+
})
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
export { CulqiAuthentication, useOrderAuthentication };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CulqiPaymentSource } from "./culqi-three-ds.js";
|
|
2
|
+
import { OrderPaymentActionData } from "./order-status.js";
|
|
3
|
+
import { OrderPaymentStart } from "@ecomiq/core";
|
|
4
|
+
export declare function useOrderAuthentication({ result, payment, orderStatusUrl }: {
|
|
5
|
+
result: OrderPaymentActionData | undefined;
|
|
6
|
+
payment: OrderPaymentStart | null;
|
|
7
|
+
orderStatusUrl: string;
|
|
8
|
+
}): void;
|
|
9
|
+
export declare function CulqiAuthentication({ payment, orderStatusUrl, email, source, result }: {
|
|
10
|
+
payment: OrderPaymentStart;
|
|
11
|
+
orderStatusUrl: string;
|
|
12
|
+
email: string | null;
|
|
13
|
+
source: CulqiPaymentSource | null;
|
|
14
|
+
result?: OrderPaymentActionData;
|
|
15
|
+
}): import("react").JSX.Element;
|