fix(ecommerce): imagen principal cortaba cabeza + fuente grande + sugerido duplicado
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 23s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 8m28s

- 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:
devopsandClaude Sonnet 5 committed 2026-09-14 02:11:12 +00:00
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,