Files
projektuebersicht/public/js/weeks.js
T

156 lines
6.8 KiB
JavaScript

// -----------------------------
// 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/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=>`<option value="${w.id}" ${w.id===db.currentWeek?'selected':''}>${w.label}</option>`).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) 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();
if(current){
const label = current.label;
console.log('Lösche Woche auf Server:', label);
deleteWeekFromServer(label).then(res=>{
if(res && res.ok){ console.log('Woche gelöscht:', label); }
else { alert('Wochen-Löschung fehlgeschlagen: ' + (res && res.error ? res.error : 'unbekannter Fehler')); }
}).catch(err=>{ alert('Wochen-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;
}