chore: build

This commit is contained in:
2026-06-14 17:50:35 +02:00
parent 3c92a0371f
commit 3a0f725159
93 changed files with 5311 additions and 4224 deletions
+54 -34
View File
@@ -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>
);
}