/* ── 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 = '
'
+ '| Tipo | ID Sessione | Corso | '
+ 'Azienda | Articolo | Prima Lezione | Modifiche | Rilevato | | '
+ '
';
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 =
''
+ '| Cartella | File | Doc | Caricato SP |
'
+ '' + rows + ''
+ '
';
})
.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'));
});
})();