feat: filtre par catégorie dans la GUI
Docker / docker (push) Successful in 1m15s

- arte_api.py : GENRE_PAGES devient une liste de (nom, url), chaque
  concert reçoit un champ "categories" avec ses genres d'appartenance
- main.py : endpoint /api/categories + param ?category= sur /api/concerts
- index.html : barre de pills catégories (Tout + 10 genres)
- style.css : styles .cat-bar / .cat-pill avec pill active en or
- app.js : chargement dynamique des pills, filtre catégorie dans le state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dev
2026-04-26 13:03:52 +02:00
parent 1815a4e8c2
commit 16736e2e7a
5 changed files with 122 additions and 30 deletions
+28 -1
View File
@@ -4,6 +4,7 @@
const state = {
page: 1,
search: '',
category: '',
pageSize: 24,
totalPages: 1,
current: null, // concert object shown in modal
@@ -21,6 +22,7 @@ const modalOverlay = $('modal-overlay');
const dlPanel = $('dl-panel');
const dlPanelBody = $('dl-panel-body');
const dlBadge = $('dl-badge');
const catBar = $('cat-bar');
// ── Helpers ──────────────────────────────────────────────────────────────────
function fmtDuration(secs) {
@@ -45,12 +47,37 @@ function debounce(fn, ms) {
let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms); };
}
// ── Categories ───────────────────────────────────────────────────────────────
async function loadCategories() {
try {
const cats = await fetch('/api/categories').then(r => r.json());
cats.forEach(cat => {
const btn = document.createElement('button');
btn.className = 'cat-pill';
btn.dataset.cat = cat;
btn.textContent = cat;
catBar.appendChild(btn);
});
} catch {}
}
catBar.addEventListener('click', e => {
const pill = e.target.closest('.cat-pill');
if (!pill) return;
catBar.querySelectorAll('.cat-pill').forEach(p => p.classList.remove('active'));
pill.classList.add('active');
state.category = pill.dataset.cat;
state.page = 1;
refresh();
});
// ── Concerts ─────────────────────────────────────────────────────────────────
async function loadConcerts() {
const params = new URLSearchParams({
page: state.page,
search: state.search,
page_size: state.pageSize,
category: state.category,
});
const res = await fetch(`/api/concerts?${params}`);
if (!res.ok) throw new Error(res.statusText);
@@ -359,6 +386,6 @@ document.addEventListener('keydown', e => {
// ── Init ─────────────────────────────────────────────────────────────────────
(async () => {
await refreshDlHistory();
await Promise.all([loadCategories(), refreshDlHistory()]);
await refresh();
})();