@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,96 @@
|
|
|
1
|
+
import { Link, useRouteLoaderData } from "react-router";
|
|
2
|
+
import { catalogLinkKey } from "@ecomiq/core";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
// src/links.tsx
|
|
5
|
+
function linkKey(link) {
|
|
6
|
+
if (link.reference) return catalogLinkKey(link);
|
|
7
|
+
return link.url;
|
|
8
|
+
}
|
|
9
|
+
async function readStorefrontLayout({ client, links }) {
|
|
10
|
+
const layout = await client.getLayout(links);
|
|
11
|
+
return {
|
|
12
|
+
settings: layout.settings,
|
|
13
|
+
collections: layout.collections,
|
|
14
|
+
storefrontLinks: Object.fromEntries(links.map((link, index) => [linkKey(link), layout.links[index]?.url ?? link.url]))
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function readStorefrontLinks(client, links) {
|
|
18
|
+
if (links.length === 0) return {};
|
|
19
|
+
try {
|
|
20
|
+
const resolved = await client.getLinks(links);
|
|
21
|
+
return Object.fromEntries(links.map((link, index) => [linkKey(link), resolved[index]?.url ?? link.url]));
|
|
22
|
+
} catch {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function savedHref(links, key) {
|
|
27
|
+
if (Object.hasOwn(links, key)) return links[key];
|
|
28
|
+
}
|
|
29
|
+
function storefrontHref(value, links) {
|
|
30
|
+
if (typeof value !== "string" && value.reference) {
|
|
31
|
+
if (!links) return value.url;
|
|
32
|
+
return savedHref(links, catalogLinkKey(value)) ?? value.url;
|
|
33
|
+
}
|
|
34
|
+
let href;
|
|
35
|
+
if (typeof value === "string") href = value;
|
|
36
|
+
else href = value.url;
|
|
37
|
+
if (!links) return href;
|
|
38
|
+
const exact = savedHref(links, href);
|
|
39
|
+
if (exact !== void 0) return exact;
|
|
40
|
+
if (!href.startsWith("/") || href.startsWith("//")) return href;
|
|
41
|
+
const at = href.search(/[?#]/);
|
|
42
|
+
if (at < 0) return href;
|
|
43
|
+
const base = savedHref(links, href.slice(0, at));
|
|
44
|
+
if (base === void 0) return href;
|
|
45
|
+
return base.split(/[?#]/, 1)[0] + href.slice(at);
|
|
46
|
+
}
|
|
47
|
+
function destination(to, links) {
|
|
48
|
+
if (typeof to === "string") return storefrontHref(to, links);
|
|
49
|
+
if ("url" in to) return storefrontHref(to, links);
|
|
50
|
+
if (!to.pathname) return to;
|
|
51
|
+
const href = `${to.pathname}${to.search ?? ""}${to.hash ?? ""}`;
|
|
52
|
+
const resolved = storefrontHref(href, links);
|
|
53
|
+
if (resolved === href) return to;
|
|
54
|
+
return resolved;
|
|
55
|
+
}
|
|
56
|
+
function isUnpublishedPage(to, publishedPages) {
|
|
57
|
+
let href;
|
|
58
|
+
if (typeof to === "string") href = to;
|
|
59
|
+
else href = to.pathname;
|
|
60
|
+
if (href === void 0) return false;
|
|
61
|
+
let path = href;
|
|
62
|
+
const suffix = path.search(/[?#]/);
|
|
63
|
+
if (suffix >= 0) path = path.slice(0, suffix);
|
|
64
|
+
path = path.replace(/\/+$/, "");
|
|
65
|
+
if (!path.toLowerCase().startsWith("/pages/")) return false;
|
|
66
|
+
try {
|
|
67
|
+
const pagePath = decodeURIComponent(path).toLowerCase();
|
|
68
|
+
return publishedPages?.some((page) => page.toLowerCase() === pagePath) !== true;
|
|
69
|
+
} catch {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function useStorefrontLinkPublished(to) {
|
|
74
|
+
const data = useRouteLoaderData("root");
|
|
75
|
+
return !isUnpublishedPage(destination(to, data?.storefrontLinks), data?.publishedPages);
|
|
76
|
+
}
|
|
77
|
+
function StorefrontLink(props) {
|
|
78
|
+
const data = useRouteLoaderData("root");
|
|
79
|
+
const to = destination(props.to, data?.storefrontLinks);
|
|
80
|
+
if (isUnpublishedPage(to, data?.publishedPages)) return null;
|
|
81
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
82
|
+
...props,
|
|
83
|
+
to
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function StorefrontAnchor(props) {
|
|
87
|
+
const data = useRouteLoaderData("root");
|
|
88
|
+
let href;
|
|
89
|
+
if (props.href !== void 0) href = storefrontHref(props.href, data?.storefrontLinks);
|
|
90
|
+
if (href !== void 0 && isUnpublishedPage(href, data?.publishedPages)) return null;
|
|
91
|
+
return /* @__PURE__ */ jsx("a", {
|
|
92
|
+
...props,
|
|
93
|
+
href
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export { StorefrontAnchor, StorefrontLink, readStorefrontLayout, readStorefrontLinks, storefrontHref, useStorefrontLinkPublished };
|
package/dist/links.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Link, To } from "react-router";
|
|
2
|
+
import { CatalogLink, StorefrontClient, StorefrontLayout } from "@ecomiq/core";
|
|
3
|
+
import { ComponentPropsWithRef } from "react";
|
|
4
|
+
export type StorefrontLinks = Record<string, string>;
|
|
5
|
+
export declare function readStorefrontLayout({ client, links }: {
|
|
6
|
+
client: Pick<StorefrontClient, "getLayout">;
|
|
7
|
+
links: readonly CatalogLink[];
|
|
8
|
+
}): Promise<Pick<StorefrontLayout, "settings" | "collections"> & {
|
|
9
|
+
storefrontLinks: StorefrontLinks;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function readStorefrontLinks(client: Pick<StorefrontClient, "getLinks">, links: readonly CatalogLink[]): Promise<StorefrontLinks>;
|
|
12
|
+
export declare function storefrontHref(value: string | CatalogLink, links: StorefrontLinks | undefined): string;
|
|
13
|
+
export type StorefrontLinkProps = Omit<ComponentPropsWithRef<typeof Link>, "to"> & {
|
|
14
|
+
to: To | CatalogLink;
|
|
15
|
+
};
|
|
16
|
+
export type StorefrontAnchorProps = Omit<ComponentPropsWithRef<"a">, "href"> & {
|
|
17
|
+
href?: string | CatalogLink;
|
|
18
|
+
};
|
|
19
|
+
export declare function useStorefrontLinkPublished(to: To | CatalogLink): boolean;
|
|
20
|
+
export declare function StorefrontLink(props: StorefrontLinkProps): import("react").JSX.Element | null;
|
|
21
|
+
export declare function StorefrontAnchor(props: StorefrontAnchorProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/mercadopago-checkout.ts
|
|
2
|
+
const MERCADOPAGO_CARD_METHODS = /* @__PURE__ */ new Set(["card"]);
|
|
3
|
+
const MERCADOPAGO_YAPE_METHODS = /* @__PURE__ */ new Set(["yape"]);
|
|
4
|
+
let loading;
|
|
5
|
+
function loadMercadoPago() {
|
|
6
|
+
if (window.MercadoPago) return Promise.resolve(window.MercadoPago);
|
|
7
|
+
if (loading) return loading;
|
|
8
|
+
loading = new Promise((resolve, reject) => {
|
|
9
|
+
const script = document.createElement("script");
|
|
10
|
+
script.src = "https://sdk.mercadopago.com/js/v2";
|
|
11
|
+
script.async = true;
|
|
12
|
+
script.onload = () => {
|
|
13
|
+
if (window.MercadoPago) resolve(window.MercadoPago);
|
|
14
|
+
else reject(/* @__PURE__ */ new Error("No pudimos abrir el pago."));
|
|
15
|
+
};
|
|
16
|
+
script.onerror = () => {
|
|
17
|
+
script.remove();
|
|
18
|
+
reject(/* @__PURE__ */ new Error("No pudimos cargar el pago. Revisa tu conexión e intenta de nuevo."));
|
|
19
|
+
};
|
|
20
|
+
document.head.appendChild(script);
|
|
21
|
+
}).catch((error) => {
|
|
22
|
+
loading = void 0;
|
|
23
|
+
throw error;
|
|
24
|
+
});
|
|
25
|
+
return loading;
|
|
26
|
+
}
|
|
27
|
+
export { MERCADOPAGO_CARD_METHODS, MERCADOPAGO_YAPE_METHODS, loadMercadoPago };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { useStorefrontLocale, useStorefrontText } from "./storefront-language-DrMjVbmk.js";
|
|
2
|
+
import { loadMercadoPago } from "./mercadopago-checkout-DC7RXa8k.js";
|
|
3
|
+
import { money } from "./money-DtGOtDri.js";
|
|
4
|
+
import { PaymentLogo } from "./payment-logo-BoPaGJc_.js";
|
|
5
|
+
import { PaymentDialogFrame } from "./payment-dialog-frame-B-Q_xQ94.js";
|
|
6
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
// src/mercadopago-dialog.tsx
|
|
9
|
+
const MERCADOPAGO_LOGO = /* @__PURE__ */ jsx(PaymentLogo, {
|
|
10
|
+
code: "mercadopago",
|
|
11
|
+
className: "h-8 w-auto"
|
|
12
|
+
});
|
|
13
|
+
function MercadoPagoDialog({ dialog }) {
|
|
14
|
+
if (dialog === null) return null;
|
|
15
|
+
if (dialog.kind === "card") return /* @__PURE__ */ jsx(CardDialog, { dialog });
|
|
16
|
+
return /* @__PURE__ */ jsx(YapeDialog, { dialog });
|
|
17
|
+
}
|
|
18
|
+
function CardDialog({ dialog }) {
|
|
19
|
+
const storefrontTranslate = useStorefrontText();
|
|
20
|
+
const { locale } = useStorefrontLocale();
|
|
21
|
+
const paymentLocale = locale.startsWith("en") ? "en-US" : locale.startsWith("pt") ? "pt-BR" : "es-PE";
|
|
22
|
+
const container = `mercadopago-card-${useId().replace(/[^\w-]/g, "")}`;
|
|
23
|
+
const latest = useRef(dialog);
|
|
24
|
+
latest.current = dialog;
|
|
25
|
+
const [ready, setReady] = useState(false);
|
|
26
|
+
const { publicKey, amount, email } = dialog;
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
let active = true;
|
|
29
|
+
let controller = null;
|
|
30
|
+
async function mount() {
|
|
31
|
+
const MercadoPago = await loadMercadoPago();
|
|
32
|
+
if (!active) return;
|
|
33
|
+
let payer;
|
|
34
|
+
if (email !== null) payer = { email };
|
|
35
|
+
const created = await new MercadoPago(publicKey, { locale: paymentLocale }).bricks().create("cardPayment", container, {
|
|
36
|
+
initialization: {
|
|
37
|
+
amount,
|
|
38
|
+
payer
|
|
39
|
+
},
|
|
40
|
+
customization: { paymentMethods: { maxInstallments: 1 } },
|
|
41
|
+
callbacks: {
|
|
42
|
+
onReady: () => {
|
|
43
|
+
if (active) setReady(true);
|
|
44
|
+
},
|
|
45
|
+
onSubmit: async (data) => {
|
|
46
|
+
if (active) latest.current.onTokenized(data.token, data.payment_method_id);
|
|
47
|
+
},
|
|
48
|
+
onError: (error) => {
|
|
49
|
+
if (active && error.type === "critical") latest.current.onError("No pudimos abrir el pago con tarjeta. Intenta de nuevo.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (active) controller = created;
|
|
54
|
+
else created.unmount();
|
|
55
|
+
}
|
|
56
|
+
mount().catch((error) => {
|
|
57
|
+
if (!active) return;
|
|
58
|
+
if (error instanceof Error) latest.current.onError(error.message);
|
|
59
|
+
else latest.current.onError("No pudimos abrir el pago.");
|
|
60
|
+
});
|
|
61
|
+
return () => {
|
|
62
|
+
active = false;
|
|
63
|
+
controller?.unmount();
|
|
64
|
+
};
|
|
65
|
+
}, [
|
|
66
|
+
publicKey,
|
|
67
|
+
amount,
|
|
68
|
+
email,
|
|
69
|
+
container
|
|
70
|
+
]);
|
|
71
|
+
return /* @__PURE__ */ jsxs(PaymentDialogFrame, {
|
|
72
|
+
title: storefrontTranslate("Pagar con tarjeta"),
|
|
73
|
+
logo: MERCADOPAGO_LOGO,
|
|
74
|
+
onClose: () => latest.current.onClose(),
|
|
75
|
+
note: "Mercado Pago procesa los datos de tu tarjeta de forma segura.",
|
|
76
|
+
children: [ready ? null : /* @__PURE__ */ jsxs("p", {
|
|
77
|
+
role: "status",
|
|
78
|
+
className: "py-8 text-center text-sm text-muted-foreground",
|
|
79
|
+
children: [storefrontTranslate("Cargando el pago…"), " "]
|
|
80
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
81
|
+
id: container,
|
|
82
|
+
className: "[&_h1]:font-sans [&_h1]:tracking-normal"
|
|
83
|
+
})]
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const FIELD = "w-full rounded-md border border-input bg-background px-3 py-2 text-base outline-none md:text-sm focus:border-ring focus:ring-1 focus:ring-ring";
|
|
87
|
+
function YapeDialog({ dialog }) {
|
|
88
|
+
const storefrontTranslate = useStorefrontText();
|
|
89
|
+
const { locale } = useStorefrontLocale();
|
|
90
|
+
const paymentLocale = locale.startsWith("en") ? "en-US" : locale.startsWith("pt") ? "pt-BR" : "es-PE";
|
|
91
|
+
const [busy, setBusy] = useState(false);
|
|
92
|
+
const [error, setError] = useState(null);
|
|
93
|
+
const mounted = useRef(true);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
mounted.current = true;
|
|
96
|
+
return () => {
|
|
97
|
+
mounted.current = false;
|
|
98
|
+
};
|
|
99
|
+
}, []);
|
|
100
|
+
async function submit(event) {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
if (busy) return;
|
|
103
|
+
const data = new FormData(event.currentTarget);
|
|
104
|
+
const phoneNumber = String(data.get("phoneNumber") ?? "").trim();
|
|
105
|
+
const otp = String(data.get("otp") ?? "").trim();
|
|
106
|
+
setBusy(true);
|
|
107
|
+
setError(null);
|
|
108
|
+
try {
|
|
109
|
+
const token = await new (await (loadMercadoPago()))(dialog.publicKey, { locale: paymentLocale }).yape({
|
|
110
|
+
otp,
|
|
111
|
+
phoneNumber
|
|
112
|
+
}).create();
|
|
113
|
+
if (!mounted.current) return;
|
|
114
|
+
dialog.onTokenized(token.id);
|
|
115
|
+
} catch {
|
|
116
|
+
if (!mounted.current) return;
|
|
117
|
+
setError("No pudimos validar tu Yape. Revisa el celular y genera un nuevo código de aprobación.");
|
|
118
|
+
} finally {
|
|
119
|
+
if (mounted.current) setBusy(false);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return /* @__PURE__ */ jsx(PaymentDialogFrame, {
|
|
123
|
+
title: storefrontTranslate("Pagar con Yape"),
|
|
124
|
+
logo: MERCADOPAGO_LOGO,
|
|
125
|
+
onClose: dialog.onClose,
|
|
126
|
+
note: "Mercado Pago procesa tu pago con Yape de forma segura.",
|
|
127
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
128
|
+
onSubmit: submit,
|
|
129
|
+
className: "flex flex-col gap-3 py-2",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ jsxs("label", {
|
|
132
|
+
className: "flex flex-col gap-1 text-sm",
|
|
133
|
+
children: [/* @__PURE__ */ jsx("span", { children: storefrontTranslate("Celular registrado en Yape") }), /* @__PURE__ */ jsx("input", {
|
|
134
|
+
name: "phoneNumber",
|
|
135
|
+
type: "tel",
|
|
136
|
+
inputMode: "numeric",
|
|
137
|
+
autoComplete: "tel-national",
|
|
138
|
+
pattern: "[0-9]{9}",
|
|
139
|
+
maxLength: 9,
|
|
140
|
+
required: true,
|
|
141
|
+
placeholder: "987654321",
|
|
142
|
+
className: FIELD
|
|
143
|
+
})]
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ jsxs("label", {
|
|
146
|
+
className: "flex flex-col gap-1 text-sm",
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ jsx("span", { children: storefrontTranslate("Código de aprobación") }),
|
|
149
|
+
/* @__PURE__ */ jsx("input", {
|
|
150
|
+
name: "otp",
|
|
151
|
+
inputMode: "numeric",
|
|
152
|
+
autoComplete: "one-time-code",
|
|
153
|
+
pattern: "[0-9]{6}",
|
|
154
|
+
maxLength: 6,
|
|
155
|
+
required: true,
|
|
156
|
+
placeholder: "123456",
|
|
157
|
+
className: FIELD
|
|
158
|
+
}),
|
|
159
|
+
/* @__PURE__ */ jsx("span", {
|
|
160
|
+
className: "text-xs text-muted-foreground",
|
|
161
|
+
children: storefrontTranslate("Lo encuentras en tu app de Yape, en el menú «Código de aprobación».")
|
|
162
|
+
})
|
|
163
|
+
]
|
|
164
|
+
}),
|
|
165
|
+
error ? /* @__PURE__ */ jsx("p", {
|
|
166
|
+
role: "alert",
|
|
167
|
+
className: "text-sm text-destructive",
|
|
168
|
+
children: error
|
|
169
|
+
}) : null,
|
|
170
|
+
/* @__PURE__ */ jsx("button", {
|
|
171
|
+
type: "submit",
|
|
172
|
+
disabled: busy,
|
|
173
|
+
className: "rounded-md bg-primary px-4 py-2.5 text-sm font-medium text-primary-foreground disabled:opacity-60",
|
|
174
|
+
children: busy ? "Validando…" : storefrontTranslate("Pagar {value0}", { value0: money(dialog.amount, dialog.currency, locale) })
|
|
175
|
+
})
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
export { MercadoPagoDialog };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type MercadoPagoCardDialog = {
|
|
2
|
+
kind: "card";
|
|
3
|
+
publicKey: string;
|
|
4
|
+
amount: number;
|
|
5
|
+
email: string | null;
|
|
6
|
+
onTokenized: (token: string, paymentMethodId: string) => void;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
onError: (message: string) => void;
|
|
9
|
+
};
|
|
10
|
+
export type MercadoPagoYapeDialog = {
|
|
11
|
+
kind: "yape";
|
|
12
|
+
publicKey: string;
|
|
13
|
+
amount: number;
|
|
14
|
+
currency: string;
|
|
15
|
+
onTokenized: (token: string) => void;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
};
|
|
18
|
+
export type MercadoPagoDialogState = MercadoPagoCardDialog | MercadoPagoYapeDialog;
|
|
19
|
+
export declare function MercadoPagoDialog({ dialog }: {
|
|
20
|
+
dialog: MercadoPagoDialogState | null;
|
|
21
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/money.ts
|
|
2
|
+
const WHOLE = /* @__PURE__ */ new Set([
|
|
3
|
+
"CLP",
|
|
4
|
+
"COP",
|
|
5
|
+
"PYG",
|
|
6
|
+
"JPY",
|
|
7
|
+
"KRW",
|
|
8
|
+
"VND",
|
|
9
|
+
"ISK",
|
|
10
|
+
"UGX",
|
|
11
|
+
"XAF",
|
|
12
|
+
"XOF"
|
|
13
|
+
]);
|
|
14
|
+
function money(value, currency, language, display = "narrowSymbol") {
|
|
15
|
+
const locale = language;
|
|
16
|
+
const digits = WHOLE.has(currency.toUpperCase()) ? 0 : 2;
|
|
17
|
+
const options = {
|
|
18
|
+
style: "currency",
|
|
19
|
+
currency,
|
|
20
|
+
minimumFractionDigits: digits,
|
|
21
|
+
maximumFractionDigits: digits
|
|
22
|
+
};
|
|
23
|
+
try {
|
|
24
|
+
return new Intl.NumberFormat(locale, {
|
|
25
|
+
...options,
|
|
26
|
+
currencyDisplay: display
|
|
27
|
+
}).format(value);
|
|
28
|
+
} catch {
|
|
29
|
+
return new Intl.NumberFormat(language, options).format(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export { money };
|
package/dist/money.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function money(value: number, currency: string, language: string, display?: "narrowSymbol" | "code"): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { CART_ACTION } from "./cart-form-y9P1r_EX.js";
|
|
2
|
+
import { useFetchers, useNavigation } from "react-router";
|
|
3
|
+
// src/optimistic-cart.ts
|
|
4
|
+
function postsToCart(submission) {
|
|
5
|
+
if (submission.formData === void 0 || submission.formAction === void 0) return false;
|
|
6
|
+
return new URL(submission.formAction, "https://storefront.invalid").pathname === CART_ACTION;
|
|
7
|
+
}
|
|
8
|
+
function lineChange(form) {
|
|
9
|
+
const intent = form.get("intent");
|
|
10
|
+
const itemId = form.get("itemId");
|
|
11
|
+
if (typeof itemId !== "string" || itemId === "") return null;
|
|
12
|
+
if (intent === "remove") return [itemId, {
|
|
13
|
+
quantity: null,
|
|
14
|
+
removing: true
|
|
15
|
+
}];
|
|
16
|
+
if (intent !== "update") return null;
|
|
17
|
+
const quantity = Math.max(0, Math.floor(Number(form.get("quantity"))));
|
|
18
|
+
if (!Number.isFinite(quantity)) return null;
|
|
19
|
+
return [itemId, {
|
|
20
|
+
quantity,
|
|
21
|
+
removing: quantity === 0
|
|
22
|
+
}];
|
|
23
|
+
}
|
|
24
|
+
function useOptimisticCart(cart) {
|
|
25
|
+
const fetchers = useFetchers();
|
|
26
|
+
const navigation = useNavigation();
|
|
27
|
+
const changes = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const submission of [...fetchers, navigation]) {
|
|
29
|
+
if (!postsToCart(submission)) continue;
|
|
30
|
+
const change = lineChange(submission.formData);
|
|
31
|
+
if (change) changes.set(change[0], change[1]);
|
|
32
|
+
}
|
|
33
|
+
const lines = (cart?.items ?? []).map((item) => {
|
|
34
|
+
const change = changes.get(item.id);
|
|
35
|
+
if (change === void 0) return {
|
|
36
|
+
...item,
|
|
37
|
+
pending: false,
|
|
38
|
+
removing: false
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
...item,
|
|
42
|
+
quantity: change.quantity ?? item.quantity,
|
|
43
|
+
pending: true,
|
|
44
|
+
removing: change.removing
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
lines,
|
|
49
|
+
count: lines.reduce((sum, line) => sum + (line.removing ? 0 : line.quantity), 0),
|
|
50
|
+
pending: lines.some((line) => line.pending)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export { useOptimisticCart };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type CartLineLike = {
|
|
2
|
+
id: string;
|
|
3
|
+
quantity: number;
|
|
4
|
+
};
|
|
5
|
+
export type OptimisticCartLine<T extends CartLineLike> = T & {
|
|
6
|
+
pending: boolean;
|
|
7
|
+
removing: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type OptimisticCart<T extends CartLineLike> = {
|
|
10
|
+
lines: OptimisticCartLine<T>[];
|
|
11
|
+
count: number;
|
|
12
|
+
pending: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function useOptimisticCart<T extends CartLineLike>(cart: {
|
|
15
|
+
items: readonly T[];
|
|
16
|
+
} | null): OptimisticCart<T>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { orderStepLabel, orderStepOf, paymentLabel } from "./order-view-9IlBg5AF.js";
|
|
2
|
+
import { PaymentLogo, hasPaymentLogo } from "./payment-logo-BoPaGJc_.js";
|
|
3
|
+
import { useStorefrontLocale, useStorefrontText } from "./storefront-language-DrMjVbmk.js";
|
|
4
|
+
import { Form } from "react-router";
|
|
5
|
+
import { formatOrderDate } from "@ecomiq/core";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Button } from "@theme/ui/button";
|
|
8
|
+
// src/order-display.tsx
|
|
9
|
+
/** The payment's logo and its last digits; the method name only when there is no logo. */
|
|
10
|
+
function PaymentPreview({ payment, className = "" }) {
|
|
11
|
+
const code = payment.cardBrand ?? payment.paymentCode;
|
|
12
|
+
const logo = hasPaymentLogo(code);
|
|
13
|
+
const last4 = payment.cardLast4?.trim() ?? "";
|
|
14
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
15
|
+
className: `flex min-w-0 items-center gap-2 ${className}`,
|
|
16
|
+
children: [logo ? /* @__PURE__ */ jsx(PaymentLogo, {
|
|
17
|
+
code,
|
|
18
|
+
className: "h-5 w-8 shrink-0 object-contain"
|
|
19
|
+
}) : null, /* @__PURE__ */ jsx("span", {
|
|
20
|
+
className: "truncate",
|
|
21
|
+
children: logo && last4 !== "" ? `•••• ${last4}` : paymentLabel(payment)
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function latest(items, field) {
|
|
26
|
+
return items.reduce((last, item) => {
|
|
27
|
+
const value = item[field] ?? null;
|
|
28
|
+
return value !== null && (last === null || value > last) ? value : last;
|
|
29
|
+
}, null);
|
|
30
|
+
}
|
|
31
|
+
/** The line under a status: the date it happened, or what comes next. */
|
|
32
|
+
function useOrderStepDetail() {
|
|
33
|
+
const storefrontTranslate = useStorefrontText();
|
|
34
|
+
const { locale, timeZone } = useStorefrontLocale();
|
|
35
|
+
return (step, items) => {
|
|
36
|
+
const delivered = latest(items, "deliveredAt");
|
|
37
|
+
const shipped = latest(items, "shippedAt");
|
|
38
|
+
if (step === "delivered") return delivered === null ? null : formatOrderDate(delivered, locale, timeZone);
|
|
39
|
+
if (step === "shipped" || step === "outForDelivery") return shipped === null ? storefrontTranslate("Va en camino") : formatOrderDate(shipped, locale, timeZone);
|
|
40
|
+
if (step === "confirmed") return storefrontTranslate("Lo estamos preparando");
|
|
41
|
+
if (step === "pending") return storefrontTranslate("Esperando confirmación");
|
|
42
|
+
return null;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** «Entregado el 21 oct.»: the order's step with the day it got there. */
|
|
46
|
+
function useOrderHeadline() {
|
|
47
|
+
const storefrontTranslate = useStorefrontText();
|
|
48
|
+
const { locale, timeZone } = useStorefrontLocale();
|
|
49
|
+
return (order) => {
|
|
50
|
+
const step = orderStepOf(order);
|
|
51
|
+
const label = storefrontTranslate(orderStepLabel(step));
|
|
52
|
+
const at = step === "delivered" ? latest(order.items, "deliveredAt") : step === "shipped" ? latest(order.items, "shippedAt") : step === "pending" || step === "confirmed" ? order.orderDate : null;
|
|
53
|
+
const date = at === null ? null : new Date(at);
|
|
54
|
+
if (date === null || Number.isNaN(date.getTime())) return label;
|
|
55
|
+
const year = date.getFullYear() === (/* @__PURE__ */ new Date()).getFullYear() ? void 0 : "numeric";
|
|
56
|
+
const day = new Intl.DateTimeFormat(locale, {
|
|
57
|
+
day: "numeric",
|
|
58
|
+
month: "short",
|
|
59
|
+
year,
|
|
60
|
+
timeZone
|
|
61
|
+
}).format(date);
|
|
62
|
+
return storefrontTranslate("{value0} el {value1}", {
|
|
63
|
+
value0: label,
|
|
64
|
+
value1: day
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function ReorderButton({ items, variant = "default" }) {
|
|
69
|
+
const storefrontTranslate = useStorefrontText();
|
|
70
|
+
const lines = items.filter((item) => item.variantId !== null);
|
|
71
|
+
if (lines.length === 0) return null;
|
|
72
|
+
return /* @__PURE__ */ jsxs(Form, {
|
|
73
|
+
method: "post",
|
|
74
|
+
action: "/cart",
|
|
75
|
+
className: "relative",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx("input", {
|
|
78
|
+
type: "hidden",
|
|
79
|
+
name: "intent",
|
|
80
|
+
value: "reorder"
|
|
81
|
+
}),
|
|
82
|
+
lines.map((item) => /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("input", {
|
|
83
|
+
type: "hidden",
|
|
84
|
+
name: "variantId",
|
|
85
|
+
value: item.variantId ?? ""
|
|
86
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
87
|
+
type: "hidden",
|
|
88
|
+
name: "quantity",
|
|
89
|
+
value: item.quantity
|
|
90
|
+
})] }, item.id)),
|
|
91
|
+
/* @__PURE__ */ jsx(Button, {
|
|
92
|
+
type: "submit",
|
|
93
|
+
variant,
|
|
94
|
+
children: storefrontTranslate("Volver a comprar")
|
|
95
|
+
})
|
|
96
|
+
]
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/** A theme button that opens `path`: a GET form, so it keeps the theme's button look without JavaScript. */
|
|
100
|
+
function PayButton({ path, label, variant = "default" }) {
|
|
101
|
+
return /* @__PURE__ */ jsx(Form, {
|
|
102
|
+
method: "get",
|
|
103
|
+
action: path,
|
|
104
|
+
className: "relative",
|
|
105
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
106
|
+
type: "submit",
|
|
107
|
+
variant,
|
|
108
|
+
children: label
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
export { PayButton, PaymentPreview, ReorderButton, useOrderHeadline, useOrderStepDetail };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CustomerOrderLineItem, CustomerOrderListItem, CustomerOrderPayment, OrderStep } from "@ecomiq/core";
|
|
2
|
+
/** The payment's logo and its last digits; the method name only when there is no logo. */
|
|
3
|
+
export declare function PaymentPreview({ payment, className }: {
|
|
4
|
+
payment: CustomerOrderPayment;
|
|
5
|
+
className?: string;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
/** The line under a status: the date it happened, or what comes next. */
|
|
8
|
+
export declare function useOrderStepDetail(): (step: OrderStep, items: CustomerOrderLineItem[]) => string | null;
|
|
9
|
+
/** «Entregado el 21 oct.»: the order's step with the day it got there. */
|
|
10
|
+
export declare function useOrderHeadline(): (order: CustomerOrderListItem) => string;
|
|
11
|
+
export declare function ReorderButton({ items, variant }: {
|
|
12
|
+
items: CustomerOrderLineItem[];
|
|
13
|
+
variant?: "default" | "outline";
|
|
14
|
+
}): import("react").JSX.Element | null;
|
|
15
|
+
/** A theme button that opens `path`: a GET form, so it keeps the theme's button look without JavaScript. */
|
|
16
|
+
export declare function PayButton({ path, label, variant }: {
|
|
17
|
+
path: string;
|
|
18
|
+
label: string;
|
|
19
|
+
variant?: "default" | "outline";
|
|
20
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { found, store } from "./store-8Q-_LFrQ.js";
|
|
2
|
+
import { data, redirect } from "react-router";
|
|
3
|
+
import { ApiError } from "@ecomiq/core";
|
|
4
|
+
// src/order-draft.ts
|
|
5
|
+
function isOrderDraftPayable(draft) {
|
|
6
|
+
return draft.items.length > 0 && draft.orderPaths === null && [
|
|
7
|
+
"draft",
|
|
8
|
+
"sent",
|
|
9
|
+
"viewed",
|
|
10
|
+
"accepted"
|
|
11
|
+
].includes(draft.status);
|
|
12
|
+
}
|
|
13
|
+
async function loadOrderDraft(context, token) {
|
|
14
|
+
const client = store(context);
|
|
15
|
+
const [draft, settings] = await Promise.all([found(client.getOrderDraft(token), (code) => code < 500), client.getSettings()]);
|
|
16
|
+
const orderPaths = draft.orderPaths ?? [];
|
|
17
|
+
if (orderPaths.length === 1) throw redirect(orderPaths[0]);
|
|
18
|
+
return {
|
|
19
|
+
token,
|
|
20
|
+
draft,
|
|
21
|
+
payable: isOrderDraftPayable(draft),
|
|
22
|
+
orderPaths,
|
|
23
|
+
language: `${settings.store.language}-${settings.store.countryCode}`
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function orderDraftAction(context, token) {
|
|
27
|
+
try {
|
|
28
|
+
const result = await store(context).checkoutOrderDraft(token);
|
|
29
|
+
if (result.orderPaths.length === 1) return redirect(result.orderPaths[0]);
|
|
30
|
+
return { orderPaths: result.orderPaths };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (error instanceof ApiError && error.status === 404) throw data(null, { status: 404 });
|
|
33
|
+
let message = "No pudimos preparar el pago. Intenta de nuevo.";
|
|
34
|
+
if (error instanceof ApiError && error.status >= 400 && error.status < 500) message = error.message;
|
|
35
|
+
return data({ error: message }, { status: 400 });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export { isOrderDraftPayable, loadOrderDraft, orderDraftAction };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RouterContextProvider } from "react-router";
|
|
2
|
+
import { OrderDraft } from "@ecomiq/core";
|
|
3
|
+
export type OrderDraftData = {
|
|
4
|
+
token: string;
|
|
5
|
+
draft: OrderDraft;
|
|
6
|
+
payable: boolean;
|
|
7
|
+
orderPaths: string[];
|
|
8
|
+
language: string;
|
|
9
|
+
};
|
|
10
|
+
export type OrderDraftActionData = {
|
|
11
|
+
error?: string;
|
|
12
|
+
orderPaths?: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare function isOrderDraftPayable(draft: OrderDraft): boolean;
|
|
15
|
+
export declare function loadOrderDraft(context: Readonly<RouterContextProvider>, token: string): Promise<OrderDraftData>;
|
|
16
|
+
export declare function orderDraftAction(context: Readonly<RouterContextProvider>, token: string): Promise<import("react-router").UNSAFE_DataWithResponseInit<OrderDraftActionData> | OrderDraftActionData | Response>;
|