/* ── Filter + grouped view ─────────────────────────────────────────────── */ (function(){ var today = new Date().toISOString().slice(0,10); var sevenAgo = new Date(Date.now() - 7*86400000).toISOString().slice(0,10); document.getElementById('f-da').value = sevenAgo; document.getElementById('f-a').value = today; var table = document.querySelector('.tw table'); var tbody = table.querySelector('tbody'); var thead = table.querySelector('thead'); var allFlatRows = Array.prototype.slice.call(tbody.querySelectorAll('tr')); var flatTheadHTML = thead.innerHTML; var groupedTheadHTML = '' + 'TipoID SessioneCorso' + 'AziendaArticoloPrima LezioneModificheRilevato' + ''; var isGrouped = false; function esc(s) { return String(s == null ? '' : s) .replace(/&/g,'&').replace(//g,'>'); } function badgeHtml(tipo) { if (tipo === 'nuovo') return 'Nuovo'; if (tipo === 'modificato') return 'Modificato'; return esc(tipo); } function getRowData(row) { var c = row.cells; return { tipo: row.getAttribute('data-tipo') || '', sessione_id: c[1] ? c[1].textContent.trim() : '', corso: c[2] ? c[2].textContent.trim() : '', azienda: c[3] ? c[3].textContent.trim() : '', articolo: c[4] ? c[4].textContent.trim() : '', prima_lezione: c[5] ? c[5].textContent.trim() : '', campo: c[6] ? c[6].textContent.trim() : '', valore_prec: c[7] ? c[7].textContent.trim() : '', valore_nuovo: c[8] ? c[8].textContent.trim() : '', rilevato: c[9] ? c[9].textContent.trim() : '', }; } function toIso(rilevato) { var m = rilevato.match(/(\d{2})\/(\d{2})\/(\d{4})/); return m ? m[3] + '-' + m[2] + '-' + m[1] : ''; } function getFilters() { var tipi = []; document.querySelectorAll('.tipo-chk:checked').forEach(function(c){ tipi.push(c.value); }); return { da: document.getElementById('f-da').value, a: document.getElementById('f-a').value, sid: document.getElementById('f-sid').value.trim(), tipi: tipi, }; } function passes(d, f) { var pd = toIso(d.prima_lezione); return (!f.da || pd >= f.da) && (!f.a || pd <= f.a) && (!f.sid || d.sessione_id === f.sid) && f.tipi.indexOf(d.tipo) !== -1; } function updateCount(n) { document.getElementById('visible-count').textContent = n + ' righe'; } function applyFlat(f) { tbody.innerHTML = ''; allFlatRows.forEach(function(r) { tbody.appendChild(r); }); var n = 0; allFlatRows.forEach(function(row) { var ok = passes(getRowData(row), f); row.style.display = ok ? '' : 'none'; if (ok) n++; }); updateCount(n); } function applyGrouped(f) { var visible = allFlatRows.filter(function(r) { return passes(getRowData(r), f); }); var groups = {}, order = []; visible.forEach(function(row) { var d = getRowData(row); var key = d.sessione_id || '__?__'; if (!groups[key]) { groups[key] = { base: d, tipi: [], changes: [], latestIso: '', latestRilevato: '' }; order.push(key); } var g = groups[key]; if (g.tipi.indexOf(d.tipo) === -1) g.tipi.push(d.tipo); var iso = toIso(d.rilevato); if (iso > g.latestIso) { g.latestIso = iso; g.latestRilevato = d.rilevato; } if (d.campo && d.campo !== '-') { g.changes.push({ campo: d.campo, prec: d.valore_prec, nuovo: d.valore_nuovo }); } }); var html = ''; order.forEach(function(key) { var g = groups[key]; var b = g.base; var tipiHtml = g.tipi.map(badgeHtml).join(' '); var modHtml = g.changes.length ? g.changes.map(function(c) { return '
' + '' + esc(c.campo) + ': ' + '' + esc(c.prec) + '' + ' → ' + '' + esc(c.nuovo) + '' + '
'; }).join('') : '\u2014'; html += '' + '' + tipiHtml + '' + '' + esc(b.sessione_id) + '' + '' + esc(b.corso) + '' + '' + esc(b.azienda) + '' + '' + esc(b.articolo) + '' + '' + esc(b.prima_lezione) + '' + '' + modHtml + '' + '' + esc(g.latestRilevato) + '' + '' + ''; }); tbody.innerHTML = html || 'Nessun dato'; updateCount(order.length); } function applyFilters() { var f = getFilters(); if (isGrouped) applyGrouped(f); else applyFlat(f); } document.getElementById('btn-toggle-view').addEventListener('click', function() { isGrouped = !isGrouped; this.textContent = isGrouped ? '\u229e Tabella' : '\u2a27 Raggruppa corso'; this.classList.toggle('active', isGrouped); thead.innerHTML = isGrouped ? groupedTheadHTML : flatTheadHTML; applyFilters(); }); document.getElementById('btn-filter').addEventListener('click', applyFilters); document.getElementById('btn-reset').addEventListener('click', function(){ document.getElementById('f-da').value = sevenAgo; document.getElementById('f-a').value = today; document.getElementById('f-sid').value = ''; document.querySelectorAll('.tipo-chk').forEach(function(c){ c.checked = true; }); applyFilters(); }); document.querySelectorAll('.tipo-chk').forEach(function(c){ c.addEventListener('change', applyFilters); }); applyFilters(); })(); /* ── Docs modal ────────────────────────────────────────────────────────── */ (function(){ var modal = document.getElementById('docs-modal'); var modalBody = document.getElementById('docs-modal-body'); var modalSid = document.getElementById('docs-modal-sid'); var modalCorso = document.getElementById('docs-modal-corso'); function esc(s) { return String(s == null ? '' : s) .replace(/&/g,'&').replace(//g,'>'); } function openDocsModal(sid, corso) { modalSid.textContent = sid; modalCorso.textContent = corso || ''; modalBody.innerHTML = '

Caricamento\u2026

'; modal.style.display = 'flex'; fetch('/api/docs?sessione_id=' + encodeURIComponent(sid)) .then(function(r){ return r.json(); }) .then(function(docs) { if (!docs || docs.length === 0) { modalBody.innerHTML = '

Nessun documento caricato.

'; return; } var rows = docs.map(function(d) { var st = d.doc_status || ''; var badge = '' + esc(st) + ''; var fn = d.filename || ''; var fnHtml = esc(fn); if (fn.charAt(0) === '[' && fn.charAt(fn.length - 1) === ']') fnHtml = '' + fnHtml + ''; var name = d.sp_web_url ? '' + fnHtml + '' : fnHtml; var ts = d.uploaded_at ? d.uploaded_at.slice(0,16).replace('T',' ') : '-'; return '' + '' + esc(d.subfolder) + '' + '' + name + '' + '' + badge + '' + '' + ts + '' + ''; }).join(''); modalBody.innerHTML = '' + '' + '' + rows + '' + '
CartellaFileDocCaricato SP
'; }) .catch(function(err) { modalBody.innerHTML = '

Errore: ' + esc(String(err)) + '

'; }); } function closeDocsModal() { modal.style.display = 'none'; } document.getElementById('docs-modal-close').addEventListener('click', closeDocsModal); modal.addEventListener('click', function(ev) { if (ev.target === modal) closeDocsModal(); }); document.addEventListener('keydown', function(ev) { if (ev.key === 'Escape') closeDocsModal(); }); document.querySelector('.tw').addEventListener('click', function(ev) { var btn = ev.target.closest('.doc-btn'); if (btn) openDocsModal(btn.getAttribute('data-sid'), btn.getAttribute('data-corso')); }); })();