fix(ecommerce): imagen principal cortaba cabeza + fuente grande + sugerido duplicado
- Imagen principal del producto pasa de object-cover a object-contain (mismo motivo que las miniaturas del commit anterior): la foto vertical de Buzz Lightyear (933x1500) aparecía sin cabeza al seleccionarla, reportado en vivo con captura real. - Descripción del producto baja de 16px a 14px (text-sm leading-6, mismo tamaño que los párrafos secundarios de /envios y /cambios) -- seguía viéndose grande al lado del resto de la columna. - El buy-box mostraba los mismos 2 productos que ya aparecían en el carrusel "También te puede gustar" de abajo (ambos usaban el mismo cálculo de categoría/colección). Ahora el buy-box sugiere 1 producto de una categoría DISTINTA -- cross-sell real en vez de duplicado. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
This commit is contained in:
1 parent
4009fde072
commit
545062c3ef
2 files changed
+21
-10
No files matched your search
@@ -34,7 +34,13 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
if (!product) notFound();
|
if (!product) notFound();
|
||||||
const products = await getProducts();
|
const products = await getProducts();
|
||||||
const recommended = products.filter((candidate) => candidate.id !== product.id && (candidate.category === product.category || candidate.collection === product.collection)).slice(0, 8);
|
const recommended = products.filter((candidate) => candidate.id !== product.id && (candidate.category === product.category || candidate.collection === product.collection)).slice(0, 8);
|
||||||
const suggestions = recommended.slice(0, 2);
|
// Categoría distinta a propósito -- antes repetía los primeros 2 del
|
||||||
|
// mismo "recommended" que ya alimenta el carrusel de abajo (mismos
|
||||||
|
// productos en dos lugares de la página, reportado por el usuario).
|
||||||
|
// Un cross-sell real de otra categoría aporta algo que el carrusel no
|
||||||
|
// muestra, en vez de duplicarlo.
|
||||||
|
const crossCategory = products.filter((candidate) => candidate.id !== product.id && candidate.category !== product.category);
|
||||||
|
const crossSell = crossCategory.find((candidate) => candidate.available) ?? crossCategory[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -55,7 +61,7 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">{product.category} · {product.collection}</span>
|
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">{product.category} · {product.collection}</span>
|
||||||
<h1 className="mt-3 text-4xl font-black tracking-tight sm:text-6xl">{product.name}</h1>
|
<h1 className="mt-3 text-4xl font-black tracking-tight sm:text-6xl">{product.name}</h1>
|
||||||
<p className="mt-5 text-base leading-7 text-slate-600">{product.description}</p>
|
<p className="mt-5 text-sm leading-6 text-slate-600">{product.description}</p>
|
||||||
{/* Antes escondido detrás de un click en el acordeón --
|
{/* Antes escondido detrás de un click en el acordeón --
|
||||||
siempre visible, estilo Amazon, con los mismos datos
|
siempre visible, estilo Amazon, con los mismos datos
|
||||||
reales que ya existían (marca/edad/categoría/colección),
|
reales que ya existían (marca/edad/categoría/colección),
|
||||||
@@ -76,19 +82,19 @@ export default async function ProductPage({ params }: ProductPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
{/* Buy box estilo Amazon: precio/variantes/carrito en su propia
|
{/* Buy box estilo Amazon: precio/variantes/carrito en su propia
|
||||||
tarjeta, sticky desde xl mientras el resto de la pagina
|
tarjeta, sticky desde xl mientras el resto de la pagina
|
||||||
scrollea. Los sugeridos (hasta 2) usan el mismo cálculo de
|
scrollea. El cross-sell es de OTRA categoría a propósito --
|
||||||
"recommended" que ya alimenta el carrusel de abajo -- mismo
|
evita repetir lo que ya muestra el carrusel de "También te
|
||||||
criterio real (categoría/colección), no un dato inventado. */}
|
puede gustar" de abajo (mismo criterio de categoría/colección
|
||||||
|
que ese carrusel), aportando un producto genuinamente distinto
|
||||||
|
en vez de duplicado. */}
|
||||||
<div className="min-w-0 xl:sticky xl:top-24 xl:row-span-2 xl:self-start">
|
<div className="min-w-0 xl:sticky xl:top-24 xl:row-span-2 xl:self-start">
|
||||||
<div className="rounded-2xl border border-slate-200 p-6 shadow-sm">
|
<div className="rounded-2xl border border-slate-200 p-6 shadow-sm">
|
||||||
<ProductPurchase product={product} />
|
<ProductPurchase product={product} />
|
||||||
</div>
|
</div>
|
||||||
{suggestions.length > 0 && (
|
{crossSell && (
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<h2 className="mb-4 text-xs font-black uppercase tracking-[.14em] text-slate-500">También te puede interesar</h2>
|
<h2 className="mb-4 text-xs font-black uppercase tracking-[.14em] text-slate-500">También te puede interesar</h2>
|
||||||
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-1">
|
<ProductCard product={crossSell} />
|
||||||
{suggestions.map((item) => <ProductCard key={item.id} product={item} />)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -147,13 +147,18 @@ export function ProductGallery({ images, name }: { images: string[]; name: strin
|
|||||||
(ambos Chromium) y en Chromium headless. unoptimized deja
|
(ambos Chromium) y en Chromium headless. unoptimized deja
|
||||||
un solo recurso real por foto -- sin candidatos entre los
|
un solo recurso real por foto -- sin candidatos entre los
|
||||||
que el bug pueda elegir mal. */}
|
que el bug pueda elegir mal. */}
|
||||||
|
{/* object-contain (no object-cover): mismo motivo que las
|
||||||
|
miniaturas -- fotos verticales (933x1500 confirmado en
|
||||||
|
este catalogo) perdian la cabeza al forzar el cuadrado.
|
||||||
|
Reportado en vivo: al seleccionar esa foto, Buzz aparecia
|
||||||
|
sin cabeza en la imagen principal. */}
|
||||||
<Image
|
<Image
|
||||||
src={selected}
|
src={selected}
|
||||||
alt={name}
|
alt={name}
|
||||||
fill
|
fill
|
||||||
priority
|
priority
|
||||||
unoptimized
|
unoptimized
|
||||||
className="object-cover"
|
className="object-contain"
|
||||||
/>
|
/>
|
||||||
{/* Lupa: recuadro que marca la region ampliada -- solo cuando
|
{/* Lupa: recuadro que marca la region ampliada -- solo cuando
|
||||||
hay lugar real para el panel de al lado (showPanel,
|
hay lugar real para el panel de al lado (showPanel,
|
||||||
|
|||||||
Reference in new issue
Block a user