This commit is contained in:
@@ -57,7 +57,8 @@ function ProductCard({
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const [showSuccess, setShowSuccess] = useState(false);
|
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 isOutOfStock = stock === 0;
|
||||||
const isComingSoon = coming_soon === true;
|
const isComingSoon = coming_soon === true;
|
||||||
@@ -100,16 +101,13 @@ function ProductCard({
|
|||||||
const selectedGrams = Number(e.target.value);
|
const selectedGrams = Number(e.target.value);
|
||||||
setSelectedQuantity(selectedGrams);
|
setSelectedQuantity(selectedGrams);
|
||||||
|
|
||||||
|
if (stock > 0 && selectedGrams > stock) {
|
||||||
|
setStockWarning({ wanted: selectedGrams, available: stock });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const priceOption = prices?.find((p) => p.quantity === selectedGrams);
|
const priceOption = prices?.find((p) => p.quantity === selectedGrams);
|
||||||
if (priceOption) {
|
if (priceOption) {
|
||||||
console.log("💾 [ProductCard] Ajout au panier:", {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
category: normalizedCategory,
|
|
||||||
quantity: selectedGrams,
|
|
||||||
price: priceOption.price,
|
|
||||||
});
|
|
||||||
|
|
||||||
addToCart({
|
addToCart({
|
||||||
product_id: id,
|
product_id: id,
|
||||||
name_product: name,
|
name_product: name,
|
||||||
@@ -237,6 +235,49 @@ function ProductCard({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</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 */}
|
{/* ✨ Modal vidéo — rendu via Portal pour éviter le clipping du transform:scale sur .product-card */}
|
||||||
{showVideo &&
|
{showVideo &&
|
||||||
videoUrl &&
|
videoUrl &&
|
||||||
|
|||||||
@@ -27,7 +27,13 @@ function UserAccueil() {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
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(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user