Notre boutique
Tout notre matériel classé par domaine, famille et catégorie. Recherchez par nom ou référence, triez comme vous voulez.
đŹ
`;
});
li.innerHTML=`
${dom}${nDom}âž
`;
tree.appendChild(li);
});
renderSelectors();
}
function esc(s){return s.replace(/'/g,"\\'");}
/* ---------- Menus déroulants directs (par nom) ---------- */
function fill(sel,items,current,allLabel){
sel.innerHTML=`
`+
items.map(i=>`
`).join("");
}
function renderSelectors(){
const doms=Object.keys(TREE);
// familles dépendantes du domaine choisi (sinon toutes)
let fams = F.dom ? Object.keys(TREE[F.dom]) : [...new Set(PRODUCTS.map(p=>p.fam))];
// catégories dépendantes du domaine/famille
let cats = PRODUCTS.filter(p=>(!F.dom||p.dom===F.dom)&&(!F.fam||p.fam===F.fam)).map(p=>p.cat);
cats=[...new Set(cats)];
fill(document.getElementById('selDom'),doms,F.dom,"Tous les domaines");
fill(document.getElementById('selFam'),fams,F.fam,"Toutes les familles");
fill(document.getElementById('selCat'),cats,F.cat,"Toutes les catégories");
}
/* Sélection d'un niveau */
function pick(dom,fam,cat,e){
if(e) e.stopPropagation();
// re-clic sur le mĂȘme = dĂ©sĂ©lection
if(cat){ F.dom=dom;F.fam=fam; F.cat=(F.cat===cat?null:cat); }
else if(fam){ F.dom=dom; F.cat=null; F.fam=(F.fam===fam?null:fam); }
else { F.cat=null;F.fam=null; F.dom=(F.dom===dom?null:dom); }
renderTree(); apply();
if(window.innerWidth<=860 && cat) openSide(false);
}
function resetFilters(){ F={dom:null,fam:null,cat:null,q:document.getElementById('q').value,sort:F.sort}; renderTree(); apply(); }
/* ---------- Filtrage + tri ---------- */
/* normalise : minuscules + suppression des accents (recherche tolérante) */
function norm(s){return (s||"").toLowerCase().normalize('NFD').replace(/[Ì-ÍŻ]/g,'');}
function apply(){
const q=norm(F.q.trim());
let list=PRODUCTS.filter(p=>{
if(F.dom && p.dom!==F.dom) return false;
if(F.fam && p.fam!==F.fam) return false;
if(F.cat && p.cat!==F.cat) return false;
if(q){
const hay=norm(p.name+" "+p.ref+" "+p.dom+" "+p.fam+" "+p.cat+" "+p.desc+" "+(p.tags||""));
// chaque mot de la recherche doit ĂȘtre prĂ©sent (recherche multi-mots)
if(!q.split(/\s+/).every(w=>hay.includes(w))) return false;
}
return true;
});
const s=F.sort;
const by=(k)=>(a,b)=>(""+a[k]).localeCompare(""+b[k],'fr');
if(s==="name-asc")list.sort(by('name'));
else if(s==="name-desc")list.sort((a,b)=>(""+b.name).localeCompare(a.name,'fr'));
else if(s==="price-asc")list.sort((a,b)=>a.price-b.price);
else if(s==="price-desc")list.sort((a,b)=>b.price-a.price);
else if(s==="ref")list.sort(by('ref'));
else if(s==="cat")list.sort(by('cat'));
else if(s==="dom")list.sort(by('dom'));
else if(s==="fam")list.sort(by('fam'));
renderGrid(list);
renderInfo(list.length);
renderChips();
}
function renderInfo(n){
document.getElementById('info').innerHTML=`
${n} produit${n>1?'s':''} ${F.dom||F.fam||F.cat||F.q?'trouvé'+(n>1?'s':''):'au catalogue'}`;
}
function renderChips(){
const c=document.getElementById('chips'); c.innerHTML="";
const add=(label,clear)=>{const e=document.createElement('span');e.className="chip";e.innerHTML=`${label}
â`;e.querySelector('.x').onclick=clear;c.appendChild(e);};
if(F.dom) add("Domaine : "+F.dom,()=>{F.dom=F.fam=F.cat=null;renderTree();apply();});
if(F.fam) add("Famille : "+F.fam,()=>{F.fam=F.cat=null;renderTree();apply();});
if(F.cat) add("Catégorie : "+F.cat,()=>{F.cat=null;renderTree();apply();});
if(F.q) add("Recherche : "+F.q,()=>{F.q="";document.getElementById('q').value="";apply();});
}
function renderGrid(list){
const grid=document.getElementById('grid'); grid.innerHTML="";
if(!list.length){
grid.innerHTML=`
đ
Aucun produit ne correspond Ă votre recherche.
`;
return;
}
list.forEach(p=>{
const msg=encodeURIComponent(`Bonjour, je suis intĂ©ressĂ©(e) par : ${p.name} (rĂ©f. ${p.ref}, ${p.price.toFixed(2)} âŹ). Est-il disponible ?`);
const out=(typeof p.stock==='number' && p.stock<=0); // null = stock non géré = disponible
const el=document.createElement('div'); el.className="prod";
el.innerHTML=`
${p.old?'PROMO':''}
${out?'Sur commande':'En stock'}
${p.icon}
Réf. ${p.ref}
${p.dom} âș ${p.fam} âș ${p.cat}
${p.name}
${p.desc}
${p.price.toFixed(2)} âŹ${p.old?`${p.old.toFixed(2)} âŹ`:''}
`;
grid.appendChild(el);
});
}
/* ---------- Sidebar mobile ---------- */
function openSide(o){
document.getElementById('side').classList.toggle('open',o);
document.getElementById('backdrop').classList.toggle('show',o);
}
/* ---------- ĂvĂ©nements ---------- */
document.getElementById('q').addEventListener('input',e=>{F.q=e.target.value;apply();renderChips();});
document.getElementById('sort').addEventListener('change',e=>{F.sort=e.target.value;apply();});
/* Menus déroulants : sélection directe par nom */
function domOf(fam){return Object.keys(TREE).find(d=>TREE[d][fam]);}
function locOfCat(cat){const p=PRODUCTS.find(x=>x.cat===cat);return p?{dom:p.dom,fam:p.fam}:{};}
document.getElementById('selDom').addEventListener('change',e=>{F.dom=e.target.value||null;F.fam=null;F.cat=null;renderTree();apply();});
document.getElementById('selFam').addEventListener('change',e=>{const v=e.target.value||null;F.fam=v;F.cat=null;if(v&&!F.dom)F.dom=domOf(v);renderTree();apply();});
document.getElementById('selCat').addEventListener('change',e=>{const v=e.target.value||null;F.cat=v;if(v){const l=locOfCat(v);F.dom=l.dom;F.fam=l.fam;}renderTree();apply();});
document.getElementById('y').textContent=new Date().getFullYear();
/* ---------- Init (avec sync optionnelle) ---------- */
async function init(){
if(CATALOG_URL){
try{
const r=await fetch(CATALOG_URL,{cache:"no-store"});
const data=await r.json();
const list=Array.isArray(data)?data:data.products;
if(list&&list.length){ PRODUCTS=list; TREE=buildTree(); }
}catch(e){ console.warn("Catalogue distant indisponible, utilisation des données intégrées.",e); }
}
renderTree(); apply();
}
init();