// ----------------------------- // Projektübersicht — Sitzungs-/Wochen-Verwaltung // ----------------------------- // Diese Datei verwaltet die Sitzungen (Wochen): Auswahl, Anzeige des Datums, // Erzeugung neuer Sitzungen, Duplizieren, Sperren (Auto-Lock) und Löschen. // Sie wird von `Test.html` nach `js/store.js` geladen und stellt globale // Funktionen wie `currentWeek()`, `switchWeek()`, `newWeek()`, `cloneWeek()`, // `applyAutoLock()`, `guardWeekLocked()` und `deleteWeek()` bereit. Genutzt wird // sie u.a. von `js/board.js` (`renderBoard`, `isWeekLocked`), `js/store.js` // (`load`) und `js/tabs-auth.js` (Passwort-Aktionen für Entsperren/Löschen). // refreshWeekSelect: aktualisiert das Dropdown `weekSelect` mit allen Sitzungen // der aktuellen Abteilung und markiert die aktuell ausgewählte. Kein Parameter, // keine Rückgabe. function refreshWeekSelect(){ const sel = document.getElementById('weekSelect'); sel.innerHTML = db.weeks.map(w=>``).join(''); } // updateWeekDate: zeigt das Datum der aktuellen Sitzung im Display // `weekDateDisplay` an (formatiert über `formatWeekDate()`). Kein Parameter, // keine Rückgabe; leer, wenn keine Woche gewählt ist. function updateWeekDate(){ const disp = document.getElementById('weekDateDisplay'); const w = currentWeek(); if(!disp) return; disp.textContent = w?.date ? `Datum: ${formatWeekDate(w.date)}` : ''; } // currentWeek: liefert das Woche-Objekt zur aktuellen Auswahl aus `db.weeks`. // Kein Parameter; Rückgabe: das gefundene Woche-Objekt oder undefined. function currentWeek(){ return db.weeks.find(w=>w.id===db.currentWeek); } // switchWeek: setzt die aktuell gewählte Wochen-ID (`id`), speichert und // rendert die Ansicht neu. Keine Rückgabe. function switchWeek(id){ db.currentWeek = id; save(); renderAll(); } // newWeek: erzeugt über zwei prompt-Dialoge eine neue leere Sitzung (Bezeichnung // und Datum). Die neue Woche übernimmt die globale Personenliste der Abteilung, // wird angehängt, per `applyAutoLock()` gesperrt und als aktuelle Woche gesetzt. // Keine Parameter, keine Rückgabe. function newWeek(){ const label = prompt("Bezeichnung der neuen Sitzung (z.B. KW 31 / 2026):","KW / 2026"); if(!label) return; const date = prompt("Datum (JJJJ-MM-TT):", new Date().toISOString().slice(0,10)) || ""; // Neue Woche übernimmt die aktuell globale Personenliste const people = JSON.parse(JSON.stringify(db.globalPeople[currentDepartment] || [])); const w = {id:uid(), label, date, people, projects:[], attendance:{}, locked:false}; db.weeks.push(w); applyAutoLock(); db.currentWeek=w.id; save(); renderAll(); } // cloneWeek: dupliziert die aktuelle Sitzung inkl. Projekten (Dialog für // Bezeichnung und Datum). Projekte erhalten neue IDs; Status-Markierungen // werden auf `statusState='duplicated'` gesetzt. Keine Parameter, keine Rückgabe. function cloneWeek(){ const cur = currentWeek(); if(!cur) return; const label = prompt("Bezeichnung der duplizierten Sitzung:", cur.label+" (Kopie)"); if(!label) return; const date = prompt("Datum (JJJJ-MM-TT):", new Date().toISOString().slice(0,10)) || ""; const w = JSON.parse(JSON.stringify(cur)); w.id=uid(); w.label=label; w.date=date; w.attendance={}; w.locked=false; // Neue IDs für duplizierte Projekte und Kennzeichnung w.projects.forEach(p=>{ p.id = uid(); if(p.status && p.status.trim() !== "") p.statusState = 'duplicated'; else delete p.statusState; }); db.weeks.push(w); applyAutoLock(); db.currentWeek=w.id; save(); renderAll(); } // -------- Sperren (Auto-Lock) und Entsperren -------- // applyAutoLock: sperrt alle Sitzungen bis auf die chronologisch // letzte (aktuellste). Wird beim Laden, Erstellen und Duplizieren verwendet, // damit historische Sitzungen nicht mehr unbeabsichtigt bearbeitet werden. function applyAutoLock(){ if(db.weeks.length === 0) return; const sorted = [...db.weeks].sort((a,b) => weekSortKey(a.label).localeCompare(weekSortKey(b.label))); const latestId = sorted[sorted.length - 1].id; db.weeks.forEach(w => { w.locked = (w.id !== latestId); }); } // isWeekLocked: prüft, ob eine Sitzung gesperrt ist. Parameter `w`: Woche-Objekt. // Rückgabe: `true` bei gesperrter bzw. fehlender Woche, sonst `false`. function isWeekLocked(w){ return !!w && !!w.locked; } // guardWeekLocked: zeigt eine Warnung, wenn die aktuelle Sitzung gesperrt ist. // Wird von Bearbeitungsfunktionen verwendet, um versehentliche Änderungen an // historischen Sitzungen zu verhindern. Rückgabe: `true` bei Sperre (Abbruch), // sonst `false`. function guardWeekLocked(){ const w = currentWeek(); if(isWeekLocked(w)){ alert('Diese Sitzung ist gesperrt. Bitte entsperren Sie sie zuerst.'); return true; } return false; } // unlockCurrentWeek: Entsperrt die aktuelle Sitzung nach Passwortprüfung. // Parameter `skipAuth=true` überspringt die Passwortabfrage (Aufruf nach // erfolgreicher Authentifizierung). Keine Rückgabe. function unlockCurrentWeek(skipAuth = false){ const w = currentWeek(); if(!w || !w.locked) return; if(!skipAuth && !isAuthenticated){ requestedAction = { type: 'unlockWeek' }; document.getElementById('passwordModal').style.display='flex'; document.getElementById('passwordInput').value=''; document.getElementById('passwordInput').focus(); return; } w.locked = false; save(); renderAll(); requestedAction = null; } // deleteWeek: löscht die aktuell ausgewählte Sitzung (nur wenn mehr als 1 // vorhanden) inkl. ihrer CSV-Datei auf dem Server. Parameter `skipAuth=true` // überspringt die Passwortabfrage. Danach wird die letzte verbleibende Woche // aktiviert und neu gerendert. Keine Rückgabe. function deleteWeek(skipAuth = false){ if(db.weeks.length<=1){ alert("Mindestens eine Sitzung muss bestehen bleiben."); return; } if(!skipAuth && !isAuthenticated){ requestedAction = { type: 'deleteWeek' }; document.getElementById('passwordModal').style.display='flex'; document.getElementById('passwordInput').value=''; document.getElementById('passwordInput').focus(); return; } if(!confirm("Diese Sitzung wirklich löschen?")) { requestedAction = null; return; } const current = currentWeek(); const filename = current ? filenameForWeek(current.label) : null; if(filename){ console.log('Lösche CSV-Datei auf Server:', filename); deleteCsvFromServer(filename).then(res=>{ if(res && res.ok){ console.log('CSV-Datei gelöscht:', filename); } else { alert('CSV-Löschung fehlgeschlagen: ' + (res && res.error ? res.error : 'unbekannter Fehler')); } }).catch(err=>{ alert('CSV-Löschung fehlgeschlagen: ' + (err.message || err)); }); } db.weeks = db.weeks.filter(w=>w.id!==db.currentWeek); db.weeks.sort((a,b) => weekSortKey(a.label).localeCompare(weekSortKey(b.label))); db.currentWeek = db.weeks[db.weeks.length - 1].id; applyAutoLock(); save(); renderAll(); requestedAction = null; }