chore: fix ui
This commit is contained in:
@@ -1,19 +1,10 @@
|
||||
// ============================================
|
||||
// pages/Cart/Cart.tsx - MÊME LOGIQUE QUE PRODUCTCARD
|
||||
// ============================================
|
||||
// ✅ Affiche quantity en grammes (5g, 10g, etc.)
|
||||
// ✅ Affiche photos et vidéos SANS appels API supplémentaires
|
||||
// ❌ Pas de boutons +/- (on ne modifie pas les grammes)
|
||||
// ✅ Pour acheter 2× le même produit, l'ajouter 2 fois
|
||||
// ✅ Vérification continue de l'authentification
|
||||
|
||||
import { useCart } from "../../context/useCart";
|
||||
import Navbar from "../../components/Navbar";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { isUserAuthenticated, getProductById, getMediaUrl } from "../../api/api";
|
||||
import type { Product } from "../../api/api";
|
||||
import { Trash2, ShoppingBag, AlertTriangle } from "lucide-react";
|
||||
import { Trash2, ShoppingCart, AlertTriangle } from "lucide-react";
|
||||
import "./Cart.css";
|
||||
|
||||
interface CartItemWithMedia {
|
||||
@@ -30,258 +21,89 @@ interface CartItemWithMedia {
|
||||
|
||||
function Cart() {
|
||||
const navigate = useNavigate();
|
||||
const { cartItems, removeFromCart, clearCart, loading, refreshCart } =
|
||||
useCart();
|
||||
const { cartItems, removeFromCart, clearCart, loading, refreshCart } = useCart();
|
||||
const [showClearConfirm, setShowClearConfirm] = useState(false);
|
||||
const [showVideo, setShowVideo] = useState(false); // ✨ État pour afficher/masquer la vidéo
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
const [currentVideoUrl, setCurrentVideoUrl] = useState<string>("");
|
||||
const [enrichedItems, setEnrichedItems] = useState<CartItemWithMedia[]>([]);
|
||||
const [loadingMedia, setLoadingMedia] = useState(false);
|
||||
|
||||
// ============================================
|
||||
// HANDLERS VIDÉO (COMME PRODUCTCARD)
|
||||
// ============================================
|
||||
|
||||
const handleVideoToggle = (videoUrl: string) => {
|
||||
setCurrentVideoUrl(videoUrl);
|
||||
setShowVideo(true);
|
||||
};
|
||||
|
||||
const handleCloseVideo = () => {
|
||||
setShowVideo(false);
|
||||
setCurrentVideoUrl("");
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// VÉRIFICATION AUTHENTIFICATION
|
||||
// ============================================
|
||||
useEffect(() => {
|
||||
const checkAuth = () => {
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log(
|
||||
"❌ [Cart] Utilisateur non authentifié, redirection vers /login/client",
|
||||
);
|
||||
navigate("/login/client", { replace: true });
|
||||
}
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
if (!isUserAuthenticated()) navigate("/login/client", { replace: true });
|
||||
}, [navigate]);
|
||||
|
||||
// ✅ VÉRIFICATION CONTINUE (toutes les 5 secondes)
|
||||
useEffect(() => {
|
||||
const authInterval = setInterval(() => {
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log(
|
||||
"❌ [Cart] Session expirée, redirection vers /login/client",
|
||||
);
|
||||
navigate("/login/client", { replace: true });
|
||||
}
|
||||
const interval = setInterval(() => {
|
||||
if (!isUserAuthenticated()) navigate("/login/client", { replace: true });
|
||||
}, 5000);
|
||||
|
||||
return () => clearInterval(authInterval);
|
||||
return () => clearInterval(interval);
|
||||
}, [navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
// ✅ Vérifier l'auth avant de rafraîchir le panier
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log("❌ [refreshCart] Non authentifié");
|
||||
navigate("/login/client", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isUserAuthenticated()) { navigate("/login/client", { replace: true }); return; }
|
||||
refreshCart();
|
||||
}, []);
|
||||
|
||||
// ============================================
|
||||
// CALCULS
|
||||
// ============================================
|
||||
|
||||
const total = cartItems.reduce((sum, item) => sum + item.price, 0);
|
||||
|
||||
// ============================================
|
||||
// FONCTIONS POUR PHOTOS ET VIDÉOS (COMME PRODUCTCARD)
|
||||
// ============================================
|
||||
|
||||
const getProductImage = (product: Product): string => {
|
||||
if (!product.media || product.media.length === 0) {
|
||||
return "https://via.placeholder.com/400x400/1a1a1a/ffffff?text=No+Image";
|
||||
if (!product.media || product.media.length === 0)
|
||||
return "https://via.placeholder.com/120x120/1a1a1a/ffffff?text=No+Image";
|
||||
for (const m of product.media) {
|
||||
if (m && m.type === "image" && m.url) return getMediaUrl(m.url);
|
||||
}
|
||||
|
||||
for (let i = 0; i < product.media.length; i++) {
|
||||
const mediaItem = product.media[i];
|
||||
if (mediaItem && mediaItem.type === "image" && mediaItem.url) {
|
||||
return getMediaUrl(mediaItem.url);
|
||||
}
|
||||
}
|
||||
|
||||
return "https://via.placeholder.com/400x400/1a1a1a/ffffff?text=No+Image";
|
||||
return "https://via.placeholder.com/120x120/1a1a1a/ffffff?text=No+Image";
|
||||
};
|
||||
|
||||
const hasProductVideo = (product: Product): boolean => {
|
||||
if (!product.media || product.media.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return product.media.some(
|
||||
(mediaItem) => mediaItem && mediaItem.type === "video",
|
||||
);
|
||||
};
|
||||
|
||||
const getProductVideoUrl = (product: Product): string | undefined => {
|
||||
if (!product.media || product.media.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const videoMedia = product.media.find(
|
||||
(mediaItem) => mediaItem && mediaItem.type === "video",
|
||||
);
|
||||
|
||||
return videoMedia?.url ? getMediaUrl(videoMedia.url) : undefined;
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// ENRICHIR LES ITEMS AVEC MÉDIAS
|
||||
// ============================================
|
||||
|
||||
useEffect(() => {
|
||||
const enrichCartItems = async () => {
|
||||
if (cartItems.length === 0) {
|
||||
console.log("🔄 [CART] Panier vide, pas d'enrichissement");
|
||||
setEnrichedItems([]);
|
||||
setLoadingMedia(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ Guard: ne pas re-enrichir si déjà fait pour ces mêmes items
|
||||
const sameItems =
|
||||
const enrich = async () => {
|
||||
if (cartItems.length === 0) { setEnrichedItems([]); return; }
|
||||
const same =
|
||||
enrichedItems.length === cartItems.length &&
|
||||
enrichedItems.every(
|
||||
(enriched, index) =>
|
||||
enriched.id === cartItems[index]?.id &&
|
||||
enriched.product_id === cartItems[index]?.product_id,
|
||||
);
|
||||
|
||||
if (sameItems) {
|
||||
console.log("🔄 [CART] Items déjà enrichis, skip");
|
||||
return;
|
||||
}
|
||||
enrichedItems.every((e, i) => e.id === cartItems[i]?.id && e.product_id === cartItems[i]?.product_id);
|
||||
if (same) return;
|
||||
|
||||
setLoadingMedia(true);
|
||||
console.log(
|
||||
"🔄 [CART] Enrichissement de",
|
||||
cartItems.length,
|
||||
"items...",
|
||||
);
|
||||
|
||||
try {
|
||||
const enrichedPromises = cartItems.map(async (item) => {
|
||||
try {
|
||||
console.log(
|
||||
`📦 [CART] Récupération médias pour produit ${item.product_id}...`,
|
||||
);
|
||||
const productResponse = await getProductById(
|
||||
item.product_id,
|
||||
);
|
||||
|
||||
if (productResponse.success && productResponse.data) {
|
||||
const product = productResponse.data;
|
||||
const enriched = {
|
||||
...item,
|
||||
image: getProductImage(product),
|
||||
hasVideo: hasProductVideo(product),
|
||||
videoUrl: getProductVideoUrl(product),
|
||||
};
|
||||
console.log(`✅ [CART] Item enrichi:`, {
|
||||
name: item.name_product,
|
||||
image: enriched.image,
|
||||
hasVideo: enriched.hasVideo,
|
||||
});
|
||||
return enriched;
|
||||
} else {
|
||||
console.warn(
|
||||
`⚠️ [CART] Produit ${item.product_id} non trouvé`,
|
||||
);
|
||||
return {
|
||||
...item,
|
||||
image: "https://via.placeholder.com/400x400/1a1a1a/ffffff?text=No+Image",
|
||||
hasVideo: false,
|
||||
videoUrl: undefined,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ [CART] Erreur pour produit ${item.product_id}:`,
|
||||
error,
|
||||
);
|
||||
return {
|
||||
...item,
|
||||
image: "https://via.placeholder.com/400x400/1a1a1a/ffffff?text=No+Image",
|
||||
hasVideo: false,
|
||||
videoUrl: undefined,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const enriched = await Promise.all(enrichedPromises);
|
||||
const enriched = await Promise.all(
|
||||
cartItems.map(async (item) => {
|
||||
try {
|
||||
const res = await getProductById(item.product_id);
|
||||
if (res.success && res.data) {
|
||||
const p = res.data;
|
||||
const videoMedia = p.media?.find((m: any) => m && m.type === "video");
|
||||
return {
|
||||
...item,
|
||||
image: getProductImage(p),
|
||||
hasVideo: !!videoMedia,
|
||||
videoUrl: videoMedia?.url ? getMediaUrl(videoMedia.url) : undefined,
|
||||
};
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
return { ...item, image: "https://via.placeholder.com/120x120/1a1a1a/ffffff?text=No+Image", hasVideo: false };
|
||||
})
|
||||
);
|
||||
setEnrichedItems(enriched);
|
||||
console.log(
|
||||
"✅ [CART] Enrichissement terminé:",
|
||||
enriched.length,
|
||||
"items",
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("❌ [CART] Erreur enrichissement:", error);
|
||||
setEnrichedItems(
|
||||
cartItems.map((item) => ({
|
||||
...item,
|
||||
image: "https://via.placeholder.com/400x400/1a1a1a/ffffff?text=No+Image",
|
||||
hasVideo: false,
|
||||
videoUrl: undefined,
|
||||
})),
|
||||
);
|
||||
} finally {
|
||||
setLoadingMedia(false);
|
||||
}
|
||||
};
|
||||
|
||||
enrichCartItems();
|
||||
}, [cartItems]); // ✅ Dépendance sur cartItems complet
|
||||
|
||||
// ============================================
|
||||
// HANDLERS
|
||||
// ============================================
|
||||
enrich();
|
||||
}, [cartItems]);
|
||||
|
||||
const handleClearCart = async () => {
|
||||
// ✅ Vérifier l'auth avant de vider le panier
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log("❌ [handleClearCart] Non authentifié");
|
||||
navigate("/login/client", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isUserAuthenticated()) { navigate("/login/client", { replace: true }); return; }
|
||||
setShowClearConfirm(false);
|
||||
await clearCart();
|
||||
};
|
||||
|
||||
const handleRemoveItem = async (itemId: number) => {
|
||||
// ✅ Vérifier l'auth avant de supprimer un item
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log("❌ [handleRemoveItem] Non authentifié");
|
||||
navigate("/login/client", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isUserAuthenticated()) { navigate("/login/client", { replace: true }); return; }
|
||||
await removeFromCart(itemId);
|
||||
};
|
||||
|
||||
const handleCheckout = () => {
|
||||
// ✅ Vérifier l'auth avant de passer commande
|
||||
if (!isUserAuthenticated()) {
|
||||
console.log("❌ [handleCheckout] Non authentifié");
|
||||
navigate("/login/client", { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isUserAuthenticated()) { navigate("/login/client", { replace: true }); return; }
|
||||
navigate("/user/checkout");
|
||||
};
|
||||
|
||||
@@ -290,231 +112,145 @@ function Cart() {
|
||||
<>
|
||||
<Navbar />
|
||||
<div className="cart-container">
|
||||
<div className="cart-header">
|
||||
<h1>Votre Panier</h1>
|
||||
</div>
|
||||
<div className="loading-cart">
|
||||
<p>Chargement de votre panier...</p>
|
||||
</div>
|
||||
<div className="loading-cart"><p>Chargement du panier...</p></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const displayItems = enrichedItems.length > 0 ? enrichedItems : cartItems.map(i => ({ ...i, image: "", hasVideo: false }));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<div className="cart-container">
|
||||
<div className="cart-header">
|
||||
<h1>Votre Panier</h1>
|
||||
{cartItems.length > 0 && (
|
||||
<button
|
||||
className="clear-all-button"
|
||||
onClick={() => setShowClearConfirm(true)}
|
||||
disabled={loading}
|
||||
>
|
||||
<Trash2 size={16} className="trash-icon" />
|
||||
Tout supprimer
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{cartItems.length === 0 ? (
|
||||
<div className="empty-cart">
|
||||
<ShoppingBag size={48} className="empty-cart-icon" />
|
||||
<p>Votre panier est vide</p>
|
||||
<button
|
||||
className="continue-shopping"
|
||||
onClick={() => navigate("/user/nos-produits")}
|
||||
>
|
||||
Continuer mes achats
|
||||
<ShoppingCart size={72} className="empty-cart-icon" />
|
||||
<h2>Panier vide</h2>
|
||||
<p>Ajoutez des produits pour commencer</p>
|
||||
<button className="continue-shopping" onClick={() => navigate("/user/nos-produits")}>
|
||||
Découvrir nos produits
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{loadingMedia && enrichedItems.length === 0 ? (
|
||||
<div className="loading-cart">
|
||||
<p>Chargement des médias...</p>
|
||||
{/* Header */}
|
||||
<div className="cart-header">
|
||||
<div className="cart-header-left">
|
||||
<h1 className="cart-title">Mon panier</h1>
|
||||
<span className="cart-header-count">
|
||||
{cartItems.length} article{cartItems.length > 1 ? "s" : ""}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="cart-items">
|
||||
{enrichedItems.map((item, index) => (
|
||||
<div
|
||||
key={`${item.id}-${index}`}
|
||||
className="cart-item"
|
||||
>
|
||||
{/* ✨ MEDIA CONTAINER - Photo + Badge Vidéo */}
|
||||
<div className="cart-item-media-container">
|
||||
<img
|
||||
src={item.image}
|
||||
alt={item.name_product}
|
||||
className="cart-item-image"
|
||||
loading="lazy"
|
||||
onError={(e) => {
|
||||
console.warn(
|
||||
`❌ Erreur chargement image pour ${item.name_product}:`,
|
||||
item.image,
|
||||
);
|
||||
e.currentTarget.src =
|
||||
"https://via.placeholder.com/400x400/7c3aed/ffffff?text=" +
|
||||
encodeURIComponent(
|
||||
item.name_product.substring(
|
||||
0,
|
||||
10,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<button className="clear-all-button" onClick={() => setShowClearConfirm(true)} disabled={loading}>
|
||||
Tout vider
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* ✨ Badge vidéo si disponible */}
|
||||
{item.hasVideo && item.videoUrl && (
|
||||
{/* Liste des articles */}
|
||||
<div className="cart-items-list">
|
||||
{loadingMedia && enrichedItems.length === 0 ? (
|
||||
<div className="loading-cart"><p>Chargement des médias...</p></div>
|
||||
) : (
|
||||
displayItems.map((item, index) => (
|
||||
<div key={`${item.id}-${index}`} className="cart-row">
|
||||
|
||||
{/* Vignette image */}
|
||||
<div className="cart-row-thumb">
|
||||
{item.image ? (
|
||||
<img
|
||||
src={item.image}
|
||||
alt={item.name_product}
|
||||
className="cart-row-img"
|
||||
loading="lazy"
|
||||
onError={(e) => { e.currentTarget.src = "https://via.placeholder.com/72x72/2d2d2d/ffffff?text=?"; }}
|
||||
/>
|
||||
) : (
|
||||
<div className="cart-row-img-placeholder">
|
||||
<i className="fas fa-leaf"></i>
|
||||
</div>
|
||||
)}
|
||||
{(item as CartItemWithMedia).hasVideo && (item as CartItemWithMedia).videoUrl && (
|
||||
<button
|
||||
className="cart-video-badge"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleVideoToggle(
|
||||
item.videoUrl!,
|
||||
);
|
||||
}}
|
||||
aria-label="Voir la vidéo du produit"
|
||||
className="cart-row-video-badge"
|
||||
onClick={(e) => { e.stopPropagation(); setCurrentVideoUrl((item as CartItemWithMedia).videoUrl!); setShowVideo(true); }}
|
||||
aria-label="Voir la vidéo"
|
||||
>
|
||||
<i className="fas fa-camera"></i>
|
||||
<span>Vidéo</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="cart-item-info">
|
||||
<h3>{item.name_product}</h3>
|
||||
<p className="cart-item-category">
|
||||
Catégorie: {item.category}
|
||||
</p>
|
||||
|
||||
{/* Quantité en grammes */}
|
||||
<p className="cart-item-quantity">
|
||||
Quantité:{" "}
|
||||
<strong>
|
||||
{item.quantity}g
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<p className="cart-item-price">
|
||||
{item.price.toFixed(2)} €
|
||||
</p>
|
||||
{/* Infos */}
|
||||
<div className="cart-row-info">
|
||||
<p className="cart-row-name">{item.name_product}</p>
|
||||
<p className="cart-row-qty">{item.quantity}g</p>
|
||||
<p className="cart-row-price">{item.price.toFixed(2)} €</p>
|
||||
</div>
|
||||
|
||||
{/* Bouton supprimer */}
|
||||
<div className="cart-item-controls">
|
||||
<button
|
||||
className="remove-item-button"
|
||||
onClick={() =>
|
||||
handleRemoveItem(item.id)
|
||||
}
|
||||
disabled={loading}
|
||||
title="Supprimer cet article"
|
||||
aria-label={`Supprimer ${item.name_product}`}
|
||||
>
|
||||
<Trash2
|
||||
size={18}
|
||||
className="trash-icon"
|
||||
/>
|
||||
Supprimer
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
className="cart-row-remove"
|
||||
onClick={() => handleRemoveItem(item.id)}
|
||||
disabled={loading}
|
||||
aria-label={`Supprimer ${item.name_product}`}
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="cart-summary">
|
||||
<div className="summary-row">
|
||||
<span>Nombre d'articles:</span>
|
||||
<span>{cartItems.length}</span>
|
||||
{/* Footer fixe */}
|
||||
<div className="cart-footer">
|
||||
<div className="cart-footer-total">
|
||||
<span className="cart-footer-total-label">Total</span>
|
||||
<span className="cart-footer-total-value">{total.toFixed(2)} €</span>
|
||||
</div>
|
||||
|
||||
<div className="summary-row total-row">
|
||||
<span>Total:</span>
|
||||
<span className="total-amount">
|
||||
{total.toFixed(2)} €
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="checkout-button"
|
||||
onClick={handleCheckout}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading
|
||||
? "Chargement..."
|
||||
: "Valider la commande"}
|
||||
<button className="checkout-button" onClick={handleCheckout} disabled={loading}>
|
||||
{loading ? "Chargement..." : "Commander"}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Modal de confirmation vidage */}
|
||||
{/* Modal vider le panier */}
|
||||
{showClearConfirm && (
|
||||
<div
|
||||
className="modal-overlay"
|
||||
onClick={() => setShowClearConfirm(false)}
|
||||
>
|
||||
<div
|
||||
className="modal-content2"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="modal-overlay" onClick={() => setShowClearConfirm(false)}>
|
||||
<div className="modal-content2" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-icon-container">
|
||||
<AlertTriangle size={48} className="modal-icon" />
|
||||
<AlertTriangle size={40} className="modal-icon" />
|
||||
</div>
|
||||
|
||||
<h2 className="modal-title">Vider le panier</h2>
|
||||
<p className="modal-message">
|
||||
Êtes-vous sûr de vouloir supprimer tous les articles
|
||||
de votre panier ? Cette action est irréversible.
|
||||
Supprimer les {cartItems.length} article{cartItems.length > 1 ? "s" : ""} du panier ?
|
||||
</p>
|
||||
|
||||
<div className="modal-actions">
|
||||
<button
|
||||
className="modal-button modal-cancel"
|
||||
onClick={() => setShowClearConfirm(false)}
|
||||
>
|
||||
<button className="modal-button modal-cancel" onClick={() => setShowClearConfirm(false)}>
|
||||
Annuler
|
||||
</button>
|
||||
<button
|
||||
className="modal-button modal-confirm"
|
||||
onClick={handleClearCart}
|
||||
disabled={loading}
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
Tout supprimer
|
||||
<button className="modal-button modal-confirm" onClick={handleClearCart} disabled={loading}>
|
||||
<Trash2 size={16} />
|
||||
Vider
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ✨ Modal vidéo (COMME PRODUCTCARD) */}
|
||||
{/* Modal vidéo */}
|
||||
{showVideo && currentVideoUrl && (
|
||||
<div className="video-modal" onClick={handleCloseVideo}>
|
||||
<div
|
||||
className="video-modal-content"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
className="video-close-btn"
|
||||
onClick={handleCloseVideo}
|
||||
aria-label="Fermer la vidéo"
|
||||
>
|
||||
<div className="video-modal" onClick={() => { setShowVideo(false); setCurrentVideoUrl(""); }}>
|
||||
<div className="video-modal-content" onClick={(e) => e.stopPropagation()}>
|
||||
<button className="video-close-btn" onClick={() => { setShowVideo(false); setCurrentVideoUrl(""); }}>
|
||||
<i className="fas fa-times"></i>
|
||||
</button>
|
||||
<video
|
||||
src={currentVideoUrl}
|
||||
controls
|
||||
autoPlay
|
||||
className="video-player"
|
||||
>
|
||||
Votre navigateur ne supporte pas la lecture de
|
||||
vidéos.
|
||||
<video src={currentVideoUrl} controls autoPlay className="video-player">
|
||||
Votre navigateur ne supporte pas la lecture de vidéos.
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user