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" }}> {product.name} {/* 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 });