// ---------- ÉTAT ---------- let HISTORY_CACHE = []; // [{ date, rawDate, items: [...] }] let HISTORY_SEARCH = ""; // Normalisation basique pour la recherche const ACCENT_RX = /[\u0300-\u036f]/g; const norm = s => (s || "").toString().toLowerCase() .normalize("NFD").replace(ACCENT_RX, "").trim(); // Palette de couleurs (plus large possible pour différencier) const USER_COLORS = [ "#C0392B", // rouge foncé "#2980B9", // bleu foncé "#27AE60", // vert foncé "#D35400", // orange foncé "#8E44AD", // violet foncé "#2C3E50", // gris/bleu très foncé "#7D3C98", // violet profond "#1ABC9C" // turquoise foncé ]; // Cache pour assigner une couleur unique par user const userColorMap = new Map(); let userColorIndex = 0; function getUserColor(username) { if (!username) return "#999"; if (!userColorMap.has(username)) { // Assigne une couleur en cycle userColorMap.set(username, USER_COLORS[userColorIndex % USER_COLORS.length]); userColorIndex++; } return userColorMap.get(username); } function buildUserBadges(usersArr) { const wrap = document.createElement("div"); wrap.className = "label-container"; (usersArr || []).forEach(u => { const span = document.createElement("span"); span.className = "label-badge user-badge"; span.textContent = u; // Couleur dynamique par utilisateur span.style.backgroundColor = getUserColor(u); span.style.color = "#fff"; // texte blanc pour lisibilité wrap.appendChild(span); }); return wrap; } const truncate = (s, m) => (s && s.length > m ? s.slice(0, m) + "…" : (s ?? "")); function buildRecipeCardHistory(rec) { const card = document.createElement("div"); card.className = "card"; card.id = `hist-${rec.id}`; const name = rec.name || `Recette ${rec.id}`; const imgSrc = rec.image || "/images/recipe-placeholder.png"; // mets un vrai fichier ici card.innerHTML = `
${truncate(name, 10)}
${rec.portions} portion${rec.portions > 1 ? 's' : ''}

${name}

`; // badges utilisateurs (JSON camelCase => "users") const users = Array.isArray(rec.users) ? rec.users : Array.isArray(rec.Users) ? rec.Users : []; if (users.length) { card.querySelector(".image-container")?.appendChild(buildUserBadges(users)); } return card; } function buildDateSection(dateStr, items) { const sec = document.createElement("section"); sec.className = "history-section"; const h = document.createElement("h3"); h.className = "history-date"; h.textContent = dateStr; sec.appendChild(h); const grid = document.createElement("div"); grid.className = "hf-grid"; if (Array.isArray(items) && items.length) { items.forEach(r => grid.appendChild(buildRecipeCardHistory(r))); } else { grid.innerHTML = `

Aucune recette pour cette date.

`; } sec.appendChild(grid); return sec; } // Applique la recherche sur le cache et rend function renderHistoryFiltered() { const container = document.getElementById("historyContainer"); if (!container) return; const q = norm(HISTORY_SEARCH); const groups = []; for (const g of (HISTORY_CACHE || [])) { if (!q) { groups.push(g); continue; } const filteredItems = (g.items || []).filter(it => norm(it.name).includes(q)); if (filteredItems.length) { groups.push({ date: g.date, rawDate: g.rawDate, items: filteredItems }); } } container.innerHTML = ""; if (!groups.length) { container.innerHTML = `

Aucun résultat pour “${HISTORY_SEARCH}”.

`; return; } groups.forEach(group => container.appendChild(buildDateSection(group.date, group.items))); } // ---------- CHARGEMENT ---------- async function loadHistory(scope = "mine") { const container = document.getElementById("historyContainer"); if (!container) return; container.innerHTML = "Chargement…"; try { const isUserImportant = (scope !== "all"); const res = await fetch(`/HelloFresh/GetHistory?isUserImportant=${isUserImportant ? "true" : "false"}&search=${encodeURIComponent(HISTORY_SEARCH)}`, { credentials: "same-origin" }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); // [{ date, rawDate, items }] HISTORY_CACHE = Array.isArray(data) ? data : []; renderHistoryFiltered(); // premier rendu (avec éventuel terme déjà saisi) } catch (e) { console.error("loadHistory error:", e); container.innerHTML = `

Erreur de chargement.

`; } } // ---------- INIT ---------- document.addEventListener("DOMContentLoaded", () => { const scopeSel = document.getElementById("historyScope"); const search = document.getElementById("historySearch"); // charge au démarrage loadHistory(scopeSel?.value || "mine"); // changement de portée scopeSel?.addEventListener("change", () => loadHistory(scopeSel.value || "mine")); // recherche (debounce) let timer; search?.addEventListener("input", (e) => { HISTORY_SEARCH = e.target.value || ""; clearTimeout(timer); timer = setTimeout(renderHistoryFiltered, 200); }); // Entrée = rendu immédiat search?.addEventListener("keydown", (e) => { if (e.key === "Enter") { e.preventDefault(); clearTimeout(timer); renderHistoryFiltered(); } }); });