/* global React */
const { useState, useEffect, useMemo, useRef } = React;
// -------- Icons (inline SVGs) --------
const Icon = {
Search: () => ( ),
Heart: ({filled}) => ( ),
X: () => ( ),
Bag: () => ( ),
Arrow: () => ( ),
Repeat: () => ( ),
Check: () => ( ),
Download: () => ( ),
Sparkle: () => ( ),
};
// -------- Helpers --------
const fmt = (n) => n.toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €';
const fmt0 = (n) => Math.round(n).toLocaleString('fr-FR') + ' €';
// -------- Qty stepper --------
function QtyStepper({ value, onChange, min = 3 }) {
const dec = () => onChange(Math.max(min, value - 1));
const inc = () => onChange(value + 1);
const set = (v) => {
const n = parseInt(v, 10);
if (isNaN(n)) onChange(min);
else onChange(Math.max(min, n));
};
return (
e.stopPropagation()}>
−
set(e.target.value)}
onClick={(e) => e.target.select()}
/>
+
);
}
// -------- Product Card --------
function ProductCard({ product, cartQty, onAdd, onSetQty, onFav, isFav, onQuickView, reordered }) {
const inCart = cartQty > 0;
const available = product.available;
const isIdentified = !!(window.CLIENT && window.CLIENT.identified);
const signupUrl = (window.EXTRANET_CONFIG?.base_url || '') + '/#auth';
return (
{
if (!isIdentified) { window.location.href = signupUrl; return; }
if (available) onQuickView(product);
}}
>
{e.target.style.opacity=0.2;e.target.src="data:image/svg+xml;utf8,
";}}/>
{product.isNew && Nouveau }
{product.popular && available && !product.isNew && ★ Best }
{!available && Rupture }
{reordered && available && Déjà commandé }
{isIdentified && (
{ e.stopPropagation(); onFav(product.ref); }}
aria-label="Favori"
>
)}
{available && isIdentified &&
{ e.stopPropagation(); onQuickView(product); }}>Aperçu rapide }
{product.ref}
{product.name}
);
}
// -------- Quick View Modal --------
function QuickViewModal({ product, onClose, cartQty, onSetQty, onAdd, productsByRef, onSwitch }) {
useEffect(() => {
const handler = (e) => e.key === 'Escape' && onClose();
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, [onClose]);
if (!product) return null;
const cobought = (window.COBOUGHT[product.ref] || []).map(r => productsByRef[r]).filter(Boolean);
const themeLabel = window.THEMES[product.theme] || '';
const catLabel = (window.CATEGORIES.find(c => c.id === product.cat) || {}).label || '';
return (
e.stopPropagation()}>
{product.ref}
{product.name}
{fmt(product.price)} HT · par 3 minimum
Kit créatif artisanal complet, livré avec tous les éléments nécessaires et le pas-à-pas illustré.
Conçu et préparé à la main dans nos ateliers en France — idéal pour vos clients en quête d'une activité douce et inspirante.
Catégorie · {catLabel}
Type · {themeLabel}
Conditionné par 3
{product.popular && ★ Best-seller }
{cartQty > 0 ? (
onSetQty(product.ref, q)} />
) : (
onAdd(product.ref)}> Ajouter au bon de commande
)}
{cartQty > 0 && Sous-total : {fmt(cartQty * product.price)} }
{cobought.length > 0 && (
Souvent commandés ensemble
{cobought.slice(0, 3).map(p => (
onSwitch(p)}>
{p.name}
{p.ref} · {fmt(p.price)}
))}
)}
);
}
// Expose
Object.assign(window, { QtyStepper, ProductCard, QuickViewModal, Icon, fmt, fmt0 });