const ProductCard = ({ product, onView, onAddToCart, lang }) => {
const [hovered, setHovered] = React.useState(false);
const [wish, setWish] = React.useState(false);
const [rating, setRating] = React.useState(product.rating > 0 ? { avg: product.rating, total: product.ratingCount || 0 } : null);
const ACCENT = "#a9744f";
React.useEffect(() => {
if (product.rating > 0) return; // pakai rating manual dari admin
fetch("api/reviews.php?product_id=" + product.id)
.then(r=>r.json())
.then(d=>{ if(d.total>0) setRating({avg:d.avg_rating, total:d.total}); })
.catch(()=>{});
}, [product.id]);
const t = (en, id) => lang === "id" ? id : en;
// peta nama warna → hex untuk swatch
const COLORMAP = {
black:"#1d1d1f", hitam:"#1d1d1f", ivory:"#efece4", putih:"#f4f1ea", white:"#f4f1ea",
cream:"#ece3d2", caramel:"#c9a37a", brown:"#8a5a37", coklat:"#8a5a37", stone:"#b9b2a6",
blush:"#e7b9b0", pink:"#e7b9b0", grey:"#b8b8bd", gray:"#b8b8bd", abu:"#b8b8bd",
silver:"#cfcfcf", gold:"#d4af37", "rose gold":"#dca08a", navy:"#2a3550", blue:"#2a4d8f",
sand:"#e3d9c8", tan:"#c9a37a", beige:"#e8e0d4", green:"#4a6b4a", red:"#b4452f", maroon:"#7a2e3a"
};
const colorNames = Array.isArray(product.colors) ? product.colors.slice(0,5) : [];
const hexOf = (c) => (product.colorHex && product.colorHex[c]) || COLORMAP[String(c).toLowerCase().trim()] || "#d9d4cb";
const [selColor, setSelColor] = React.useState(null); // jangan paksa pilih warna — cover = foto utama produk
const hasDisc = product.originalPrice && Number(product.originalPrice) > Number(product.price);
const discPct = hasDisc ? Math.round((1 - Number(product.price)/Number(product.originalPrice)) * 100) : 0;
const _matchVar = (Array.isArray(product.variants) && selColor)
? product.variants.find(v => v.image && String(v.name).toLowerCase().trim() === String(selColor).toLowerCase().trim())
: null;
const img = (product.colorImages && selColor && product.colorImages[selColor])
|| (_matchVar && _matchVar.image)
|| (Array.isArray(product.images) && product.images.length > 0 ? product.images[0] : product.image);
return (
setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{
background:"#fff", border:"1px solid #ececf0", borderRadius:22, overflow:"hidden",
cursor:"pointer", transition:"transform 0.35s ease, box-shadow 0.35s ease",
transform: hovered ? "translateY(-6px)" : "none",
boxShadow: hovered ? "0 18px 50px rgba(20,20,30,0.10)" : "none",
display:"flex", flexDirection:"column"
}}
>
{/* Image */}
onView(product)} className="lh-card-img"
style={{ position:"relative", overflow:"hidden", aspectRatio:"1/1", background:"#f5f5f7" }}>

{/* Badge */}
{product.isPreorder ? (
⏳ PO {product.preorderDays || 14}h
) : hasDisc ? (
−{discPct}%
) : product.badge ? (
{product.badge}
) : null}
{/* Wishlist */}
{/* Quick add */}
{(() => {
const hasVar = Array.isArray(product.variants) && product.variants.length > 0;
const hasColor = Array.isArray(product.colors) && product.colors.length > 0;
const needsPick = hasVar || hasColor; // wajib pilih dulu di halaman produk
return (
);
})()}
{/* Info */}
onView(product)} style={{ padding:"15px 17px 18px", flex:1, display:"flex", flexDirection:"column" }}>
{colorNames.length > 0 && (
{colorNames.map((c,i)=>{
const active = selColor === c;
return (
)}
{product.categoryLabel}
{product.name}
{rating && (
{"★".repeat(Math.round(rating.avg))}{"☆".repeat(5-Math.round(rating.avg))}
{rating.total>0 && ({rating.total})}
)}
{(Array.isArray(product.variants) && product.variants.length) ? (t("From ","Mulai ") ) : ""}{formatPrice(product.price)}
{hasDisc && (
{formatPrice(product.originalPrice)}
)}
{/* Urgensi stok asli — cuma tampil kalau stok beneran tinggal sedikit */}
{Number(product.stock) > 0 && Number(product.stock) <= 8 && (
🔥 {t(`Only ${product.stock} left`, `Sisa ${product.stock} stok`)}
)}
);
};
Object.assign(window, { ProductCard });