@asteby/storefront-react 0.13.1 → 0.14.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/README.md +2 -0
- package/dist/checkout.cjs +20 -2
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +20 -3
- package/dist/checkout.d.ts +20 -3
- package/dist/checkout.js +20 -3
- package/dist/checkout.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -542,6 +542,8 @@ import '@asteby/storefront-react/checkout.css' // opcional: disposición, insign
|
|
|
542
542
|
|
|
543
543
|
Cotizaciones largas (`layout="recommended"`): con 10+ servicios, la lista plana obliga a comparar todo. Con `layout="recommended"` se ven hasta tres tarifas (`recommendedCount`) con su etiqueta: la más económica, la más rápida y la de mejor equilibrio precio-tiempo («Recomendado»); el resto queda en «Ver más opciones (N)» (`<details>`, funciona sin JavaScript) agrupado por paquetería, con la marca y el nombre UNA vez por grupo (cada radio conserva su nombre completo para lectores de pantalla). Los servicios repetidos (misma paquetería y servicio cotizados por dos proveedores) se quedan con el más barato. Si la tarifa elegida está dentro, la lista se abre sola (también en el HTML del servidor). La lógica pura está en `recommendRates()` / `dedupeRates()`. `error` (+ `onRetry`) muestra un aviso amable con «Intentar de nuevo» cuando no se pudo cotizar.
|
|
544
544
|
|
|
545
|
+
Una sola lista (`layout="flat"`): como en la mayoría de los ecommerce. Muestra TODAS las tarifas en una lista plana, de menor a mayor precio, sin `<details>` ni grupos; cada fila lleva la marca de la paquetería, el nombre completo, el servicio, el tiempo y el precio. Los servicios repetidos (misma paquetería y servicio de dos proveedores) se quedan con el más barato, y las etiquetas «Más económico», «Más rápido» y «Recomendado» (esta última solo en cotizaciones de más de 4 servicios, `recommendedCount`) van sobre las filas que las ganan. La tarifa elegida siempre aparece (aunque sea un servicio repetido) y, sin `defaultValue`, se preselecciona la primera fila, la más barata. Son radios nativos con el mismo `name` (grupo de radio sin JavaScript); envuélvelos en tu `<fieldset><legend>`. Decisión de API: es un tercer valor de `layout`, no otra prop, para no tocar `list` ni `recommended`; la lógica pura está en `flatRates()`.
|
|
546
|
+
|
|
545
547
|
Tarifa vencida o cambiada: si guardar la entrega falla con `isQuoteChange(err)` (códigos `quote_expired`/`rate_expired`…, un 409, o el 422 genérico de servidores anteriores), la tienda recarga las tarifas conservando la dirección, vuelve a elegir el mismo servicio con `matchRate(anterior, nuevas)`, pasa `requoted` a `DeliveryOptions` y resuelve `syncDelivery` con `'requote'`: `PaymentMethodSection` muestra un aviso (no un error) y vuelve a intentar con la nueva tarifa.
|
|
546
548
|
|
|
547
549
|
### Campos, validación en línea y resumen del pedido
|
package/dist/checkout.cjs
CHANGED
|
@@ -843,6 +843,17 @@ function recommendRates(input, options = {}) {
|
|
|
843
843
|
const more = [...groups.values()];
|
|
844
844
|
return { recommended, more, moreCount: more.reduce((n, g) => n + g.rates.length, 0) };
|
|
845
845
|
}
|
|
846
|
+
function flatRates(input, options = {}) {
|
|
847
|
+
const count = options.count ?? 3;
|
|
848
|
+
const rates = options.dedupe === false ? [...input] : dedupeRates(input);
|
|
849
|
+
const tags = /* @__PURE__ */ new Map();
|
|
850
|
+
for (const { rate, tags: t } of recommendRates(rates, { count, dedupe: false }).recommended) tags.set(rate, t);
|
|
851
|
+
const list = [...rates];
|
|
852
|
+
const kept = options.keepId ? input.find((r) => r.id === options.keepId) : void 0;
|
|
853
|
+
if (kept && !list.includes(kept)) list.push(kept);
|
|
854
|
+
const byCost = (a, b) => (costOf(a) ?? Infinity) - (costOf(b) ?? Infinity);
|
|
855
|
+
return list.sort(byCost).map((rate) => ({ rate, tags: tags.get(rate) ?? [] }));
|
|
856
|
+
}
|
|
846
857
|
|
|
847
858
|
// src/checkout/delivery.ts
|
|
848
859
|
var ES4 = {
|
|
@@ -1031,7 +1042,13 @@ function DeliveryOptions(props) {
|
|
|
1031
1042
|
const m = react.useMemo(() => deliveryMessages(locale, props.messages), [locale, props.messages]);
|
|
1032
1043
|
const hydrated = useHydrated();
|
|
1033
1044
|
const badges = react.useMemo(() => showBadges ? rateBadges(rates) : /* @__PURE__ */ new Map(), [rates, showBadges]);
|
|
1034
|
-
const
|
|
1045
|
+
const flat = react.useMemo(
|
|
1046
|
+
() => layout === "flat" ? flatRates(rates, { count: props.recommendedCount ?? 3, keepId: value ? rates.find((r) => rateValue(r) === value)?.id ?? null : null }) : null,
|
|
1047
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1048
|
+
[layout, rates, props.recommendedCount, value]
|
|
1049
|
+
);
|
|
1050
|
+
const firstRate = flat ? flat[0]?.rate : rates[0];
|
|
1051
|
+
const firstValue = firstRate ? rateValue(firstRate) : null;
|
|
1035
1052
|
const defaultValue = props.defaultValue === void 0 ? firstValue : props.defaultValue;
|
|
1036
1053
|
const amount = (money) => Number(money.amount) === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.free, "data-sf-delivery-free": true, children: m.free }) : renderAmount ? renderAmount(money) : storefront.formatMoney(money, locale);
|
|
1037
1054
|
const mode = props.quoteNote ?? "always";
|
|
@@ -1097,7 +1114,7 @@ function DeliveryOptions(props) {
|
|
|
1097
1114
|
] }) : null,
|
|
1098
1115
|
children,
|
|
1099
1116
|
loading && rates.length === 0 ? [0, 1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx.skeleton, "data-sf-delivery-skeleton": true, "aria-hidden": "true" }, i)) : null,
|
|
1100
|
-
plan ? plan.recommended.map(({ rate, tags }) => rateRow(rate, { tags: showBadges ? tags : [] })) : rates.map((rate) => rateRow(rate, { tags: badges.get(rate.id) ?? [] })),
|
|
1117
|
+
flat ? flat.map(({ rate, tags }) => rateRow(rate, { tags: showBadges ? tags : [] })) : plan ? plan.recommended.map(({ rate, tags }) => rateRow(rate, { tags: showBadges ? tags : [] })) : rates.map((rate) => rateRow(rate, { tags: badges.get(rate.id) ?? [] })),
|
|
1101
1118
|
plan && plan.moreCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cx.more, "data-sf-delivery-more": true, ...inMore ? { open: true } : {}, children: [
|
|
1102
1119
|
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: cx.moreSummary, "data-sf-delivery-more-summary": true, children: m.moreOptions.replace("{n}", String(plan.moreCount)) }),
|
|
1103
1120
|
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-sf-delivery-groups": true, children: plan.more.map((g) => {
|
|
@@ -1141,6 +1158,7 @@ exports.dedupeRates = dedupeRates;
|
|
|
1141
1158
|
exports.deliveryMessages = deliveryMessages;
|
|
1142
1159
|
exports.fieldMessages = fieldMessages;
|
|
1143
1160
|
exports.findBrand = findBrand;
|
|
1161
|
+
exports.flatRates = flatRates;
|
|
1144
1162
|
exports.isQuoteChange = isQuoteChange;
|
|
1145
1163
|
exports.listBrands = listBrands;
|
|
1146
1164
|
exports.matchRate = matchRate;
|