chore: build
This commit is contained in:
@@ -7,7 +7,13 @@ 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 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);
|
||||
@@ -22,10 +28,11 @@ interface ProductCardProps {
|
||||
image: string;
|
||||
stock: number;
|
||||
category: string;
|
||||
prices?: Array<{ quantity: number; price: number }>;
|
||||
prices?: Array<{ quantity: number; price: number; active_price?: boolean }>;
|
||||
hasVideo?: boolean;
|
||||
videoUrl?: string; // ✨ Nouveau prop pour l'URL de la vidéo
|
||||
categoryColor?: string;
|
||||
coming_soon?: boolean;
|
||||
}
|
||||
|
||||
function ProductCard({
|
||||
@@ -40,6 +47,7 @@ function ProductCard({
|
||||
hasVideo = false,
|
||||
videoUrl,
|
||||
categoryColor,
|
||||
coming_soon,
|
||||
}: ProductCardProps) {
|
||||
const navigate = useNavigate();
|
||||
const { addToCart } = useCart();
|
||||
@@ -52,6 +60,7 @@ function ProductCard({
|
||||
const [showVideo, setShowVideo] = useState(false); // ✨ État pour afficher/masquer la vidéo
|
||||
|
||||
const isOutOfStock = stock === 0;
|
||||
const isComingSoon = coming_soon === true;
|
||||
const normalizedCategory = (category || "autre").toLowerCase().trim();
|
||||
|
||||
const handleDetailsClick = (e: React.MouseEvent) => {
|
||||
@@ -156,6 +165,9 @@ function ProductCard({
|
||||
{isOutOfStock && (
|
||||
<div className="sold-out-overlay">SOLD OUT</div>
|
||||
)}
|
||||
{isComingSoon && (
|
||||
<div className="coming-soon-overlay">COMMING SOON</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="product-info">
|
||||
@@ -177,18 +189,23 @@ function ProductCard({
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
className={`quick-add-btn ${isOutOfStock ? "disabled" : ""}`}
|
||||
className={`quick-add-btn ${isOutOfStock || isComingSoon ? "disabled" : ""}`}
|
||||
onClick={handleQuickAddClick}
|
||||
disabled={isOutOfStock}
|
||||
disabled={isOutOfStock || isComingSoon}
|
||||
style={
|
||||
categoryColor && !isOutOfStock
|
||||
? { background: categoryColor, color: getTextColor(categoryColor) }
|
||||
categoryColor && !isOutOfStock && !isComingSoon
|
||||
? {
|
||||
background: categoryColor,
|
||||
color: getTextColor(categoryColor),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{isOutOfStock
|
||||
? "Rupture de stock"
|
||||
: "Ajouter rapidement"}
|
||||
: isComingSoon
|
||||
? "BIENTÔT DISPONIBLE"
|
||||
: "Ajouter rapidement"}
|
||||
</button>
|
||||
|
||||
{showQuantitySelect && prices && prices.length > 0 && (
|
||||
@@ -209,8 +226,9 @@ function ProductCard({
|
||||
key={priceOption.quantity}
|
||||
value={priceOption.quantity}
|
||||
>
|
||||
{priceOption.quantity}{unit} -{" "}
|
||||
{priceOption.price.toFixed(2)} €
|
||||
{priceOption.quantity}
|
||||
{unit} - {priceOption.price.toFixed(2)}{" "}
|
||||
€
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -220,32 +238,34 @@ function ProductCard({
|
||||
</div>
|
||||
|
||||
{/* ✨ Modal vidéo — rendu via Portal pour éviter le clipping du transform:scale sur .product-card */}
|
||||
{showVideo && videoUrl && createPortal(
|
||||
<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"
|
||||
{showVideo &&
|
||||
videoUrl &&
|
||||
createPortal(
|
||||
<div className="video-modal" onClick={handleCloseVideo}>
|
||||
<div
|
||||
className="video-modal-content"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
<video
|
||||
src={videoUrl}
|
||||
controls
|
||||
autoPlay
|
||||
className="video-player"
|
||||
>
|
||||
Votre navigateur ne supporte pas la lecture de
|
||||
vidéos.
|
||||
</video>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
<button
|
||||
className="video-close-btn"
|
||||
onClick={handleCloseVideo}
|
||||
aria-label="Fermer la vidéo"
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
<video
|
||||
src={videoUrl}
|
||||
controls
|
||||
autoPlay
|
||||
className="video-player"
|
||||
>
|
||||
Votre navigateur ne supporte pas la lecture de
|
||||
vidéos.
|
||||
</video>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user