Files
dogfather-universe/workspace/assets/js/start.js
T
DogFatherGit 072ded20a2 Workspace: Reports & Review -- Phase 2 vollstaendig
/workspace/report.html. Fuehrt bewusst KEINE eigenen Eintraege, sondern
fasst zusammen, was in Aufgaben, Bereichen, Terminen und Dateien schon
steht: "Fortschritt wird nicht gefuehlt, sondern nachvollziehbar
gemacht".

Die vier Abschnitte sind woertlich die Fragen aus dem Deck, Seite 16:
Was wurde erledigt? Was blockiert? Was hat funktioniert? Was kommt als
Naechstes?

Zwei Punkte daraus sind ernst genommen:

1. "Vorher / nachher" (Historie). Jede Zahl wird mit demselben,
   unmittelbar davorliegenden Zeitraum verglichen. Eine Zahl allein sagt
   wenig -- 3 erledigte Aufgaben sind gut oder schlecht, je nachdem ob es
   vorher 1 oder 9 waren. Bei Zahlen, wo mehr SCHLECHTER ist (offene
   Probleme), ist die Trendfarbe umgedreht.

2. "Jeder Review endet mit einer Entscheidung, nicht nur mit einer
   Zusammenfassung." Der Report legt deshalb direkt eine Aufgabe an --
   ohne Seitenwechsel, mit hoher Prioritaet und optionaler Frist.
   Geprueft: Eintrag im Report -> Aufgabe erscheint im Brett.

"Was blockiert?" zeigt zusaetzlich die drei am laengsten offenen
Aufgaben mit Namen, nicht nur eine Zahl.

Sichtbarkeit:
- Scout: 404, sowohl Schnittstelle als auch Seite (leitet weg)
- Creator: sieht nur sich. Geprueft -- Luna fordert ?creator=3 (Mika) an
  und bekommt einen Report ueber SICH, der Parameter wird fuer
  Nicht-Management ignoriert
- Der Review-Termin aus dem Profil ist Steuerungswissen und wird einem
  Creator auch hier nicht mitgeschickt, genau wie im Profil selbst

Damit ist Phase 2 aus dem Konzept vollstaendig.
2026-08-28 09:48:03 +02:00

129 lines
5.0 KiB
JavaScript

/* ===================================================================
Startseite nach dem Anmelden.
Die Seite ist bereits serverseitig geschützt (workspace.js). Dieses
Skript holt nur noch, WER angemeldet ist, und regelt das Abmelden.
=================================================================== */
(() => {
'use strict';
const ROLLENTEXT = {
admin: 'Management · Gesamtübersicht und Freigaben',
creator: 'Creator · dein eigener Bereich',
scout: 'Scout · deine Pipeline und Kontakte',
};
/* Bereiche aus dem Konzept, mit der Phase aus dem Umsetzungsplan.
`rollen` steuert, wem ein Bereich überhaupt angezeigt wird - schon
jetzt, damit die Trennung von Anfang an sichtbar ist. */
const BEREICHE = [
{ name: 'Dashboard', phase: 1, rollen: ['admin', 'creator', 'scout'] },
{ name: 'Personen & Zugänge', phase: 1, rollen: ['admin'], ziel: 'personen.html' },
{ name: 'Creator-Profile', phase: 1, rollen: ['admin'], ziel: 'profil.html' },
{ name: 'Mein Profil', phase: 1, rollen: ['creator'], ziel: 'profil.html' },
{ name: 'Aufgaben', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'aufgaben.html' },
{ name: 'Kalender', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'kalender.html' },
{ name: 'Dateien', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'dateien.html' },
{ name: 'LIVE-Analyse', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=live' },
{ name: 'Content-Planung', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=content' },
{ name: 'Technik', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=technik' },
{ name: 'Community', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=community' },
{ name: 'Schutz & Regeln', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=schutz' },
{ name: 'Reports & Review', phase: 2, rollen: ['admin', 'creator'], ziel: 'report.html' },
{ name: 'Calls', phase: 3, rollen: ['admin', 'creator', 'scout'] },
{ name: 'Scout-Pipeline', phase: 3, rollen: ['admin', 'scout'] },
{ name: 'Automationen', phase: 4, rollen: ['admin'] },
];
const $ = (id) => document.getElementById(id);
async function laden() {
let ich;
try {
const antwort = await fetch('/workspace/api/ich', { credentials: 'same-origin' });
if (!antwort.ok) { location.assign('/workspace/'); return; }
ich = await antwort.json();
} catch {
location.assign('/workspace/');
return;
}
$('wer').textContent = `${ich.name} · ${ich.rolle}`;
$('gruss').textContent = `Willkommen, ${ich.name}`;
$('rollentext').textContent = ROLLENTEXT[ich.rolle] || ich.rolle;
const liste = $('bereiche');
for (const b of BEREICHE.filter((b) => b.rollen.includes(ich.rolle))) {
const li = document.createElement('li');
li.className = 'bereich';
li.dataset.phase = String(b.phase);
if (b.ziel) li.dataset.fertig = 'ja';
const name = document.createElement('span');
name.className = 'bereich__name';
name.textContent = b.name;
const stand = document.createElement('span');
stand.className = 'bereich__stand';
stand.textContent = b.ziel ? 'öffnen' : (b.phase === 1 ? 'als Nächstes' : `Phase ${b.phase}`);
if (b.ziel) {
/* Fertige Bereiche sind echte Verweise -- Tastatur und
Rechtsklick funktionieren damit wie gewohnt. */
const a = document.createElement('a');
a.className = 'bereich__link';
a.href = b.ziel;
a.append(name, stand);
li.append(a);
} else {
li.append(name, stand);
}
liste.append(li);
}
await zahlenLaden();
}
/* Die Zahlen kommen aus derselben Quelle wie das Brett und sind bereits
serverseitig auf die eigene Rolle eingegrenzt. */
const ZAHLEN = [
{ schluessel: 'ueberfaellig', name: 'Überfällig', warn: true },
{ schluessel: 'heute', name: 'Heute fällig' },
{ schluessel: 'offen', name: 'Offen' },
{ schluessel: 'arbeit', name: 'In Arbeit' },
{ schluessel: 'review', name: 'Review' },
{ schluessel: 'erledigt', name: 'Erledigt' },
];
async function zahlenLaden() {
let daten;
try {
const antwort = await fetch('/workspace/api/uebersicht', { credentials: 'same-origin' });
if (!antwort.ok) return;
daten = await antwort.json();
} catch { return; }
const liste = $('zahlen');
liste.textContent = '';
for (const z of ZAHLEN) {
const wert = daten[z.schluessel] ?? 0;
const li = document.createElement('li');
li.className = 'zahl';
if (z.warn && wert > 0) li.dataset.warn = 'ja';
const n = document.createElement('span');
n.className = 'zahl__wert';
n.textContent = String(wert);
const t = document.createElement('span');
t.className = 'zahl__name';
t.textContent = z.name;
li.append(n, t);
liste.append(li);
}
}
laden();
})();