// ===== Données exemple (contexte terrain / chantier) ===== let products = [ { id: 1, name: "Gants de manutention", unit: "paire", qty: 3 }, { id: 2, name: "Vis autoperceuse 4.8×38", unit: "boîte", qty: 2 }, { id: 3, name: "Marteau de coffreur 700g", unit: "pièce", qty: 1 }, { id: 4, name: "Chaussures de sécurité S3", unit: "paire", qty: 1 }, { id: 5, name: "Niveau à bulle 40 cm", unit: "pièce", qty: 1 }, { id: 6, name: "Ruban de mesure 5 m", unit: "pièce", qty: 2 }, { id: 7, name: "Bobine de fil de tension", unit: "pièce", qty: 1 }, { id: 8, name: "Serre-joints 80 cm", unit: "pièce", qty: 2 }, { id: 9, name: "Cutter lame 18 mm", unit: "pièce", qty: 3 }, { id: 10, name: "Lunettes de protection", unit: "pièce", qty: 5 }, { id: 11, name: "Coffret forets béton SDS", unit: "boîte", qty: 1 }, { id: 12, name: "Gilet haute visibilité Classe 2", unit: "pièce", qty: 4 }, ]; let activeId = null; const listEl = document.getElementById('product-list'); const headerCountEl = document.getElementById('header-count'); const totalQtyEl = document.getElementById('total-qty'); // ===== Rendu initial ===== function init() { renderList(); updateSummary(); lucide.createIcons(); } function renderList() { listEl.innerHTML = products.map(p => `
${escapeHtml(p.name)}
${escapeHtml(p.unit)}
${p.qty}
`).join(''); lucide.createIcons(); } function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // ===== Mise à jour du résumé ===== function updateSummary() { const total = products.reduce((sum, p) => sum + p.qty, 0); const count = products.length; headerCountEl.textContent = `${count} article${count > 1 ? 's' : ''}`; totalQtyEl.textContent = total; } // ===== Gestion du focus / activation ===== function setActiveId(id) { // Désactiver l’ancien if (activeId !== null) { const oldRow = document.querySelector(`.product-row[data-id="${activeId}"]`); if (oldRow) oldRow.classList.remove('active'); } activeId = id; // Activer le nouveau if (activeId !== null) { const newRow = document.querySelector(`.product-row[data-id="${activeId}"]`); if (newRow) newRow.classList.add('active'); } } // ===== Actions quantité / suppression ===== function updateQty(id, delta) { const product = products.find(p => p.id === id); if (!product) return; const newQty = product.qty + delta; if (newQty < 1) return; // empêche de descendre sous 1 (utiliser la poubelle) product.qty = newQty; // Mise à jour DOM ciblée (pas de re-render complet pour garder l’état visuel) const badge = document.querySelector(`.qty-badge[data-qty-id="${id}"]`); if (badge) badge.textContent = product.qty; updateSummary(); } function deleteProduct(id) { const row = document.querySelector(`.product-row[data-id="${id}"]`); if (row) { // Animation rapide de sortie row.style.transition = "opacity 0.2s ease, transform 0.2s ease, max-height 0.25s ease"; row.style.opacity = "0"; row.style.transform = "translateX(-1rem)"; row.style.maxHeight = row.offsetHeight + "px"; requestAnimationFrame(() => { row.style.maxHeight = "0px"; row.style.padding = "0px"; row.style.margin = "0px"; row.style.overflow = "hidden"; }); } setTimeout(() => { products = products.filter(p => p.id !== id); if (activeId === id) activeId = null; renderList(); updateSummary(); // Ré-applique l’état actif si un autre était déjà sélectionné (théoriquement impossible ici car 1 seul actif) if (activeId !== null) { const remain = document.querySelector(`.product-row[data-id="${activeId}"]`); if (remain) remain.classList.add('active'); } }, 220); } // ===== Écouteurs d’événements ===== // Clics sur les lignes et boutons (délégation) listEl.addEventListener('click', (e) => { const btn = e.target.closest('[data-action]'); // 1. Bouton d’action (+, –, poubelle) if (btn) { e.stopPropagation(); const row = btn.closest('.product-row'); const id = parseInt(row.dataset.id, 10); const action = btn.dataset.action; if (action === 'plus') updateQty(id, 1); else if (action === 'minus') updateQty(id, -1); else if (action === 'delete') deleteProduct(id); return; } // 2. Ligne produit (hors bouton) const row = e.target.closest('.product-row'); if (row) { const id = parseInt(row.dataset.id, 10); // Si on tape la ligne déjà active → on la referme // Sinon on active la nouvelle setActiveId(activeId === id ? null : id); } }); // Clic en dehors des lignes (zone vide, header, footer…) → désactive tout document.getElementById('app').addEventListener('click', (e) => { const row = e.target.closest('.product-row'); const btn = e.target.closest('[data-action]'); if (!row && !btn) { setActiveId(null); } }); // Démarrage init();