@ecomiq/storefront 2.1.3 → 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 -123
- 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 -81
- 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/cloud-runtime-client.ts +0 -378
- package/src/codegen.mjs +0 -789
- 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 -354
- 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 -111
- 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 -301
- package/src/storefront-definition/contract.ts +0 -1
- package/src/storefront-definition/data.ts +0 -188
- package/src/storefront-definition/index.ts +0 -2
- package/src/storefront-definition/renderer.tsx +0 -1481
- package/src/storefront-layout.ts +0 -59
- package/src/storefront-runtime.ts +0 -173
- package/src/styles.css +0 -97
- 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,259 @@
|
|
|
1
|
+
import type { CustomerOrderLineItem, CustomerOrderListItem } from "@ecomiq/core";
|
|
2
|
+
import { Form, Link, useLocation, useNavigate } from "react-router";
|
|
3
|
+
import { Button } from "@theme/ui/button";
|
|
4
|
+
import { Input } from "@theme/ui/input";
|
|
5
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@theme/ui/select";
|
|
6
|
+
import { money, useStorefrontLocale, useStorefrontText, type SectionCatalog } from "../index";
|
|
7
|
+
import {
|
|
8
|
+
PayButton,
|
|
9
|
+
PaymentPreview,
|
|
10
|
+
ReorderButton,
|
|
11
|
+
mainPayment,
|
|
12
|
+
orderFiltersQuery,
|
|
13
|
+
orderStepLabel,
|
|
14
|
+
orderStepOf,
|
|
15
|
+
useOrderHeadline,
|
|
16
|
+
useOrderPages,
|
|
17
|
+
useOrderStepDetail,
|
|
18
|
+
type OrderFilters,
|
|
19
|
+
type OrdersData,
|
|
20
|
+
} from "../entries/account";
|
|
21
|
+
|
|
22
|
+
export const catalog: SectionCatalog = {
|
|
23
|
+
name: "Mis pedidos",
|
|
24
|
+
description: "Pedidos del cliente con búsqueda, filtros, estado y pago.",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const STATUSES: ReadonlyArray<{ value: OrderFilters["status"]; label: string }> = [
|
|
28
|
+
{ value: null, label: "Todos" },
|
|
29
|
+
{ value: "open", label: "En curso" },
|
|
30
|
+
{ value: "delivered", label: "Entregados" },
|
|
31
|
+
{ value: "cancelled", label: "Cancelados" },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
function Collage({ items }: { items: CustomerOrderLineItem[] }) {
|
|
35
|
+
const shown = items.slice(0, 4);
|
|
36
|
+
const hidden = items.length - shown.length;
|
|
37
|
+
const tile = (index: number) => {
|
|
38
|
+
if (shown.length === 1) return "col-span-2 row-span-2";
|
|
39
|
+
if (shown.length === 2) return "row-span-2";
|
|
40
|
+
if (shown.length === 3 && index === 0) return "row-span-2";
|
|
41
|
+
return "";
|
|
42
|
+
};
|
|
43
|
+
return (
|
|
44
|
+
<div className="grid aspect-[5/4] grid-cols-2 grid-rows-2 gap-1 overflow-hidden rounded-md">
|
|
45
|
+
{shown.map((item, index) => (
|
|
46
|
+
<span key={item.id} className={`relative min-h-0 overflow-hidden bg-muted ${tile(index)}`}>
|
|
47
|
+
{item.thumbnail ? <img src={item.thumbnail} alt="" loading="lazy" decoding="async" className="size-full object-cover" /> : null}
|
|
48
|
+
{hidden > 0 && index === shown.length - 1 ? (
|
|
49
|
+
<span className="absolute inset-0 flex items-center justify-center bg-foreground/55 text-lg font-semibold text-background">+{hidden + 1}</span>
|
|
50
|
+
) : null}
|
|
51
|
+
</span>
|
|
52
|
+
))}
|
|
53
|
+
{shown.length === 0 ? <span className="col-span-2 row-span-2 bg-muted" /> : null}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function Thumbnails({ items }: { items: CustomerOrderLineItem[] }) {
|
|
59
|
+
const shown = items.slice(0, 4);
|
|
60
|
+
const hidden = items.length - shown.length;
|
|
61
|
+
const size = items.length <= 2 ? "size-24 sm:size-28" : "size-16";
|
|
62
|
+
return (
|
|
63
|
+
<div className="flex gap-2">
|
|
64
|
+
{shown.map((item, index) => (
|
|
65
|
+
<span key={item.id} className={`relative shrink-0 overflow-hidden rounded-md border bg-muted ${size}`}>
|
|
66
|
+
{item.thumbnail ? <img src={item.thumbnail} alt="" loading="lazy" decoding="async" className="size-full object-cover" /> : null}
|
|
67
|
+
{hidden > 0 && index === shown.length - 1 ? (
|
|
68
|
+
<span className="absolute inset-0 flex items-center justify-center bg-foreground/55 text-sm font-semibold text-background">+{hidden + 1}</span>
|
|
69
|
+
) : null}
|
|
70
|
+
</span>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function OrderCard({ order }: { order: CustomerOrderListItem }) {
|
|
77
|
+
const storefrontTranslate = useStorefrontText();
|
|
78
|
+
const { locale } = useStorefrontLocale();
|
|
79
|
+
const stepDetail = useOrderStepDetail();
|
|
80
|
+
const step = orderStepOf(order);
|
|
81
|
+
const detail = stepDetail(step, order.items);
|
|
82
|
+
const payment = mainPayment(order.payments);
|
|
83
|
+
const units = order.items.reduce((sum, item) => sum + item.quantity, 0);
|
|
84
|
+
return (
|
|
85
|
+
<Link to={`/account/orders/${order.orderId}`} className="group flex h-full flex-col gap-4 rounded-lg border bg-card p-4 text-card-foreground">
|
|
86
|
+
<div className="flex flex-col gap-0.5">
|
|
87
|
+
<p className={`font-heading text-xl ${step === "cancelled" ? "text-muted-foreground" : ""}`}>{storefrontTranslate(orderStepLabel(step))}</p>
|
|
88
|
+
{detail === null ? null : <p className="text-sm text-muted-foreground">{detail}</p>}
|
|
89
|
+
</div>
|
|
90
|
+
<Collage items={order.items} />
|
|
91
|
+
<div className="mt-auto grid grid-cols-[minmax(0,1fr)_auto] gap-x-4 gap-y-1 text-sm">
|
|
92
|
+
<p className="font-medium group-hover:underline">{storefrontTranslate("Pedido {value0}", { value0: order.orderNumber })}</p>
|
|
93
|
+
<p className="text-right font-medium tabular-nums">{money(order.total, order.currencyCode, locale)}</p>
|
|
94
|
+
<p className="text-muted-foreground">{units === 1 ? storefrontTranslate("1 producto") : storefrontTranslate("{value0} productos", { value0: units })}</p>
|
|
95
|
+
{payment ? <PaymentPreview payment={payment} className="justify-end text-muted-foreground" /> : null}
|
|
96
|
+
</div>
|
|
97
|
+
</Link>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function OrderListCard({ order }: { order: CustomerOrderListItem }) {
|
|
102
|
+
const storefrontTranslate = useStorefrontText();
|
|
103
|
+
const { locale } = useStorefrontLocale();
|
|
104
|
+
const headline = useOrderHeadline();
|
|
105
|
+
const payment = mainPayment(order.payments);
|
|
106
|
+
return (
|
|
107
|
+
<div className="relative flex flex-col gap-4 rounded-lg border bg-card p-4 text-card-foreground transition-colors hover:border-foreground/30 sm:p-5">
|
|
108
|
+
<Thumbnails items={order.items} />
|
|
109
|
+
<div className="flex flex-wrap items-end justify-between gap-x-4 gap-y-3">
|
|
110
|
+
<div className="flex min-w-0 flex-col gap-1">
|
|
111
|
+
<Link
|
|
112
|
+
to={`/account/orders/${order.orderId}`}
|
|
113
|
+
className={`font-heading text-lg after:absolute after:inset-0 after:rounded-lg ${orderStepOf(order) === "cancelled" ? "text-muted-foreground" : ""}`}
|
|
114
|
+
>
|
|
115
|
+
{headline(order)}
|
|
116
|
+
</Link>
|
|
117
|
+
<p className="flex flex-wrap items-center gap-x-1.5 text-sm text-muted-foreground">
|
|
118
|
+
<span>{storefrontTranslate("Pedido {value0}", { value0: order.orderNumber })}</span>
|
|
119
|
+
<span aria-hidden="true">·</span>
|
|
120
|
+
<span>{money(order.total, order.currencyCode, locale)}</span>
|
|
121
|
+
{payment ? (
|
|
122
|
+
<>
|
|
123
|
+
<span aria-hidden="true">·</span>
|
|
124
|
+
<PaymentPreview payment={payment} />
|
|
125
|
+
</>
|
|
126
|
+
) : null}
|
|
127
|
+
</p>
|
|
128
|
+
</div>
|
|
129
|
+
{order.total - order.totalPaid > 0 && orderStepOf(order) !== "cancelled" ? (
|
|
130
|
+
<PayButton path={`/account/orders/${order.orderId}`} label={storefrontTranslate("Pagar")} variant="outline" />
|
|
131
|
+
) : (
|
|
132
|
+
<ReorderButton items={order.items} variant="outline" />
|
|
133
|
+
)}
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const VIEW_ICONS = {
|
|
140
|
+
list: "M4 6h16M4 12h16M4 18h16",
|
|
141
|
+
grid: "M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z",
|
|
142
|
+
} as const;
|
|
143
|
+
|
|
144
|
+
export function AccountOrders({ loaderData }: { loaderData: OrdersData }) {
|
|
145
|
+
const storefrontTranslate = useStorefrontText();
|
|
146
|
+
const { pathname } = useLocation();
|
|
147
|
+
const navigate = useNavigate();
|
|
148
|
+
const { orders, more } = useOrderPages(loaderData);
|
|
149
|
+
const { filters } = loaderData;
|
|
150
|
+
const filtered = filters.q !== "" || filters.status !== null;
|
|
151
|
+
const href = (next: OrderFilters) => {
|
|
152
|
+
const query = orderFiltersQuery(next).toString();
|
|
153
|
+
return query === "" ? pathname : `${pathname}?${query}`;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (orders.length === 0 && !filtered)
|
|
157
|
+
return (
|
|
158
|
+
<div className="flex flex-col items-start gap-4 rounded-lg border bg-card p-8 text-card-foreground md:p-10">
|
|
159
|
+
<h2 className="text-2xl">{storefrontTranslate("Aún no tienes pedidos")}</h2>
|
|
160
|
+
<p className="text-sm text-muted-foreground">{storefrontTranslate("Cuando compres, verás aquí el estado de cada pedido.")}</p>
|
|
161
|
+
<Link to="/products" className="text-sm font-medium underline underline-offset-4">
|
|
162
|
+
{storefrontTranslate("Ver productos")}
|
|
163
|
+
</Link>
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<div className="@container flex flex-col gap-6">
|
|
169
|
+
<div className="flex items-center justify-between gap-4">
|
|
170
|
+
<h2 className="text-3xl">{storefrontTranslate("Pedidos")}</h2>
|
|
171
|
+
<div className="hidden gap-1 sm:flex" role="group" aria-label={storefrontTranslate("Vista")}>
|
|
172
|
+
{(["list", "grid"] as const).map((view) => (
|
|
173
|
+
<Link
|
|
174
|
+
key={view}
|
|
175
|
+
to={href({ ...filters, view })}
|
|
176
|
+
aria-pressed={filters.view === view}
|
|
177
|
+
aria-label={storefrontTranslate(view === "list" ? "Ver como lista" : "Ver como cuadrícula")}
|
|
178
|
+
className={`flex size-9 items-center justify-center rounded-md transition-colors ${filters.view === view ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground"}`}
|
|
179
|
+
>
|
|
180
|
+
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" className="size-4">
|
|
181
|
+
<path d={VIEW_ICONS[view]} />
|
|
182
|
+
</svg>
|
|
183
|
+
</Link>
|
|
184
|
+
))}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div className="flex flex-col gap-4">
|
|
188
|
+
<Form method="get" action={pathname} className="flex gap-2" role="search">
|
|
189
|
+
<div className="relative min-w-0 flex-1">
|
|
190
|
+
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground">
|
|
191
|
+
<circle cx="11" cy="11" r="7" />
|
|
192
|
+
<path d="m20 20-3.5-3.5" />
|
|
193
|
+
</svg>
|
|
194
|
+
<Input type="search" name="q" defaultValue={filters.q} placeholder={storefrontTranslate("Buscar")} aria-label={storefrontTranslate("Buscar pedidos")} maxLength={100} className="pl-9" />
|
|
195
|
+
</div>
|
|
196
|
+
{filters.status !== null ? <input type="hidden" name="status" value={filters.status} /> : null}
|
|
197
|
+
{filters.sort === "oldest" ? <input type="hidden" name="sort" value="oldest" /> : null}
|
|
198
|
+
{filters.view === "grid" ? <input type="hidden" name="view" value="grid" /> : null}
|
|
199
|
+
<Select value={filters.sort} onValueChange={(sort) => navigate(href({ ...filters, sort: sort === "oldest" ? "oldest" : "newest" }))}>
|
|
200
|
+
<SelectTrigger aria-label={storefrontTranslate("Ordenar pedidos")} className="h-auto shrink-0 self-stretch data-[size=default]:h-auto">
|
|
201
|
+
<SelectValue>{storefrontTranslate(filters.sort === "oldest" ? "Más antiguos" : "Más recientes")}</SelectValue>
|
|
202
|
+
</SelectTrigger>
|
|
203
|
+
<SelectContent>
|
|
204
|
+
<SelectItem value="newest">{storefrontTranslate("Más recientes")}</SelectItem>
|
|
205
|
+
<SelectItem value="oldest">{storefrontTranslate("Más antiguos")}</SelectItem>
|
|
206
|
+
</SelectContent>
|
|
207
|
+
</Select>
|
|
208
|
+
</Form>
|
|
209
|
+
<div className="border-b">
|
|
210
|
+
<nav className="-mb-px flex gap-6 overflow-x-auto" aria-label={storefrontTranslate("Filtrar pedidos")}>
|
|
211
|
+
{STATUSES.map((status) => {
|
|
212
|
+
const current = status.value === filters.status;
|
|
213
|
+
return (
|
|
214
|
+
<Link
|
|
215
|
+
key={status.label}
|
|
216
|
+
to={href({ ...filters, status: status.value })}
|
|
217
|
+
aria-current={current ? "page" : undefined}
|
|
218
|
+
className={`shrink-0 whitespace-nowrap border-b-2 pb-3 text-sm transition-colors ${current ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"}`}
|
|
219
|
+
>
|
|
220
|
+
{storefrontTranslate(status.label)}
|
|
221
|
+
</Link>
|
|
222
|
+
);
|
|
223
|
+
})}
|
|
224
|
+
</nav>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
{orders.length === 0 ? (
|
|
228
|
+
<div className="flex flex-col items-start gap-3 py-6">
|
|
229
|
+
<p className="font-heading text-xl">{storefrontTranslate("Ningún pedido coincide")}</p>
|
|
230
|
+
<p className="text-sm text-muted-foreground">{storefrontTranslate("Prueba con otro número de pedido, producto o estado.")}</p>
|
|
231
|
+
<Link to={pathname} className="text-sm font-medium underline underline-offset-4">
|
|
232
|
+
{storefrontTranslate("Quitar filtros")}
|
|
233
|
+
</Link>
|
|
234
|
+
</div>
|
|
235
|
+
) : filters.view === "grid" ? (
|
|
236
|
+
<ul className="grid gap-4 @lg:grid-cols-2">
|
|
237
|
+
{orders.map((order) => (
|
|
238
|
+
<li key={order.orderId}>
|
|
239
|
+
<OrderCard order={order} />
|
|
240
|
+
</li>
|
|
241
|
+
))}
|
|
242
|
+
</ul>
|
|
243
|
+
) : (
|
|
244
|
+
<ul className="flex flex-col gap-3">
|
|
245
|
+
{orders.map((order) => (
|
|
246
|
+
<li key={order.orderId}>
|
|
247
|
+
<OrderListCard order={order} />
|
|
248
|
+
</li>
|
|
249
|
+
))}
|
|
250
|
+
</ul>
|
|
251
|
+
)}
|
|
252
|
+
{more ? (
|
|
253
|
+
<Button type="button" variant="outline" className="self-center" disabled={more.loading} onClick={() => more.load()}>
|
|
254
|
+
{more.loading ? storefrontTranslate("Cargando…") : storefrontTranslate("Ver más pedidos")}
|
|
255
|
+
</Button>
|
|
256
|
+
) : null}
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { CustomerMe } from "@ecomiq/core";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { useNavigation } from "react-router";
|
|
4
|
+
import { Button } from "@theme/ui/button";
|
|
5
|
+
import { Input } from "@theme/ui/input";
|
|
6
|
+
import { useStorefrontText, type SectionCatalog } from "../index";
|
|
7
|
+
import { CustomerDocumentFields, ProfileForm, type ProfileActionData } from "../entries/account";
|
|
8
|
+
|
|
9
|
+
export const catalog: SectionCatalog = {
|
|
10
|
+
name: "Mi perfil",
|
|
11
|
+
description: "Nombre, celular y documento del cliente.",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function Labeled({ label, hint, className = "", children }: { label: string; hint?: string; className?: string; children: ReactNode }) {
|
|
15
|
+
return (
|
|
16
|
+
<label className={`flex flex-col gap-1.5 text-sm ${className}`}>
|
|
17
|
+
<span className="font-medium">{label}</span>
|
|
18
|
+
{children}
|
|
19
|
+
{hint ? <span className="text-xs text-muted-foreground">{hint}</span> : null}
|
|
20
|
+
</label>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function AccountProfile({ loaderData, actionData }: { loaderData: { me: CustomerMe; countries: { code: string; name: string }[] }; actionData?: ProfileActionData }) {
|
|
25
|
+
const storefrontTranslate = useStorefrontText();
|
|
26
|
+
const { me, countries } = loaderData;
|
|
27
|
+
const busy = useNavigation().state !== "idle";
|
|
28
|
+
return (
|
|
29
|
+
<div className="flex flex-col gap-6">
|
|
30
|
+
<h2 className="text-3xl">{storefrontTranslate("Datos personales")}</h2>
|
|
31
|
+
<ProfileForm className="flex max-w-2xl flex-col gap-4">
|
|
32
|
+
{actionData?.error ? (
|
|
33
|
+
<p role="alert" className="rounded-md bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
|
34
|
+
{storefrontTranslate(actionData.error)}
|
|
35
|
+
</p>
|
|
36
|
+
) : null}
|
|
37
|
+
{actionData?.saved ? (
|
|
38
|
+
<p role="status" className="rounded-md bg-muted px-4 py-3 text-sm">
|
|
39
|
+
{storefrontTranslate("Datos guardados.")}
|
|
40
|
+
</p>
|
|
41
|
+
) : null}
|
|
42
|
+
<section className="flex flex-col gap-4 rounded-lg border bg-card p-5 text-card-foreground md:p-6">
|
|
43
|
+
<h3 className="font-heading text-lg">{storefrontTranslate("Tus datos")}</h3>
|
|
44
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
45
|
+
<Labeled label={storefrontTranslate("Nombre")}>
|
|
46
|
+
<Input name="firstName" autoComplete="given-name" defaultValue={me.firstName ?? ""} maxLength={100} />
|
|
47
|
+
</Labeled>
|
|
48
|
+
<Labeled label={storefrontTranslate("Apellido")}>
|
|
49
|
+
<Input name="lastName" autoComplete="family-name" defaultValue={me.lastName ?? ""} maxLength={100} />
|
|
50
|
+
</Labeled>
|
|
51
|
+
<Labeled label={storefrontTranslate("Celular")}>
|
|
52
|
+
<Input name="phone" type="tel" autoComplete="tel" defaultValue={me.phone ?? ""} />
|
|
53
|
+
</Labeled>
|
|
54
|
+
<div className="flex flex-col gap-1.5 text-sm">
|
|
55
|
+
<span className="font-medium">{storefrontTranslate("Correo")}</span>
|
|
56
|
+
<p className="flex h-10 items-center text-muted-foreground">{me.email ?? "—"}</p>
|
|
57
|
+
<span className="text-xs text-muted-foreground">{storefrontTranslate("Escríbenos si necesitas cambiarlo.")}</span>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</section>
|
|
61
|
+
<section className="rounded-lg border bg-card p-5 text-card-foreground md:p-6">
|
|
62
|
+
<CustomerDocumentFields customer={me} countries={countries} />
|
|
63
|
+
</section>
|
|
64
|
+
<Button type="submit" className="w-fit" disabled={busy}>
|
|
65
|
+
{busy ? storefrontTranslate("Guardando…") : storefrontTranslate("Guardar cambios")}
|
|
66
|
+
</Button>
|
|
67
|
+
</ProfileForm>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|