@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,376 @@
|
|
|
1
|
+
import { previewAddress } from "./preview-address-Cf0sJ-9p.js";
|
|
2
|
+
// src/preview-cart.ts
|
|
3
|
+
const PREVIEW_CART_TOKEN = "ecomiq-editor-preview-cart";
|
|
4
|
+
const BUYER = {
|
|
5
|
+
email: "ana.torres@example.com",
|
|
6
|
+
firstName: "Ana",
|
|
7
|
+
lastName: "Torres",
|
|
8
|
+
phone: "000000000",
|
|
9
|
+
identificationCountryCode: null,
|
|
10
|
+
identificationType: null,
|
|
11
|
+
identificationNumber: null,
|
|
12
|
+
entityTaxId: null,
|
|
13
|
+
entityName: null,
|
|
14
|
+
invoiceType: "ticket"
|
|
15
|
+
};
|
|
16
|
+
const RATES = [
|
|
17
|
+
{
|
|
18
|
+
shippingMethodId: "preview-regular",
|
|
19
|
+
name: "Envío regular",
|
|
20
|
+
displayName: "Envío regular",
|
|
21
|
+
target: "automatic",
|
|
22
|
+
price: 12,
|
|
23
|
+
description: "Llega en 3 a 5 días",
|
|
24
|
+
estimatedDeliveryDays: 4,
|
|
25
|
+
rateId: "preview-regular"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
shippingMethodId: "preview-express",
|
|
29
|
+
name: "Envío express",
|
|
30
|
+
displayName: "Envío express",
|
|
31
|
+
target: "automatic",
|
|
32
|
+
price: 25,
|
|
33
|
+
description: "Llega mañana",
|
|
34
|
+
estimatedDeliveryDays: 1,
|
|
35
|
+
rateId: "preview-express"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
shippingMethodId: "preview-pickup",
|
|
39
|
+
name: "Retiro en tienda",
|
|
40
|
+
displayName: "Retiro en tienda",
|
|
41
|
+
target: "pickupPoint",
|
|
42
|
+
price: 0,
|
|
43
|
+
description: "Listo en 24 horas",
|
|
44
|
+
estimatedDeliveryDays: 1,
|
|
45
|
+
rateId: "preview-pickup"
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
const SAMPLE_METHODS = [{
|
|
49
|
+
code: "card",
|
|
50
|
+
name: "Tarjeta de crédito o débito",
|
|
51
|
+
description: null,
|
|
52
|
+
kind: "card",
|
|
53
|
+
isActive: true,
|
|
54
|
+
isDefault: true,
|
|
55
|
+
isManual: false,
|
|
56
|
+
sortOrder: 0,
|
|
57
|
+
providerId: null,
|
|
58
|
+
checkoutMode: null,
|
|
59
|
+
brands: ["visa", "mastercard"],
|
|
60
|
+
bankAccounts: [],
|
|
61
|
+
publicConfiguration: {}
|
|
62
|
+
}, {
|
|
63
|
+
code: "transfer",
|
|
64
|
+
name: "Transferencia bancaria",
|
|
65
|
+
description: "Te enviamos los datos al confirmar",
|
|
66
|
+
kind: "offline",
|
|
67
|
+
isActive: true,
|
|
68
|
+
isDefault: false,
|
|
69
|
+
isManual: true,
|
|
70
|
+
sortOrder: 1,
|
|
71
|
+
providerId: null,
|
|
72
|
+
checkoutMode: null,
|
|
73
|
+
brands: [],
|
|
74
|
+
bankAccounts: [],
|
|
75
|
+
publicConfiguration: {}
|
|
76
|
+
}];
|
|
77
|
+
const state = {
|
|
78
|
+
items: null,
|
|
79
|
+
codes: [],
|
|
80
|
+
rate: "preview-regular",
|
|
81
|
+
method: null,
|
|
82
|
+
buyer: BUYER,
|
|
83
|
+
address: null
|
|
84
|
+
};
|
|
85
|
+
const variants = /* @__PURE__ */ new Map();
|
|
86
|
+
function line(id, product, quantity) {
|
|
87
|
+
return {
|
|
88
|
+
id,
|
|
89
|
+
productId: product.id,
|
|
90
|
+
title: product.name,
|
|
91
|
+
variantLabel: null,
|
|
92
|
+
productHandle: product.slug,
|
|
93
|
+
productUrl: product.url,
|
|
94
|
+
thumbnail: product.imageUrl || null,
|
|
95
|
+
quantity,
|
|
96
|
+
variantId: null,
|
|
97
|
+
variantSku: null,
|
|
98
|
+
unitPrice: product.price,
|
|
99
|
+
compareAtUnitPrice: product.compareAtPrice,
|
|
100
|
+
bundleItems: [],
|
|
101
|
+
requiresShipping: true,
|
|
102
|
+
sellerId: null,
|
|
103
|
+
sellerName: null,
|
|
104
|
+
orderBumpId: null
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function rememberProduct(product) {
|
|
108
|
+
for (const variant of product.variants) {
|
|
109
|
+
if (variant.id === null) continue;
|
|
110
|
+
const label = variant.options.map((option) => option.value).join(" / ");
|
|
111
|
+
variants.set(variant.id, {
|
|
112
|
+
...line(`preview-line-${variant.id}`, {
|
|
113
|
+
...product,
|
|
114
|
+
imageUrl: variant.images[0]?.url ?? product.imageUrl,
|
|
115
|
+
price: variant.price,
|
|
116
|
+
compareAtPrice: variant.compareAtPrice
|
|
117
|
+
}, 1),
|
|
118
|
+
variantId: variant.id,
|
|
119
|
+
variantSku: variant.sku || null,
|
|
120
|
+
variantLabel: label || null,
|
|
121
|
+
requiresShipping: variant.requiresShipping,
|
|
122
|
+
sellerId: product.seller?.id ?? null,
|
|
123
|
+
sellerName: product.seller?.name ?? null
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function items(client) {
|
|
128
|
+
if (state.items !== null) return state.items;
|
|
129
|
+
const products = (await client.getProducts({
|
|
130
|
+
pageSize: 4,
|
|
131
|
+
inStock: true
|
|
132
|
+
}).catch(() => null))?.products ?? [];
|
|
133
|
+
if (products.length === 0) {
|
|
134
|
+
state.items = [line("preview-line-sample", {
|
|
135
|
+
id: "preview-product",
|
|
136
|
+
name: "Producto de ejemplo",
|
|
137
|
+
slug: "",
|
|
138
|
+
url: null,
|
|
139
|
+
imageUrl: "",
|
|
140
|
+
price: 89,
|
|
141
|
+
compareAtPrice: null
|
|
142
|
+
}, 1)];
|
|
143
|
+
return state.items;
|
|
144
|
+
}
|
|
145
|
+
state.items = products.slice(0, 2).map((product, index) => ({
|
|
146
|
+
...line(`preview-line-${product.id}`, product, index + 1),
|
|
147
|
+
sellerId: product.seller?.id ?? null,
|
|
148
|
+
sellerName: product.seller?.name ?? null
|
|
149
|
+
}));
|
|
150
|
+
return state.items;
|
|
151
|
+
}
|
|
152
|
+
function shippingMethod() {
|
|
153
|
+
const rate = RATES.find((candidate) => candidate.shippingMethodId === state.rate) ?? RATES[0];
|
|
154
|
+
return {
|
|
155
|
+
id: `preview-shipping-${rate.shippingMethodId}`,
|
|
156
|
+
shippingMethodId: rate.shippingMethodId,
|
|
157
|
+
rateId: rate.rateId ?? null,
|
|
158
|
+
name: rate.name ?? "Envío",
|
|
159
|
+
description: rate.description ?? null,
|
|
160
|
+
type: rate.target === "pickupPoint" ? "pickup" : "regular",
|
|
161
|
+
target: rate.target,
|
|
162
|
+
targetId: null,
|
|
163
|
+
fulfillmentLocationId: null,
|
|
164
|
+
total: rate.price,
|
|
165
|
+
estimatedDays: rate.estimatedDeliveryDays ?? null,
|
|
166
|
+
scheduledDate: null,
|
|
167
|
+
scheduledTime: null,
|
|
168
|
+
serviceCode: null,
|
|
169
|
+
sellerId: null,
|
|
170
|
+
shippingProfileId: null
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function snapshot(client) {
|
|
174
|
+
const [settings, lines] = await Promise.all([client.getSettings(), items(client)]);
|
|
175
|
+
const address = state.address ?? await previewAddress(settings.store);
|
|
176
|
+
const subtotal = lines.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0);
|
|
177
|
+
const discount = state.codes.length > 0 ? Math.round(subtotal * .1 * 100) / 100 : 0;
|
|
178
|
+
const shipping = lines.some((item) => item.requiresShipping) ? shippingMethod() : null;
|
|
179
|
+
const shippingTotal = shipping?.total ?? 0;
|
|
180
|
+
return {
|
|
181
|
+
id: "preview-cart",
|
|
182
|
+
token: PREVIEW_CART_TOKEN,
|
|
183
|
+
cartNumber: "1043",
|
|
184
|
+
email: state.buyer.email,
|
|
185
|
+
phone: state.buyer.phone,
|
|
186
|
+
firstName: state.buyer.firstName,
|
|
187
|
+
lastName: state.buyer.lastName,
|
|
188
|
+
currencyCode: settings.store.currency,
|
|
189
|
+
status: "inProgress",
|
|
190
|
+
completedAt: null,
|
|
191
|
+
shippingAddress: address,
|
|
192
|
+
billingAddress: address,
|
|
193
|
+
promotionCodes: state.codes,
|
|
194
|
+
items: lines,
|
|
195
|
+
shippingMethods: shipping ? [shipping] : [],
|
|
196
|
+
paymentMethodCode: state.method,
|
|
197
|
+
totals: {
|
|
198
|
+
subtotal,
|
|
199
|
+
discountTotal: discount,
|
|
200
|
+
shippingOriginalTotal: shippingTotal,
|
|
201
|
+
shippingTotal,
|
|
202
|
+
taxTotal: 0,
|
|
203
|
+
warrantyTotal: 0,
|
|
204
|
+
total: subtotal - discount + shippingTotal
|
|
205
|
+
},
|
|
206
|
+
invoiceType: state.buyer.invoiceType,
|
|
207
|
+
identificationCountryCode: state.buyer.identificationCountryCode,
|
|
208
|
+
identificationType: state.buyer.identificationType,
|
|
209
|
+
identificationNumber: state.buyer.identificationNumber,
|
|
210
|
+
entityTaxId: state.buyer.entityTaxId,
|
|
211
|
+
entityName: state.buyer.entityName
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async function paymentMethods(client) {
|
|
215
|
+
const configured = await client.getPaymentMethods().catch(() => []);
|
|
216
|
+
if (configured.length === 0) return SAMPLE_METHODS;
|
|
217
|
+
return configured.map((method, index) => ({
|
|
218
|
+
code: method.code,
|
|
219
|
+
name: method.name,
|
|
220
|
+
description: null,
|
|
221
|
+
kind: method.kind,
|
|
222
|
+
isActive: true,
|
|
223
|
+
isDefault: index === 0,
|
|
224
|
+
isManual: method.kind === "offline",
|
|
225
|
+
sortOrder: method.sortOrder,
|
|
226
|
+
providerId: null,
|
|
227
|
+
checkoutMode: null,
|
|
228
|
+
brands: method.brands,
|
|
229
|
+
bankAccounts: [],
|
|
230
|
+
publicConfiguration: {}
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
async function add(client, variantId, quantity) {
|
|
234
|
+
const lines = await items(client);
|
|
235
|
+
const existing = lines.find((item) => item.variantId === variantId);
|
|
236
|
+
if (existing) {
|
|
237
|
+
state.items = lines.map((item) => item === existing ? {
|
|
238
|
+
...item,
|
|
239
|
+
quantity: item.quantity + quantity
|
|
240
|
+
} : item);
|
|
241
|
+
return snapshot(client);
|
|
242
|
+
}
|
|
243
|
+
const known = variants.get(variantId);
|
|
244
|
+
if (known) state.items = [...lines, {
|
|
245
|
+
...known,
|
|
246
|
+
quantity
|
|
247
|
+
}];
|
|
248
|
+
return snapshot(client);
|
|
249
|
+
}
|
|
250
|
+
async function setQuantity(client, id, quantity) {
|
|
251
|
+
const lines = await items(client);
|
|
252
|
+
if (quantity <= 0) state.items = lines.filter((item) => item.id !== id);
|
|
253
|
+
else state.items = lines.map((item) => item.id === id ? {
|
|
254
|
+
...item,
|
|
255
|
+
quantity
|
|
256
|
+
} : item);
|
|
257
|
+
return snapshot(client);
|
|
258
|
+
}
|
|
259
|
+
function shippingOptions() {
|
|
260
|
+
return { groups: [{
|
|
261
|
+
sellerId: null,
|
|
262
|
+
sellerName: null,
|
|
263
|
+
shippingProfileId: null,
|
|
264
|
+
rates: RATES
|
|
265
|
+
}] };
|
|
266
|
+
}
|
|
267
|
+
function ours(params) {
|
|
268
|
+
return params.cartToken === PREVIEW_CART_TOKEN;
|
|
269
|
+
}
|
|
270
|
+
function previewCart(client) {
|
|
271
|
+
return {
|
|
272
|
+
getProductBySlug: async (slug, options) => {
|
|
273
|
+
const product = await client.getProductBySlug(slug, options);
|
|
274
|
+
rememberProduct(product);
|
|
275
|
+
return product;
|
|
276
|
+
},
|
|
277
|
+
createCart: () => snapshot(client),
|
|
278
|
+
getCart: (params) => ours(params) ? snapshot(client) : client.getCart(params),
|
|
279
|
+
addCartItem: (params) => ours(params) ? add(client, params.variantId, params.quantity) : client.addCartItem(params),
|
|
280
|
+
updateCartItemQuantity: (params) => ours(params) ? setQuantity(client, params.cartItemId, params.quantity) : client.updateCartItemQuantity(params),
|
|
281
|
+
removeCartItem: (params) => ours(params) ? setQuantity(client, params.cartItemId, 0) : client.removeCartItem(params),
|
|
282
|
+
getCartCheckout: async (params) => {
|
|
283
|
+
if (!ours(params)) return client.getCartCheckout(params);
|
|
284
|
+
const [cart, methods] = await Promise.all([snapshot(client), paymentMethods(client)]);
|
|
285
|
+
return {
|
|
286
|
+
cart,
|
|
287
|
+
paymentMethods: { methods: methods.map((method) => ({
|
|
288
|
+
...method,
|
|
289
|
+
discountAmount: null
|
|
290
|
+
})) },
|
|
291
|
+
orderBumps: []
|
|
292
|
+
};
|
|
293
|
+
},
|
|
294
|
+
getShippingOptions: (params) => ours(params) ? Promise.resolve(shippingOptions()) : client.getShippingOptions(params),
|
|
295
|
+
putCartShippingMethod: (params) => {
|
|
296
|
+
if (!ours(params)) return client.putCartShippingMethod(params);
|
|
297
|
+
state.rate = params.shippingMethodId;
|
|
298
|
+
return snapshot(client);
|
|
299
|
+
},
|
|
300
|
+
putCartPaymentMethod: (params) => {
|
|
301
|
+
if (!ours(params)) return client.putCartPaymentMethod(params);
|
|
302
|
+
state.method = params.paymentMethodCode;
|
|
303
|
+
return snapshot(client);
|
|
304
|
+
},
|
|
305
|
+
patchCartBuyer: (params) => {
|
|
306
|
+
if (!ours(params)) return client.patchCartBuyer(params);
|
|
307
|
+
state.buyer = {
|
|
308
|
+
email: params.email,
|
|
309
|
+
firstName: params.firstName,
|
|
310
|
+
lastName: params.lastName,
|
|
311
|
+
phone: params.phone,
|
|
312
|
+
identificationCountryCode: params.identificationCountryCode ?? null,
|
|
313
|
+
identificationType: params.identificationType ?? null,
|
|
314
|
+
identificationNumber: params.identificationNumber ?? null,
|
|
315
|
+
entityTaxId: params.entityTaxId ?? null,
|
|
316
|
+
entityName: params.entityName ?? null,
|
|
317
|
+
invoiceType: params.invoiceType ?? state.buyer.invoiceType
|
|
318
|
+
};
|
|
319
|
+
return snapshot(client);
|
|
320
|
+
},
|
|
321
|
+
patchCartAddresses: async (params) => {
|
|
322
|
+
if (!ours(params)) return client.patchCartAddresses(params);
|
|
323
|
+
const address = params.shippingAddress;
|
|
324
|
+
if (address) state.address = {
|
|
325
|
+
name: address.name,
|
|
326
|
+
address1: address.address1,
|
|
327
|
+
city: address.city,
|
|
328
|
+
countryCode: address.countryCode,
|
|
329
|
+
company: null,
|
|
330
|
+
address2: address.address2 ?? null,
|
|
331
|
+
department: address.department ?? null,
|
|
332
|
+
province: address.province ?? null,
|
|
333
|
+
postalCode: address.postalCode ?? null,
|
|
334
|
+
district: address.district ?? null,
|
|
335
|
+
phone: address.phone ?? null,
|
|
336
|
+
latitude: null,
|
|
337
|
+
longitude: null
|
|
338
|
+
};
|
|
339
|
+
return snapshot(client);
|
|
340
|
+
},
|
|
341
|
+
addCartPromotionCode: (params) => {
|
|
342
|
+
if (!ours(params)) return client.addCartPromotionCode(params);
|
|
343
|
+
if (!state.codes.includes(params.code)) state.codes = [...state.codes, params.code];
|
|
344
|
+
return snapshot(client);
|
|
345
|
+
},
|
|
346
|
+
removeCartPromotionCode: (params) => {
|
|
347
|
+
if (!ours(params)) return client.removeCartPromotionCode(params);
|
|
348
|
+
state.codes = state.codes.filter((code) => code !== params.code);
|
|
349
|
+
return snapshot(client);
|
|
350
|
+
},
|
|
351
|
+
uploadPaymentReceipt: (params) => ours(params) ? Promise.resolve({
|
|
352
|
+
id: "preview-receipt",
|
|
353
|
+
url: ""
|
|
354
|
+
}) : client.uploadPaymentReceipt(params),
|
|
355
|
+
checkoutCart: async (params) => {
|
|
356
|
+
if (!ours(params)) return client.checkoutCart(params);
|
|
357
|
+
const cart = await snapshot(client);
|
|
358
|
+
state.items = null;
|
|
359
|
+
state.codes = [];
|
|
360
|
+
state.method = null;
|
|
361
|
+
return {
|
|
362
|
+
orderId: "preview-order-1",
|
|
363
|
+
orderNumber: "1",
|
|
364
|
+
orderStatusUrl: "/orders/preview-order-1",
|
|
365
|
+
orderGroup: "preview-order-group",
|
|
366
|
+
orderIds: ["preview-order-1"],
|
|
367
|
+
payment: null,
|
|
368
|
+
cart: {
|
|
369
|
+
...cart,
|
|
370
|
+
status: "completed"
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
export { PREVIEW_CART_TOKEN, paymentMethods, previewCart, rememberProduct };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/product-preview.ts
|
|
2
|
+
const BAR_ID = "ecomiq-product-preview";
|
|
3
|
+
const BAR = `<div id="${BAR_ID}" role="region" aria-label="Vista previa"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12Z"/><circle cx="12" cy="12" r="3"/></svg><strong>Vista previa</strong><span>Este producto no está publicado. Solo tú lo ves.</span><button type="button">Ocultar barra</button></div><style>${[
|
|
4
|
+
`#${BAR_ID}{position:fixed;left:0;right:0;bottom:0;z-index:2147483647;box-sizing:border-box;display:flex;align-items:center;gap:10px;height:46px;margin:0;padding:0 16px;background:#1f1f1f;color:#fff;font:14px/1.2 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;text-align:left}`,
|
|
5
|
+
`#${BAR_ID} svg{display:block;flex:none}`,
|
|
6
|
+
`#${BAR_ID} strong{flex:none;font-weight:600}`,
|
|
7
|
+
`#${BAR_ID} span{flex:1;min-width:0;overflow:hidden;color:#a3a3a3;white-space:nowrap;text-overflow:ellipsis}`,
|
|
8
|
+
`#${BAR_ID} button{flex:none;margin:0;padding:6px 12px;border:1px solid #4d4d4d;border-radius:6px;background:transparent;color:#fff;font:inherit;cursor:pointer}`,
|
|
9
|
+
`#${BAR_ID} button:hover{background:#2e2e2e}`,
|
|
10
|
+
`body:has(#${BAR_ID}){padding-bottom:46px}`
|
|
11
|
+
].join("")}</style><script>${`(()=>{const bar=document.getElementById("${BAR_ID}");if(!bar)return;const path=location.pathname;const timer=setInterval(()=>{if(location.pathname!==path)hide()},500);function hide(){clearInterval(timer);bar.remove()}bar.querySelector("button").addEventListener("click",hide)})()`}<\/script>`;
|
|
12
|
+
function productPreviewFrom(request) {
|
|
13
|
+
const key = new URL(request.url).searchParams.get("preview_key");
|
|
14
|
+
if (!key) return void 0;
|
|
15
|
+
return {
|
|
16
|
+
key,
|
|
17
|
+
shown: false
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function productPreviewClient(client, preview) {
|
|
21
|
+
return {
|
|
22
|
+
...client,
|
|
23
|
+
resolveUrl: async (path) => {
|
|
24
|
+
const resolved = await client.resolveUrl(path, { previewKey: preview.key });
|
|
25
|
+
if (resolved?.kind === "product" && resolved.product.isPreview) preview.shown = true;
|
|
26
|
+
return resolved;
|
|
27
|
+
},
|
|
28
|
+
getProductBySlug: async (slug) => {
|
|
29
|
+
const product = await client.getProductBySlug(slug, { previewKey: preview.key });
|
|
30
|
+
if (product.isPreview) preview.shown = true;
|
|
31
|
+
return product;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function productPreviewResponse(response) {
|
|
36
|
+
const headers = new Headers(response.headers);
|
|
37
|
+
headers.set("Cache-Control", "private, no-store");
|
|
38
|
+
headers.set("X-Robots-Tag", "noindex");
|
|
39
|
+
const init = {
|
|
40
|
+
status: response.status,
|
|
41
|
+
statusText: response.statusText,
|
|
42
|
+
headers
|
|
43
|
+
};
|
|
44
|
+
if (!headers.get("Content-Type")?.includes("text/html")) return new Response(response.body, init);
|
|
45
|
+
headers.delete("Content-Length");
|
|
46
|
+
const html = await response.text();
|
|
47
|
+
const end = html.lastIndexOf("</body>");
|
|
48
|
+
if (end === -1) return new Response(html + BAR, init);
|
|
49
|
+
return new Response(html.slice(0, end) + BAR + html.slice(end), init);
|
|
50
|
+
}
|
|
51
|
+
export { productPreviewClient, productPreviewFrom, productPreviewResponse };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/product-variants.ts
|
|
2
|
+
function isVariantAvailable(variant) {
|
|
3
|
+
return variant.isAvailable !== false;
|
|
4
|
+
}
|
|
5
|
+
function variantOptions(variants) {
|
|
6
|
+
const groups = /* @__PURE__ */ new Map();
|
|
7
|
+
for (const variant of variants) for (const option of variant.options) {
|
|
8
|
+
const group = groups.get(option.key) ?? {
|
|
9
|
+
name: option.name,
|
|
10
|
+
values: []
|
|
11
|
+
};
|
|
12
|
+
if (!group.values.includes(option.value)) group.values.push(option.value);
|
|
13
|
+
groups.set(option.key, group);
|
|
14
|
+
}
|
|
15
|
+
return [...groups.entries()].map(([key, group]) => ({
|
|
16
|
+
key,
|
|
17
|
+
...group
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
function pickVariant(variants, current, key, value) {
|
|
21
|
+
const wanted = current.options.map((option) => {
|
|
22
|
+
if (option.key === key) return {
|
|
23
|
+
...option,
|
|
24
|
+
value
|
|
25
|
+
};
|
|
26
|
+
return option;
|
|
27
|
+
});
|
|
28
|
+
const exact = variants.find((variant) => wanted.every((option) => variant.options.some((candidate) => candidate.key === option.key && candidate.value === option.value)));
|
|
29
|
+
if (exact) return exact;
|
|
30
|
+
return variants.find((variant) => variant.options.some((option) => option.key === key && option.value === value)) ?? null;
|
|
31
|
+
}
|
|
32
|
+
function variantSwatches(variants, key, values) {
|
|
33
|
+
const images = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const value of values) {
|
|
35
|
+
const image = variants.find((variant) => variant.options.some((option) => option.key === key && option.value === value) && variant.images.some((image) => image.type === "image"))?.images.filter((candidate) => candidate.type === "image").sort((a, b) => a.order - b.order)[0];
|
|
36
|
+
if (image === void 0) return null;
|
|
37
|
+
images.set(value, image.url);
|
|
38
|
+
}
|
|
39
|
+
if (new Set(images.values()).size < values.length) return null;
|
|
40
|
+
return images;
|
|
41
|
+
}
|
|
42
|
+
function discountPercent(value, compareAt) {
|
|
43
|
+
if (compareAt == null || compareAt <= value || compareAt <= 0) return 0;
|
|
44
|
+
return Math.round((compareAt - value) / compareAt * 100);
|
|
45
|
+
}
|
|
46
|
+
export { discountPercent, isVariantAvailable, pickVariant, variantOptions, variantSwatches };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ProductDetail } from "@ecomiq/core";
|
|
2
|
+
export type ProductVariant = ProductDetail["variants"][number];
|
|
3
|
+
export type VariantOption = {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
values: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function isVariantAvailable(variant: ProductVariant): boolean;
|
|
9
|
+
export declare function variantOptions(variants: ProductVariant[]): VariantOption[];
|
|
10
|
+
export declare function pickVariant(variants: ProductVariant[], current: ProductVariant, key: string, value: string): ProductVariant | null;
|
|
11
|
+
export declare function variantSwatches(variants: ProductVariant[], key: string, values: string[]): Map<string, string> | null;
|
|
12
|
+
export declare function discountPercent(value: number, compareAt: number | null | undefined): number;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { text } from "./form-BtQcbXlJ.js";
|
|
2
|
+
import { customer, customerHeaders } from "./session-CKvmFJyg.js";
|
|
3
|
+
import { found, store, storeHeaders } from "./store-8Q-_LFrQ.js";
|
|
4
|
+
import { data, redirect } from "react-router";
|
|
5
|
+
import { ApiError, getOrderReviewContext, getOrderTracking, sanitizeHtml } from "@ecomiq/core";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
// src/public-pages.ts
|
|
8
|
+
const SUGGESTION_MIN_LENGTH = 2;
|
|
9
|
+
const SUGGESTION_MAX_LENGTH = 80;
|
|
10
|
+
const SUGGESTION_LIMIT = 6;
|
|
11
|
+
const PageContent = z.object({
|
|
12
|
+
title: z.string().optional(),
|
|
13
|
+
html: z.string().optional(),
|
|
14
|
+
seo: z.object({
|
|
15
|
+
title: z.string().nullish(),
|
|
16
|
+
description: z.string().nullish()
|
|
17
|
+
}).optional()
|
|
18
|
+
});
|
|
19
|
+
function places(items) {
|
|
20
|
+
return items.map((item) => ({
|
|
21
|
+
code: item.code,
|
|
22
|
+
name: item.name
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
async function loadGeo(request, context) {
|
|
26
|
+
const client = store(context);
|
|
27
|
+
const params = new URL(request.url).searchParams;
|
|
28
|
+
const { store: settings } = await client.getSettings();
|
|
29
|
+
const countryCode = settings.countryCode;
|
|
30
|
+
const department = params.get("department");
|
|
31
|
+
const province = params.get("province");
|
|
32
|
+
const none = [];
|
|
33
|
+
const [departments, provinces, districts] = await Promise.all([
|
|
34
|
+
client.getDepartments({ countryCode }).catch(() => none),
|
|
35
|
+
department ? client.getProvinces({
|
|
36
|
+
countryCode,
|
|
37
|
+
departmentCode: department
|
|
38
|
+
}).catch(() => none) : none,
|
|
39
|
+
province ? client.getDistricts({
|
|
40
|
+
countryCode,
|
|
41
|
+
provinceCode: province
|
|
42
|
+
}).catch(() => none) : none
|
|
43
|
+
]);
|
|
44
|
+
return {
|
|
45
|
+
departments: places(departments),
|
|
46
|
+
provinces: places(provinces),
|
|
47
|
+
districts: places(districts)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function loadSearchSuggestions(request, context) {
|
|
51
|
+
const q = new URL(request.url).searchParams.get("q")?.trim() ?? "";
|
|
52
|
+
if (q.length < SUGGESTION_MIN_LENGTH) return {
|
|
53
|
+
q,
|
|
54
|
+
products: []
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
q,
|
|
58
|
+
products: await store(context).autocompleteProducts({
|
|
59
|
+
search: q.slice(0, SUGGESTION_MAX_LENGTH),
|
|
60
|
+
limit: SUGGESTION_LIMIT
|
|
61
|
+
}).catch(() => [])
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function loadTracking(request, context, code) {
|
|
65
|
+
const typed = new URL(request.url).searchParams.get("code")?.trim();
|
|
66
|
+
if (typed) throw redirect(`/track/${encodeURIComponent(typed)}`);
|
|
67
|
+
const client = store(context);
|
|
68
|
+
const settings = await client.getSettings();
|
|
69
|
+
const place = {
|
|
70
|
+
language: `${settings.store.language}-${settings.store.countryCode}`,
|
|
71
|
+
timeZone: settings.store.timeZone
|
|
72
|
+
};
|
|
73
|
+
if (!code) return {
|
|
74
|
+
code: "",
|
|
75
|
+
tracking: null,
|
|
76
|
+
missing: false,
|
|
77
|
+
...place
|
|
78
|
+
};
|
|
79
|
+
const tracking = await getOrderTracking(client, code, await storeHeaders(client)).catch(() => null);
|
|
80
|
+
return {
|
|
81
|
+
code,
|
|
82
|
+
tracking,
|
|
83
|
+
missing: tracking === null,
|
|
84
|
+
...place
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function loadReview(context, token) {
|
|
88
|
+
const client = store(context);
|
|
89
|
+
return { review: await found(getOrderReviewContext(client, token, await storeHeaders(client)), (status) => status < 500) };
|
|
90
|
+
}
|
|
91
|
+
async function reviewAction(request, context, token) {
|
|
92
|
+
const client = store(context);
|
|
93
|
+
const form = await request.formData();
|
|
94
|
+
const review = await found(getOrderReviewContext(client, token, await storeHeaders(client)), (status) => status < 500);
|
|
95
|
+
const rating = Number(text(form, "rating"));
|
|
96
|
+
const content = text(form, "content");
|
|
97
|
+
const name = text(form, "name");
|
|
98
|
+
if (!Number.isInteger(rating) || rating < 1 || rating > 5 || !content || !name) return data({
|
|
99
|
+
ok: false,
|
|
100
|
+
error: "Elige una calificación y cuéntanos tu experiencia."
|
|
101
|
+
}, { status: 400 });
|
|
102
|
+
try {
|
|
103
|
+
await client.createProductReview({
|
|
104
|
+
productId: text(form, "productId"),
|
|
105
|
+
rating,
|
|
106
|
+
content,
|
|
107
|
+
title: text(form, "title") || void 0,
|
|
108
|
+
reviewerName: name,
|
|
109
|
+
reviewerEmail: review.email ?? "",
|
|
110
|
+
orderId: review.orderId,
|
|
111
|
+
reviewToken: token
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
ok: true,
|
|
115
|
+
error: null
|
|
116
|
+
};
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (error instanceof ApiError && error.status === 409) return data({
|
|
119
|
+
ok: false,
|
|
120
|
+
error: "Ya opinaste sobre este producto."
|
|
121
|
+
}, { status: 400 });
|
|
122
|
+
return data({
|
|
123
|
+
ok: false,
|
|
124
|
+
error: "No pudimos guardar tu opinión."
|
|
125
|
+
}, { status: 400 });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function productReviewAction(request, context) {
|
|
129
|
+
const current = await customer(request, context);
|
|
130
|
+
if (current === null) return data({
|
|
131
|
+
ok: false,
|
|
132
|
+
error: "Inicia sesión para dejar tu opinión."
|
|
133
|
+
}, { status: 401 });
|
|
134
|
+
const form = await request.formData();
|
|
135
|
+
const rating = Number(text(form, "rating"));
|
|
136
|
+
const content = text(form, "content");
|
|
137
|
+
const name = text(form, "name");
|
|
138
|
+
if (!Number.isInteger(rating) || rating < 1 || rating > 5 || !content || !name) return data({
|
|
139
|
+
ok: false,
|
|
140
|
+
error: "Elige una calificación, escribe tu nombre y cuéntanos tu experiencia."
|
|
141
|
+
}, { status: 400 });
|
|
142
|
+
try {
|
|
143
|
+
await store(context).createCustomerProductReview({
|
|
144
|
+
productId: text(form, "productId"),
|
|
145
|
+
rating,
|
|
146
|
+
content,
|
|
147
|
+
title: text(form, "title") || void 0,
|
|
148
|
+
reviewerName: name
|
|
149
|
+
}, customerHeaders(current));
|
|
150
|
+
return {
|
|
151
|
+
ok: true,
|
|
152
|
+
error: null
|
|
153
|
+
};
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (error instanceof ApiError && error.status === 409) return data({
|
|
156
|
+
ok: false,
|
|
157
|
+
error: "Ya opinaste sobre este producto."
|
|
158
|
+
}, { status: 400 });
|
|
159
|
+
if (error instanceof ApiError && error.code === "Customers.ProfileRequired") return data({
|
|
160
|
+
ok: false,
|
|
161
|
+
error: "Completa tu perfil para dejar tu opinión."
|
|
162
|
+
}, { status: 400 });
|
|
163
|
+
return data({
|
|
164
|
+
ok: false,
|
|
165
|
+
error: "No pudimos guardar tu opinión."
|
|
166
|
+
}, { status: 400 });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function readPage(context, handle) {
|
|
170
|
+
const page = await store(context).getPageBySlug(handle).catch((error) => {
|
|
171
|
+
if (error instanceof ApiError && error.status === 404) return null;
|
|
172
|
+
throw error;
|
|
173
|
+
});
|
|
174
|
+
if (page === null) return null;
|
|
175
|
+
return pageData(page);
|
|
176
|
+
}
|
|
177
|
+
async function loadPage(context, handle) {
|
|
178
|
+
return pageData(await found(store(context).getPageBySlug(handle)));
|
|
179
|
+
}
|
|
180
|
+
function pageData(page) {
|
|
181
|
+
const parsed = PageContent.safeParse(page.settings);
|
|
182
|
+
let content = {};
|
|
183
|
+
if (parsed.success) content = parsed.data;
|
|
184
|
+
return {
|
|
185
|
+
title: content.title ?? page.name,
|
|
186
|
+
html: sanitizeHtml(content.html ?? ""),
|
|
187
|
+
layout: page.layout,
|
|
188
|
+
seo: {
|
|
189
|
+
title: content.seo?.title ?? content.title ?? page.name,
|
|
190
|
+
description: content.seo?.description ?? ""
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
export { loadGeo, loadPage, loadReview, loadSearchSuggestions, loadTracking, productReviewAction, readPage, reviewAction };
|