"use client"; import Link from "next/link"; import { OptimizedImage } from "@/components/OptimizedImage"; import { Product } from "@/lib/openFoodFactsApi"; import { AlertTriangle } from "lucide-react"; import { formatNutritionData } from "@/lib/openFoodFactsApi"; import { cn } from "@/lib/utils"; interface ProductCardProps { product: Product; className?: string; priority?: number; currentPage?: number; variant?: "default" | "mobile"; } const NUTRI_GRADE_CLASS: Record = { a: "a", b: "b", c: "c", d: "d", e: "e", }; function getVerdict(grade?: string, nova?: number): { label: string; colorClass: string } { if (grade === "a" || grade === "b") return { label: "Recomendado", colorClass: "text-[var(--nutri-a)]" }; if (grade === "c" || nova === 3) return { label: "Com moderação", colorClass: "text-[var(--nutri-c)]" }; return { label: "Evitar", colorClass: "text-[var(--nutri-e)]" }; } function getVerdictDotBg(grade?: string, nova?: number): string { if (grade === "a" || grade === "b") return "bg-[var(--nutri-a)]"; if (grade === "c" || nova === 3) return "bg-[var(--nutri-c)]"; return "bg-[var(--nutri-e)]"; } function getImageUrl(product: Product): string { return ( product.image_front_url || product.image_front_small_url || product.image_url || product.image_small_url || "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Crect fill='%23f3efe7' width='400' height='400'/%3E%3Ctext fill='%23a39c93' font-family='Georgia,serif' font-size='16' x='50%25' y='50%25' text-anchor='middle' dominant-baseline='middle'%3ESem imagem%3C/text%3E%3C/svg%3E" ); } /* ── Nutri-Letter hero circle ───────────────────────────────────────────── */ function NutriLetter({ grade, size = 56 }: { grade: string; size?: number }) { const g = grade?.toLowerCase(); if (!g || !NUTRI_GRADE_CLASS[g]) return null; return (
{g.toUpperCase()}
); } /* ── Verdict dot — pure Tailwind, no inline style ──────────────────────── */ function VerdictDot({ grade, nova }: { grade?: string; nova?: number }) { const { label, colorClass } = getVerdict(grade, nova); const dotBg = getVerdictDotBg(grade, nova); return ( {label} ); } /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ MOBILE VARIANT — horizontal row All hover/focus states are pure CSS via Tailwind so keyboard + touch work ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ function MobileCard({ product, className, priority, currentPage }: Omit) { const imageUrl = getImageUrl(product); const grade = product.nutrition_grades?.toLowerCase(); const nova = product.nova_group; const allergenCount = product.allergens_tags?.filter((a) => ["gluten", "milk", "eggs", "nuts", "peanuts", "soy"].some((c) => a.toLowerCase().includes(c) ) ).length ?? 0; return ( {/* Thumb */}
{/* Center text */}
{product.brands || "Marca desconhecida"}
{product.product_name || "Produto sem nome"}
{nova && ( <> · NOVA {nova} )} {allergenCount > 0 && ( <> · {allergenCount} alérgeno{allergenCount > 1 ? "s" : ""} )}
{/* Nutri-Score letter */} {grade && NUTRI_GRADE_CLASS[grade] && } ); } /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DEFAULT VARIANT — portrait card, image hero ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ function DefaultCard({ product, className, priority, currentPage }: Omit) { const imageUrl = getImageUrl(product); const nutritionData = formatNutritionData(product); const grade = product.nutrition_grades?.toLowerCase(); const nova = product.nova_group; const allergenCount = product.allergens_tags?.filter((a) => ["gluten", "milk", "eggs", "nuts", "peanuts", "soy"].some((c) => a.toLowerCase().includes(c) ) ).length ?? 0; return ( {/* ── Hero image area ─────────────────────────────────────────────── */}
{/* Image zooms on hover because parent now HAS the `group` class */} {/* Nutri-Score — top-right */} {grade && NUTRI_GRADE_CLASS[grade] && (
)} {/* Allergen chip — top-left */} {allergenCount > 0 && (
{allergenCount}
)}
{/* ── Card body ──────────────────────────────────────────────────── */}
{/* Brand + product name */}
{product.brands || "Marca desconhecida"}

{product.product_name || "Nome não disponível"}

{/* ── Nutrition mini-bar: 4 columns ─────────────────────────────── */} {nutritionData && (
{[ { l: "kcal", v: nutritionData.energy }, { l: "Açúcar", v: nutritionData.sugars }, { l: "Gord.", v: nutritionData.fat }, { l: "Sódio", v: nutritionData.sodium }, ].map((n, i) => n.v ? (
{n.v} {n.l}
) : null )}
)} {/* Footer row: verdict + nova badge */}
{nova && ( NOVA {nova} )}
{/* CTA — styled as ghost button, inherits the card's hover context */}
); } /* ── Public export ──────────────────────────────────────────────────────── */ export function ProductCard({ variant = "default", ...props }: ProductCardProps) { if (variant === "mobile") return ; return ; }