This commit is contained in:
@@ -57,7 +57,8 @@ function ProductCard({
|
||||
null,
|
||||
);
|
||||
const [showSuccess, setShowSuccess] = useState(false);
|
||||
const [showVideo, setShowVideo] = useState(false); // ✨ État pour afficher/masquer la vidéo
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
const [stockWarning, setStockWarning] = useState<{ wanted: number; available: number } | null>(null);
|
||||
|
||||
const isOutOfStock = stock === 0;
|
||||
const isComingSoon = coming_soon === true;
|
||||
@@ -100,16 +101,13 @@ function ProductCard({
|
||||
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) {
|
||||
console.log("💾 [ProductCard] Ajout au panier:", {
|
||||
id,
|
||||
name,
|
||||
category: normalizedCategory,
|
||||
quantity: selectedGrams,
|
||||
price: priceOption.price,
|
||||
});
|
||||
|
||||
addToCart({
|
||||
product_id: id,
|
||||
name_product: name,
|
||||
@@ -237,6 +235,49 @@ function ProductCard({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Modal stock insuffisant */}
|
||||
{stockWarning &&
|
||||
createPortal(
|
||||
<div className="video-modal" onClick={() => setStockWarning(null)}>
|
||||
<div
|
||||
className="video-modal-content"
|
||||
style={{ maxWidth: 340, padding: "2rem", textAlign: "center" }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
className="video-close-btn"
|
||||
onClick={() => setStockWarning(null)}
|
||||
aria-label="Fermer"
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
<div style={{ fontSize: "2.5rem", marginBottom: "0.75rem" }}>⚠️</div>
|
||||
<p style={{ fontWeight: 700, fontSize: "1.1rem", marginBottom: "0.5rem" }}>
|
||||
Stock insuffisant
|
||||
</p>
|
||||
<p style={{ color: "#aaa", fontSize: "0.95rem", marginBottom: "1.25rem" }}>
|
||||
Vous avez sélectionné <strong>{stockWarning.wanted}g</strong> mais il ne reste que{" "}
|
||||
<strong style={{ color: "#ef4444" }}>{stockWarning.available}g</strong> disponible pour <em>{name}</em>.
|
||||
</p>
|
||||
<button
|
||||
style={{
|
||||
background: "#ef4444",
|
||||
color: "#fff",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
padding: "0.6rem 1.5rem",
|
||||
fontWeight: 700,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => setStockWarning(null)}
|
||||
>
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
)}
|
||||
|
||||
{/* ✨ Modal vidéo — rendu via Portal pour éviter le clipping du transform:scale sur .product-card */}
|
||||
{showVideo &&
|
||||
videoUrl &&
|
||||
|
||||
@@ -27,7 +27,13 @@ function UserAccueil() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getCategories().then(setCategories);
|
||||
getCategories().then((cats) => {
|
||||
const sorted = [...cats].sort((a, b) => {
|
||||
if (a.is_coming_soon === b.is_coming_soon) return 0;
|
||||
return a.is_coming_soon ? 1 : -1;
|
||||
});
|
||||
setCategories(sorted);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user