import { useState } from "react"; import { createPortal } from "react-dom"; import { useNavigate } from "react-router-dom"; import { useCart } from "../context/useCart"; import { Camera, Info, X } from "lucide-react"; import "./ProductCard.css"; function getTextColor(hex: string): string { const h = hex.replace("#", ""); const full = h.length === 3 ? h .split("") .map((c) => c + c) .join("") : h; const r = parseInt(full.slice(0, 2), 16); const g = parseInt(full.slice(2, 4), 16); const b = parseInt(full.slice(4, 6), 16); return (r * 299 + g * 587 + b * 114) / 1000 > 128 ? "#000000" : "#ffffff"; } interface ProductCardProps { id: number; name: string; price: number; unit: string; image: string; stock: number; category: string; prices?: Array<{ quantity: number; price: number; active_price?: boolean; promo_price?: number | null; promo_percent?: number; }>; hasVideo?: boolean; videoUrl?: string; // ✨ Nouveau prop pour l'URL de la vidéo categoryColor?: string; coming_soon?: boolean; } function ProductCard({ id, name, price, unit = "g", image, stock, category = "autre", prices, hasVideo = false, videoUrl, categoryColor, coming_soon, }: ProductCardProps) { const navigate = useNavigate(); const { addToCart } = useCart(); const [showQuantitySelect, setShowQuantitySelect] = useState(false); const [selectedQuantity, setSelectedQuantity] = useState( null, ); const [showSuccess, setShowSuccess] = useState(false); const [showVideo, setShowVideo] = useState(false); const [stockWarning, setStockWarning] = useState<{ wanted: number; available: number } | null>(null); const isOutOfStock = stock === 0; const isComingSoon = coming_soon === true; const normalizedCategory = (category || "autre").toLowerCase().trim(); const firstPromoPrice = prices?.[0]?.promo_price != null && prices[0].promo_price < prices[0].price ? prices[0].promo_price : null; const handleDetailsClick = (e: React.MouseEvent) => { e.stopPropagation(); navigate(`/user/product/${id}`); }; // ✨ Handler pour afficher/masquer la vidéo const handleVideoToggle = (e: React.MouseEvent) => { e.stopPropagation(); setShowVideo(!showVideo); }; // ✨ Handler pour fermer la vidéo const handleCloseVideo = (e: React.MouseEvent) => { e.stopPropagation(); setShowVideo(false); }; const handleQuickAddClick = (e: React.MouseEvent) => { e.stopPropagation(); console.log("🔘 Bouton cliqué", { id, name, category: normalizedCategory, isOutOfStock, prices: prices?.length || 0, showQuantitySelect, }); if (!isOutOfStock && prices && prices.length > 0) { setShowQuantitySelect(!showQuantitySelect); } }; const handleQuantitySelect = (e: React.ChangeEvent) => { const selectedGrams = Number(e.target.value); setSelectedQuantity(selectedGrams); if (stock > 0 && selectedGrams > stock) { setStockWarning({ wanted: selectedGrams, available: stock }); return; } const priceOption = prices?.find((p) => p.quantity === selectedGrams); if (priceOption) { addToCart({ product_id: id, name_product: name, price: priceOption.price, quantity: selectedGrams, category: normalizedCategory, image: image, }); setShowSuccess(true); setTimeout(() => { setShowSuccess(false); setShowQuantitySelect(false); setSelectedQuantity(null); }, 1500); } }; const cardColor = categoryColor || "#ffffff"; return (
{name} {/* ✨ Icône caméra cliquable */} {hasVideo && !isOutOfStock && videoUrl && ( )} {/* ✨ Bouton "Détails" */} {isOutOfStock && (
SOLD OUT
)} {isComingSoon && (
COMMING SOON
)}

{name}

{price > 0 ? ( firstPromoPrice !== null ? ( <> {price.toFixed(2)} € {" "} {firstPromoPrice.toFixed(2)} € ) : ( `${price.toFixed(2)} €` ) ) : ( "Prix non disponible" )}

e.stopPropagation()} > {showSuccess ? (
✓ Ajouté !
) : ( <> {showQuantitySelect && prices && prices.length > 0 && ( )} )}
{/* Modal stock insuffisant */} {stockWarning && createPortal(
setStockWarning(null)}>
e.stopPropagation()} >
⚠️

Stock insuffisant

Vous avez sélectionné {stockWarning.wanted}g mais il ne reste que{" "} {stockWarning.available}g disponible pour {name}.

, document.body, )} {/* ✨ Modal vidéo — rendu via Portal pour éviter le clipping du transform:scale sur .product-card */} {showVideo && videoUrl && createPortal(
e.stopPropagation()} >
, document.body, )}
); } export default ProductCard;