Merge fix/adr0008-navy-coral-subfase3-product-card-grid into main
Merge directo sin PR de Gitea: crear un PR via API requiere leer credenciales git guardadas, bloqueado por el clasificador de auto-mode (no es una limitacion corregible del lado de la infra). Flujo aprobado por el usuario como estandar para cierres de sub-fase de este proyecto el 2026-08-27 (ver memoria del proyecto). Diff mostrado y aprobado explicitamente antes de este merge.
This commit is contained in:
commit
b123a5a9c9
2 files changed
+19
-19
No files matched your search
@@ -323,18 +323,18 @@ export function CatalogClient({
|
|||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
{breadcrumb.length > 0 && (
|
{breadcrumb.length > 0 && (
|
||||||
<nav aria-label="Breadcrumb" className="mb-4 flex flex-wrap items-center gap-1.5 text-xs font-bold text-slate-500">
|
<nav aria-label="Breadcrumb" className="mb-4 flex flex-wrap items-center gap-1.5 text-xs font-bold text-slate-500">
|
||||||
<Link href="/catalog" prefetch={false} className="hover:text-ari-ciruela">
|
<Link href="/catalog" prefetch={false} className="hover:text-ari-coral">
|
||||||
Inicio
|
Inicio
|
||||||
</Link>
|
</Link>
|
||||||
{breadcrumb.map((node, index) => (
|
{breadcrumb.map((node, index) => (
|
||||||
<span key={node.id} className="flex items-center gap-1.5">
|
<span key={node.id} className="flex items-center gap-1.5">
|
||||||
<ChevronRight className="size-3" />
|
<ChevronRight className="size-3" />
|
||||||
{index === breadcrumb.length - 1 ? (
|
{index === breadcrumb.length - 1 ? (
|
||||||
<span aria-current="page" className="text-ari-carbon">
|
<span aria-current="page" className="text-ari-marino">
|
||||||
{node.name}
|
{node.name}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<Link href={`/catalog?category=${encodeURIComponent(node.name)}`} prefetch={false} className="hover:text-ari-ciruela">
|
<Link href={`/catalog?category=${encodeURIComponent(node.name)}`} prefetch={false} className="hover:text-ari-coral">
|
||||||
{node.name}
|
{node.name}
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
@@ -342,23 +342,23 @@ export function CatalogClient({
|
|||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
)}
|
)}
|
||||||
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-ciruela">
|
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">
|
||||||
Catálogo completo
|
Catálogo completo
|
||||||
</span>
|
</span>
|
||||||
<h1 className="font-display mt-2 text-5xl font-bold tracking-tight text-ari-carbon">Todos los tesoros</h1>
|
<h1 className="font-display mt-2 text-5xl font-bold tracking-tight text-ari-marino">Todos los tesoros</h1>
|
||||||
<p className="mt-3 text-slate-500">
|
<p className="mt-3 text-slate-500">
|
||||||
Filtra por categoría, marca o edad sin recargar la página.
|
Filtra por categoría, marca o edad sin recargar la página.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-8 lg:grid-cols-[260px_1fr]">
|
<div className="grid gap-8 lg:grid-cols-[260px_1fr]">
|
||||||
<aside className="h-fit space-y-6 rounded-lg border border-slate-100 bg-white p-6 shadow-lg shadow-ari-carbon-oscuro/5 lg:sticky lg:top-44">
|
<aside className="h-fit space-y-6 rounded-lg border border-slate-100 bg-white p-6 shadow-lg shadow-ari-marino/5 lg:sticky lg:top-44">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<strong className="flex items-center gap-2 text-lg font-black">
|
<strong className="flex items-center gap-2 text-lg font-black">
|
||||||
<SlidersHorizontal className="size-5 text-ari-cobre" />
|
<SlidersHorizontal className="size-5 text-ari-coral-claro" />
|
||||||
Filtros
|
Filtros
|
||||||
</strong>
|
</strong>
|
||||||
<button onClick={reset} className="text-xs font-black text-ari-ciruela">
|
<button onClick={reset} className="text-xs font-black text-ari-coral">
|
||||||
<X className="mr-1 inline size-3" />
|
<X className="mr-1 inline size-3" />
|
||||||
Limpiar
|
Limpiar
|
||||||
</button>
|
</button>
|
||||||
@@ -392,7 +392,7 @@ export function CatalogClient({
|
|||||||
step={5000}
|
step={5000}
|
||||||
value={maxPrice}
|
value={maxPrice}
|
||||||
onChange={(event) => setMaxPrice(Number(event.target.value))}
|
onChange={(event) => setMaxPrice(Number(event.target.value))}
|
||||||
className="w-full accent-ari-ciruela"
|
className="w-full accent-ari-coral"
|
||||||
/>
|
/>
|
||||||
<p className="mt-2 text-xs font-bold text-slate-500">
|
<p className="mt-2 text-xs font-bold text-slate-500">
|
||||||
Hasta ${maxPrice.toLocaleString("es-CO")}
|
Hasta ${maxPrice.toLocaleString("es-CO")}
|
||||||
@@ -470,8 +470,8 @@ function Filter({
|
|||||||
onClick={() => onChange(value)}
|
onClick={() => onChange(value)}
|
||||||
className={`rounded-md px-3 py-2 text-xs font-bold transition ${
|
className={`rounded-md px-3 py-2 text-xs font-bold transition ${
|
||||||
selected === value
|
selected === value
|
||||||
? "bg-ari-carbon-oscuro text-white"
|
? "bg-ari-marino text-white"
|
||||||
: "bg-slate-100 text-slate-600 hover:bg-ari-cobre/10"
|
: "bg-slate-100 text-slate-600 hover:bg-ari-coral-claro/10"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
|
|||||||
@@ -33,15 +33,15 @@ export function ProductCard({ product, priority = false }: { product: Product; p
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className="group flex h-full flex-col overflow-hidden rounded-lg border border-slate-100 bg-white shadow-lg shadow-ari-carbon-oscuro/5 transition duration-300 hover:-translate-y-1.5 hover:shadow-2xl hover:shadow-ari-ciruela/10">
|
<article className="group flex h-full flex-col overflow-hidden rounded-lg border border-slate-100 bg-white shadow-lg shadow-ari-marino/5 transition duration-300 hover:-translate-y-1.5 hover:shadow-2xl hover:shadow-ari-coral/10">
|
||||||
<div className="relative aspect-square overflow-hidden bg-ari-hueso">
|
<div className="relative aspect-square overflow-hidden bg-white">
|
||||||
<Link href={`/product/${product.slug}`} prefetch={false}><Image src={product.thumbnail} alt={product.name} fill priority={priority} sizes="(max-width: 640px) 82vw, (max-width: 1024px) 44vw, 280px" className="object-cover transition duration-500 group-hover:scale-[1.035]" /></Link>
|
<Link href={`/product/${product.slug}`} prefetch={false}><Image src={product.thumbnail} alt={product.name} fill priority={priority} sizes="(max-width: 640px) 82vw, (max-width: 1024px) 44vw, 280px" className="object-cover transition duration-500 group-hover:scale-[1.035]" /></Link>
|
||||||
<div className="absolute left-3 top-3 flex gap-2">{discountPercent && discountPercent > 0 && <Badge className="bg-ari-terracota-oscuro text-white">-{discountPercent}%</Badge>}{product.isNew && <Badge className="bg-ari-carbon-oscuro text-white">Nuevo</Badge>}{product.featured && <Badge className="bg-ari-cobre text-white"><Sparkles className="mr-1 size-3" />Top</Badge>}</div>
|
<div className="absolute left-3 top-3 flex gap-2">{discountPercent && discountPercent > 0 && <Badge className="bg-ari-coral text-white">-{discountPercent}%</Badge>}{product.isNew && <Badge className="bg-ari-marino text-white">Nuevo</Badge>}{product.featured && <Badge className="bg-ari-coral-claro text-white"><Sparkles className="mr-1 size-3" />Top</Badge>}</div>
|
||||||
<button type="button" aria-label={isFavorite ? "Quitar de favoritos" : "Agregar a favoritos"} aria-pressed={isFavorite} className={`absolute right-3 top-3 rounded-full p-2.5 shadow-lg backdrop-blur transition ${isFavorite ? "bg-ari-ciruela text-white" : "bg-white/95 text-slate-900 hover:text-ari-ciruela"}`} onClick={() => toggleProduct(product)}><Heart className={`size-4 ${isFavorite ? "fill-current" : ""}`} /></button>
|
<button type="button" aria-label={isFavorite ? "Quitar de favoritos" : "Agregar a favoritos"} aria-pressed={isFavorite} className={`absolute right-3 top-3 rounded-full p-2.5 shadow-lg backdrop-blur transition ${isFavorite ? "bg-ari-coral text-white" : "bg-white/95 text-slate-900 hover:text-ari-coral"}`} onClick={() => toggleProduct(product)}><Heart className={`size-4 ${isFavorite ? "fill-current" : ""}`} /></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-1 flex-col space-y-3 p-5">
|
<div className="flex flex-1 flex-col space-y-3 p-5">
|
||||||
<div className="flex items-center justify-between gap-2 text-xs font-bold text-slate-500"><span>{product.category}</span><span className="rounded-md bg-ari-cobre/10 px-2 py-1 text-ari-cobre">{product.collection}</span></div>
|
<div className="flex items-center justify-between gap-2 text-xs font-bold text-slate-500"><span>{product.category}</span><span className="rounded-md bg-ari-coral-claro/10 px-2 py-1 text-ari-coral-claro">{product.collection}</span></div>
|
||||||
<Link href={`/product/${product.slug}`} prefetch={false}><h3 className="line-clamp-2 min-h-12 text-lg font-black leading-6 text-ari-carbon group-hover:text-ari-ciruela">{product.name}</h3></Link>
|
<Link href={`/product/${product.slug}`} prefetch={false}><h3 className="line-clamp-2 min-h-12 text-lg font-black leading-6 text-ari-marino group-hover:text-ari-coral">{product.name}</h3></Link>
|
||||||
<p className="line-clamp-2 min-h-10 text-sm leading-5 text-slate-500">{product.shortDescription}</p>
|
<p className="line-clamp-2 min-h-10 text-sm leading-5 text-slate-500">{product.shortDescription}</p>
|
||||||
{product.variants.length > 1 && (
|
{product.variants.length > 1 && (
|
||||||
<div className="flex flex-wrap gap-1.5">
|
<div className="flex flex-wrap gap-1.5">
|
||||||
@@ -55,7 +55,7 @@ export function ProductCard({ product, priority = false }: { product: Product; p
|
|||||||
onClick={() => setSelectedVariantId(variant.id)}
|
onClick={() => setSelectedVariantId(variant.id)}
|
||||||
className={`rounded-md border px-2.5 py-1 text-xs font-bold transition ${
|
className={`rounded-md border px-2.5 py-1 text-xs font-bold transition ${
|
||||||
selectedVariantId === variant.id
|
selectedVariantId === variant.id
|
||||||
? "border-ari-ciruela bg-ari-ciruela/10 text-ari-ciruela"
|
? "border-ari-coral bg-ari-coral/10 text-ari-coral"
|
||||||
: "border-slate-200 text-slate-600 hover:border-slate-400"
|
: "border-slate-200 text-slate-600 hover:border-slate-400"
|
||||||
} ${!variant.available ? "cursor-not-allowed opacity-40" : ""}`}
|
} ${!variant.available ? "cursor-not-allowed opacity-40" : ""}`}
|
||||||
>
|
>
|
||||||
@@ -70,7 +70,7 @@ export function ProductCard({ product, priority = false }: { product: Product; p
|
|||||||
<div className="mt-auto flex items-center justify-between gap-3 pt-1">
|
<div className="mt-auto flex items-center justify-between gap-3 pt-1">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{product.compareAtPrice && <span className="text-xs font-bold text-slate-400 line-through">{formatMoney(product.compareAtPrice, product.currency)}</span>}
|
{product.compareAtPrice && <span className="text-xs font-bold text-slate-400 line-through">{formatMoney(product.compareAtPrice, product.currency)}</span>}
|
||||||
<strong className="font-display text-base font-bold text-ari-carbon">{formatMoney(product.price, product.currency)}</strong>
|
<strong className="font-display text-base font-bold text-ari-marino">{formatMoney(product.price, product.currency)}</strong>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="primary" size="sm" onClick={() => addItem(product, selectedVariantId)}><ShoppingBag className="size-4" />Agregar</Button>
|
<Button variant="primary" size="sm" onClick={() => addItem(product, selectedVariantId)}><ShoppingBag className="size-4" />Agregar</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user