Modul-Datumsfilter: Picker auch im Detail-Modal + global persistent

- Datums-Picker (von/bis) jetzt auch im Modul-Detail-Modal; Aendern laedt die
  Ansicht mit neuem Zeitraum und haelt Uebersichts-Cards synchron
- _modFilter global in localStorage persistiert (bleibt bis Aenderung)
- resetModDateModal ↺ setzt auf Schuljahresbeginn

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 19:07:38 +02:00
parent 52e9fafd92
commit 532956fd7d
+35 -8
View File
@@ -2372,8 +2372,13 @@ async function ivOpenStudent(sid){
// === ÜBERSICHT ===
// Lehrer-Übersicht: Stat-Bar + aktive Aufgaben + Top-Performer + Aktivitäts-Sparkline + Modul-Cards.
// Drei parallele API-Calls (matrix + activity-week + assignments) — alle existing.
// === Schuljahr-Datumsfilter für die Modul-Sektion ===
// === Schuljahr-Datumsfilter für die Modul-Sektion (global, persistent) ===
var _modFilter = { from: null, to: null };
try {
var _mfStored = JSON.parse(localStorage.getItem('ggs-mod-filter') || 'null');
if (_mfStored && _mfStored.from && _mfStored.to) { _modFilter.from = _mfStored.from; _modFilter.to = _mfStored.to; }
} catch (e) {}
function saveModFilter() { try { localStorage.setItem('ggs-mod-filter', JSON.stringify(_modFilter)); } catch (e) {} }
function ggsTodayStr() {
var d = new Date();
return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0');
@@ -2482,10 +2487,7 @@ function renderModulesSection(modStats) {
html += '</div></div>';
return html;
}
async function applyModFilter() {
var f = document.getElementById('mf-from'), t = document.getElementById('mf-to');
if (f && f.value) _modFilter.from = f.value;
if (t && t.value) _modFilter.to = t.value;
async function refreshModulesSection() {
var host = document.getElementById('ov-modules'); if (!host) return;
host.style.opacity = '.5';
var ms = await api('results?class_id=' + currentClassId + '&view=mod_stats&from=' + _modFilter.from + '&to=' + _modFilter.to);
@@ -2493,11 +2495,32 @@ async function applyModFilter() {
host.style.opacity = '';
host.innerHTML = renderModulesSection(ms);
}
async function applyModFilter() {
var f = document.getElementById('mf-from'), t = document.getElementById('mf-to');
if (f && f.value) _modFilter.from = f.value;
if (t && t.value) _modFilter.to = t.value;
saveModFilter();
await refreshModulesSection();
}
function resetModFilter() {
_modFilter.from = ggsSchoolYearStart();
_modFilter.to = ggsTodayStr();
saveModFilter();
applyModFilter();
}
// Vom Modul-Detail-Modal aus den globalen Zeitraum ändern
function setModDate(which, val) {
if (!val) return;
_modFilter[which] = val; saveModFilter();
if (_modDetail && _modDetail.moduleId) openModuleDetail(_modDetail.moduleId);
refreshModulesSection();
}
function resetModDateModal() {
_modFilter.from = ggsSchoolYearStart();
_modFilter.to = ggsTodayStr(); saveModFilter();
if (_modDetail && _modDetail.moduleId) openModuleDetail(_modDetail.moduleId);
refreshModulesSection();
}
// Avatar-Bild oder Emoji, gegebene Pixelgröße
function ivTodayAvatar(emoji, px) {
@@ -3683,9 +3706,13 @@ function renderModDetail() {
var html = '<div style="display:flex;align-items:center;gap:.6rem;margin-bottom:.6rem">';
html += '<span style="font-size:2rem">'+d.module.icon+'</span>';
html += '<div><h3 style="margin:0">'+esc(d.module.name)+'</h3>';
function dmy(s){ if(!s) return ''; var p=s.split('-'); return p[2]+'.'+p[1]+'.'+p[0].slice(2); }
var zeit = (d.from && d.to) ? ' · <b style="color:#4a6a4e">'+dmy(d.from)+''+dmy(d.to)+'</b>' : '';
html += '<div style="font-size:.7rem;color:#8a8a8a">Klasse: '+d.classStats.totalPlays+' Durchgänge · '+totalH+'h Spielzeit · Ø '+(d.classStats.avgStars||'')+'★ · '+d.classStats.studentsActive+'/'+d.classStats.studentsTotal+' aktiv'+zeit+'</div></div></div>';
html += '<div style="font-size:.7rem;color:#8a8a8a">Klasse: '+d.classStats.totalPlays+' Durchgänge · '+totalH+'h Spielzeit · Ø '+(d.classStats.avgStars||'')+'★ · '+d.classStats.studentsActive+'/'+d.classStats.studentsTotal+' aktiv</div>';
var mfFrom = d.from || _modFilter.from || '', mfTo = d.to || _modFilter.to || '';
html += '<div style="display:inline-flex;align-items:center;gap:.35rem;font-size:.68rem;color:#6a6a6a;margin-top:.3rem">Zeitraum: '
+ '<input type="date" value="'+mfFrom+'" onchange="setModDate(\'from\',this.value)" style="font:inherit;padding:.12rem .35rem;border:1px solid #ccc;border-radius:5px">'
+ ' <input type="date" value="'+mfTo+'" onchange="setModDate(\'to\',this.value)" style="font:inherit;padding:.12rem .35rem;border:1px solid #ccc;border-radius:5px">'
+ '<button class="btn-sm" style="padding:.12rem .5rem" onclick="resetModDateModal()" title="Auf Schuljahresbeginn zurücksetzen"></button></div>';
html += '</div></div>';
var hl = d.highlights || [];
var champs = d.champions || {};