Filipe, mit dem Bildschirmfoto des Start-Checks auf crew.: "das gibt
es in der app nicht, dass ist nur auf der workspace app aber nicht
hier."
ES WAR GROESSER ALS DIESE EINE SEITE. Gemessen, bevor gebaut:
DogFather 12 Seiten ohne Kachel erreichbar, 10 davon Agentur
(Automationen, Content, Scouting, Reports, Zahlen,
Team, Calls, Creator-Profil, Dashboard, Start-Check)
rechte Hand 5, davon 3 Agentur
ein Modi 6, davon 3 Agentur -- auch der Start-Check
Die Haustrennung vom 10.09. entscheidet, WAS jemand sieht: sie filtert
Daten und Kacheln. Sie entschied nie, welche SEITEN es auf einer
Adresse gibt. Die Rechtetafel wiederum kennt nur Rollen, keine
Adressen. Zwischen beidem lag das Loch -- und der Start-Check sagte
dort "Es gibt noch keinen Creator", weil ihm die Haustrennung alle
Daten wegnimmt. Eine Seite, die laedt und leer ist, sieht aus wie ein
Fehler.
DIE REGEL WIRD ABGELEITET, NICHT GEPFLEGT: Welche Seiten zu dieser
Adresse gehoeren, steht schon in den KACHELN, die dieselbe Adresse
dieser Person zeigt. Dazu drei Seiten, die in jedem Haus dazugehoeren
und keine Kachel haben (start, treff-regeln, entwicklung). Sie altert
sicher -- eine neue Agenturseite ist dort automatisch zu, eine neue
Crew-Seite ohne Kachel faellt beim ersten Klick auf.
UND SIE AENDERT KEINE RECHTE. Was jemand DARF, steht weiter allein in
rechte.js; diese Regel beantwortet, ob es das hier ueberhaupt gibt.
Nur die Seiten, nicht die Schnittstellen -- die filtern seit dem 10.09.
selbst ueber person.haus.
DREI PRUEFUNGEN, DIE VORHER SCHON ROT WAREN, nachgemessen gegen den
Stand von heute frueh (2712473), damit ich sie nicht mir selbst
zuschreibe -- und zwei davon repariert:
pruef-treff Sie fragte "enthaelt die Antwort irgendein
gefuelltes Feld" und wurde rot, als das
Aufgabenbrett die drei Aufwandsstufen mitzuliefern
begann. Die sagen ueber niemanden etwas. Eine
Warnung, die immer kommt, wird ueberlesen -- also
praeziser statt lauter: Ein Datensatz hat eine id,
ein Vokabular einen schluessel und keine.
pruef-neue-seiten War gruen und wurde durch MEINE Arbeit rot: Mit
dem Umzug der sechs Fragen blieben bei 390 px noch
14 Textstuecke statt der geforderten 15 -- alle
lesbar. Die Zahl auf 14 zu setzen waere derselbe
Fehler mit einer anderen Zahl gewesen; die Aufgabe
("die Seite hat wirklich gerendert") erledigt zwei
Zeilen hoeher schon die Zeichenzahl.
pruef-kachel-universum, pruef-struktur, pruef-modi-wortleck
unveraendert rot, nicht von hier -- offen.
Ausserdem: "wenn alle 1 sie gesetzt haben" auf der eigenen Karte. Das
ist keine Auskunft, sondern eine Rechnung -- derselbe Fall wie "vor 0
Tagen" heute frueh. Zwei Lagen, zwei Saetze.
server/pruef-haus-seiten.mjs 24 Pruefungen, 0 Fehler (Port 4422)
pruef-crew-adresse 132, pruef-modi-verborgen 80, pruef-haus-trennung 66,
pruef-treff 66, pruef-treff-werkzeuge 70, pruef-neue-seiten 93,
pruef-befinden 48, pruef-schritt 46 -- alle 0 Fehler
Co-Authored-By: Claude Opus 5 <[email protected]>
445 lines
18 KiB
JavaScript
445 lines
18 KiB
JavaScript
/* =====================================================================
|
||
Die Entwicklungskarte (11.09.2026)
|
||
|
||
Vier Knöpfe je Beobachtung, ein Feld für den Anlass, und oben die
|
||
Abweichungen zwischen zwei Augenpaaren. Mehr ist es nicht — und das
|
||
ist Absicht: „so einfach wie möglich, aber so professionell wie
|
||
möglich" (Filipe).
|
||
|
||
WAS HIER NICHT PASSIERT: rechnen. Es gibt keine Punktzahl, keinen
|
||
Durchschnitt, keine Ampel je Person. Eine Zahl über einem Menschen
|
||
wird gelesen, verglichen und weitererzählt — gebraucht wird ein
|
||
Gesprächsanlass.
|
||
|
||
UND KEINE RECHTEPRÜFUNG. Ob jemand Block 5 sehen darf, entscheidet
|
||
der Server: Er liefert ihn gar nicht erst aus. Was hier steht, ist
|
||
höchstens ein Abschnitt, der leer bleibt.
|
||
===================================================================== */
|
||
(() => {
|
||
const $ = (id) => document.getElementById(id);
|
||
const el = (t, k, text) => {
|
||
const n = document.createElement(t);
|
||
if (k) n.className = k;
|
||
if (text !== undefined) n.textContent = text;
|
||
return n;
|
||
};
|
||
const melde = (t) => { const f = $('fehler'); if (f) { f.textContent = t; f.hidden = !t; } };
|
||
|
||
const datum = (iso) => {
|
||
if (!iso) return '';
|
||
const d = new Date(iso);
|
||
return Number.isNaN(d.getTime()) ? '' : d.toLocaleDateString('de-DE',
|
||
{ day: 'numeric', month: 'short', year: 'numeric' });
|
||
};
|
||
|
||
async function hole(pfad, optionen = {}) {
|
||
const a = await fetch(pfad, { credentials: 'same-origin', ...optionen });
|
||
if (a.status === 401) { location.assign('/workspace/'); throw new Error('abgemeldet'); }
|
||
if (a.status === 404) { location.assign('/workspace/start.html'); throw new Error('unbekannt'); }
|
||
return a;
|
||
}
|
||
|
||
let stufen = [];
|
||
let offen = null; // die gerade geöffnete Person
|
||
|
||
/* ---- Die vier Knöpfe ------------------------------------------------
|
||
Sie stehen immer in derselben Reihenfolge, auch wenn einer gesetzt
|
||
ist. Ein Knopfsatz, der sich umsortiert, sobald man ihn benutzt,
|
||
ist der sicherste Weg, beim zweiten Mal danebenzutippen. */
|
||
function knopfsatz(aktuell, waehle) {
|
||
const reihe = el('div', 'e-wahl');
|
||
for (const s of stufen) {
|
||
const b = el('button', 'e-wahl__knopf');
|
||
b.type = 'button';
|
||
b.dataset.stufe = s.schluessel;
|
||
b.setAttribute('aria-pressed', String(aktuell === s.schluessel));
|
||
b.title = s.text;
|
||
b.append(el('span', 'e-wahl__zeichen', s.zeichen));
|
||
b.append(el('span', 'e-wahl__name', s.name));
|
||
b.addEventListener('click', () => waehle(s.schluessel, b));
|
||
reihe.append(b);
|
||
}
|
||
return reihe;
|
||
}
|
||
|
||
/* ---- Die Ampel ------------------------------------------------------ */
|
||
async function ampel() {
|
||
const ziel = $('ampel');
|
||
let a;
|
||
try { a = await hole('/workspace/api/entwicklung/ampel'); } catch { return; }
|
||
if (!a.ok) return; // für einen Modi gibt es sie nicht
|
||
const r = await a.json();
|
||
ziel.textContent = '';
|
||
ziel.hidden = false;
|
||
ziel.dataset.lage = r.sagbar ? r.lage : 'still';
|
||
ziel.append(el('p', 'e-ampel__satz', r.sagbar ? r.text : r.grund));
|
||
if (r.sagbar) {
|
||
ziel.append(el('p', 'e-ampel__zusatz',
|
||
`${r.geantwortet} von ${r.team} im Team haben die sechs Fragen schon beantwortet. `
|
||
+ 'Namen stehen hier nicht – auch für dich nicht.'));
|
||
}
|
||
}
|
||
|
||
/* ---- Die Personen --------------------------------------------------- */
|
||
function personKarte(p, lage) {
|
||
const k = el('button', 'e-person');
|
||
k.type = 'button';
|
||
k.append(el('span', 'e-person__name', p.name));
|
||
k.append(el('span', 'e-person__rolle', p.rolle_name));
|
||
|
||
const zahlen = el('span', 'e-person__zahlen');
|
||
zahlen.append(el('span', 'e-person__zahl',
|
||
`${p.gesetzt} von ${lage.gesamt_fremd} angesehen`));
|
||
/* DIE ABWEICHUNG STEHT VORNE UND NICHT IM DETAIL. Sie ist das
|
||
Ergebnis dieser Seite: Wo zwei Leute dasselbe sehen, gibt es
|
||
nichts zu besprechen. */
|
||
if (p.abweichungen) {
|
||
const z = el('span', 'e-person__zahl e-person__zahl--wichtig',
|
||
`${p.abweichungen} × verschieden gesehen`);
|
||
z.title = 'Hier lohnt das Gespräch – nicht dort, wo ihr einig seid.';
|
||
zahlen.append(z);
|
||
}
|
||
if (p.veraltet) {
|
||
const z = el('span', 'e-person__zahl e-person__zahl--alt',
|
||
`${p.veraltet} älter als ${lage.verblasst_nach} Tage`);
|
||
z.title = 'Eine alte Einschätzung ist keine Einschätzung mehr.';
|
||
zahlen.append(z);
|
||
}
|
||
k.append(zahlen);
|
||
k.addEventListener('click', () => karte(p.id));
|
||
return k;
|
||
}
|
||
|
||
/* ---- Die Karte einer Person ----------------------------------------- */
|
||
async function karte(id) {
|
||
offen = id;
|
||
const ziel = $('karte');
|
||
ziel.hidden = false;
|
||
ziel.textContent = '';
|
||
ziel.append(el('p', 'leise', 'wird geladen …'));
|
||
ziel.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
|
||
const a = await hole(`/workspace/api/entwicklung/person/${id}`);
|
||
if (!a.ok) { melde('Die Karte ließ sich nicht laden.'); return; }
|
||
const r = await a.json();
|
||
stufen = r.stufen;
|
||
ziel.textContent = '';
|
||
|
||
const kopf = el('div', 'e-karte__kopf');
|
||
kopf.append(el('h2', 'e-karte__name', r.person.name));
|
||
kopf.append(el('span', 'e-karte__rolle', r.person.rolle_name));
|
||
kopf.append(el('span', 'e-karte__stand', `${r.gesetzt} von ${r.gesamt} angesehen`));
|
||
/* Der Weg zum Notizbrett. Der Katalog ist das, was man regelmäßig
|
||
durchgeht; die Notiz das, was zwischendurch auffällt. Beides
|
||
nebeneinander, nicht statt. */
|
||
const brett = el('a', 'schritt e-karte__brett', 'Notizen zu dieser Person');
|
||
brett.href = 'bereich.html?b=entwicklung';
|
||
kopf.append(brett);
|
||
ziel.append(kopf);
|
||
|
||
/* ---- Abweichungen zuerst ------------------------------------------
|
||
Sie stehen oben, weil sie das Einzige sind, was diese Seite
|
||
liefert und eine Liste nicht: die Stelle, an der zwei Leute
|
||
dieselbe Person verschieden sehen. */
|
||
if (r.abweichungen.length) {
|
||
const box = el('div', 'e-abweichung');
|
||
box.append(el('h3', 'e-abweichung__titel',
|
||
`${r.abweichungen.length} × seht ihr das verschieden`));
|
||
box.append(el('p', 'e-abweichung__satz',
|
||
'Genau hier lohnt das Gespräch. Wo ihr einig seid, gibt es nichts zu besprechen.'));
|
||
const liste = el('ul', 'e-abweichung__liste');
|
||
for (const ab of r.abweichungen) {
|
||
const li = document.createElement('li');
|
||
li.append(el('span', 'e-abweichung__punkt', ab.titel));
|
||
const nn = (s) => stufen.find((x) => x.schluessel === s)?.name || s;
|
||
li.append(el('span', 'e-abweichung__gegen',
|
||
`du: ${nn(ab.meins)} · ${ab.von_name}: ${nn(ab.andere)}`));
|
||
liste.append(li);
|
||
}
|
||
box.append(liste);
|
||
ziel.append(box);
|
||
}
|
||
|
||
/* ---- Die Blöcke ---------------------------------------------------- */
|
||
for (const b of r.bloecke) {
|
||
const abschnitt = el('section', 'e-block');
|
||
abschnitt.append(el('h3', 'e-block__titel', b.name));
|
||
abschnitt.append(el('p', 'e-block__satz', b.text));
|
||
for (const pt of b.punkte) abschnitt.append(punktZeile(id, pt, r.erwartung));
|
||
ziel.append(abschnitt);
|
||
}
|
||
}
|
||
|
||
function punktZeile(personId, pt, erwartung) {
|
||
const z = el('article', 'e-punkt');
|
||
if (pt.meins) z.dataset.stufe = pt.meins.stufe;
|
||
if (pt.meins?.verblasst) z.dataset.verblasst = 'ja';
|
||
|
||
const kopf = el('div', 'e-punkt__kopf');
|
||
kopf.append(el('h4', 'e-punkt__titel', pt.titel));
|
||
const erw = erwartung.find((e) => e.schluessel === pt.stufe);
|
||
if (erw) {
|
||
const m = el('span', 'e-punkt__erwartung', erw.name);
|
||
m.dataset.erwartung = pt.stufe;
|
||
m.title = erw.text;
|
||
kopf.append(m);
|
||
}
|
||
z.append(kopf);
|
||
z.append(el('p', 'e-punkt__text', pt.text));
|
||
|
||
/* Das Anlassfeld. Es steht IMMER da, nicht erst nach dem Klick:
|
||
Ein Feld, das aufklappt, kostet einen zweiten Blick, und genau
|
||
an der Stelle hört man auf zu schreiben. */
|
||
const feld = el('textarea', 'e-punkt__anlass');
|
||
feld.rows = 2;
|
||
feld.value = pt.meins?.anlass || '';
|
||
feld.placeholder = 'Woran hast du das gemerkt? (bei „Da hakt es" nötig)';
|
||
|
||
z.append(knopfsatz(pt.meins?.stufe || null, async (stufe, knopf) => {
|
||
const reihe = knopf.parentElement;
|
||
for (const b of reihe.querySelectorAll('.e-wahl__knopf')) {
|
||
b.setAttribute('aria-pressed', String(b === knopf));
|
||
}
|
||
z.dataset.stufe = stufe;
|
||
const a = await hole(`/workspace/api/entwicklung/person/${personId}/${pt.schluessel}`, {
|
||
method: 'PUT',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ stufe, anlass: feld.value }),
|
||
});
|
||
if (!a.ok) {
|
||
const j = await a.json().catch(() => ({}));
|
||
melde(j.fehler || 'Ging nicht.');
|
||
feld.focus();
|
||
return;
|
||
}
|
||
melde('');
|
||
/* Neu laden, sobald der erste Klick auf einem Punkt sitzt: Erst
|
||
danach darf der Stand des anderen überhaupt ausgeliefert
|
||
werden, und dann soll er auch sichtbar werden. */
|
||
if (!pt.meins) await karte(personId);
|
||
}));
|
||
|
||
z.append(feld);
|
||
|
||
if (pt.andere?.length) {
|
||
for (const a of pt.andere) {
|
||
const nn = stufen.find((x) => x.schluessel === a.stufe);
|
||
const zeile = el('p', 'e-punkt__andere',
|
||
`${a.von_name}: ${nn?.name || a.stufe}${a.anlass ? ' – ' + a.anlass : ''}`);
|
||
zeile.dataset.stufe = a.stufe;
|
||
z.append(zeile);
|
||
}
|
||
} else if (pt.andere_offen) {
|
||
/* WARUM DA ETWAS STEHT UND NICHT NICHTS: „Noch niemand" und „du
|
||
darfst es noch nicht sehen" sähen sonst gleich aus — und das
|
||
erste ist eine Auskunft, das zweite eine Täuschung. */
|
||
z.append(el('p', 'e-punkt__verdeckt',
|
||
`${pt.andere_offen} andere Einschätzung liegt vor – sichtbar, sobald du selbst gesetzt hast.`));
|
||
}
|
||
|
||
if (pt.meins) {
|
||
z.append(el('p', 'e-punkt__wann',
|
||
`von dir am ${datum(pt.meins.am)}${pt.meins.verblasst ? ' – älter als 90 Tage' : ''}`));
|
||
}
|
||
|
||
/* ==== AUS DER BEOBACHTUNG WIRD EIN SCHRITT (15.09.2026) ==========
|
||
|
||
Bis heute konnte diese Zeile genau eines: festhalten, dass etwas
|
||
hakt. Danach passierte nichts — beim nächsten Öffnen stand
|
||
dieselbe Beobachtung da, nur älter.
|
||
|
||
Ein Entwicklungsplan wirkt dann, wenn er an einer ECHTEN Aufgabe
|
||
hängt. Also wird aus „da hakt es" eine Aufgabe auf dem Brett,
|
||
mit Verantwortlichem und Frist — und wenn sie erledigt ist,
|
||
fragt die Karte dieselbe Frage noch einmal. Das ist der Kreis.
|
||
============================================================== */
|
||
z.append(schrittZeile(personId, pt));
|
||
return z;
|
||
}
|
||
|
||
const SCHRITT_ABSAGE = {
|
||
kein_hakt: 'Ein Schritt entsteht aus „Da hakt es“ – setz das zuerst.',
|
||
schon_da: 'Dazu läuft schon ein Schritt.',
|
||
};
|
||
|
||
function schrittZeile(personId, pt) {
|
||
const s = pt.schritt;
|
||
const zeile = el('div', 'e-schritt');
|
||
|
||
/* ---- Es läuft schon etwas ---- */
|
||
if (s && s.status !== 'erledigt' && s.status !== 'abgebrochen') {
|
||
zeile.dataset.lage = 'laeuft';
|
||
zeile.append(el('span', 'e-schritt__was', 'Schritt läuft'));
|
||
const a = el('a', 'e-schritt__hin', s.titel);
|
||
/* DIE SCHREIBWEISE DES HAUSES: `#a<nummer>`. Das Brett springt
|
||
damit wirklich zu der Aufgabe -- `?a=` hatte ich erfunden, und
|
||
das Brett liest es nicht. Ein Verweis, der nur die Seite
|
||
oeffnet und nichts zeigt, ist schlechter als keiner. */
|
||
a.href = 'aufgaben.html#a' + s.id;
|
||
zeile.append(a);
|
||
if (s.frist) zeile.append(el('span', 'e-schritt__frist', `bis ${datum(s.frist)}`));
|
||
return zeile;
|
||
}
|
||
|
||
/* ---- Er ist durch: dieselbe Frage noch einmal ----
|
||
DAS IST DER EIGENTLICHE GEWINN. Ohne diesen Satz wäre der Schritt
|
||
nur eine Aufgabe mehr; mit ihm wird aus der Beobachtung eine
|
||
Runde, die zu Ende geht. */
|
||
if (s && s.status === 'erledigt') {
|
||
zeile.dataset.lage = 'durch';
|
||
zeile.append(el('span', 'e-schritt__was', 'Schritt erledigt'));
|
||
zeile.append(el('span', 'e-schritt__satz',
|
||
s.erledigt_am
|
||
? `am ${datum(s.erledigt_am)} – sieh noch einmal hin und setz neu.`
|
||
: 'Sieh noch einmal hin und setz neu.'));
|
||
return zeile;
|
||
}
|
||
|
||
/* ---- Noch keiner: aber nur aus einem „da hakt es" ----
|
||
Der Knopf steht NUR dort. Ein Knopf, der überall steht und fast
|
||
überall „geht nicht" antwortet, ist schlechter als keiner. */
|
||
if (pt.meins?.stufe !== 'hakt') return zeile;
|
||
|
||
zeile.dataset.lage = 'offen';
|
||
const b = el('button', 'schritt e-schritt__knopf', 'Daraus einen Schritt machen');
|
||
b.type = 'button';
|
||
b.title = 'Legt eine Aufgabe auf dem Brett an – mit dieser Person als '
|
||
+ 'Verantwortlicher und einer Frist in zwei Wochen.';
|
||
b.addEventListener('click', async () => {
|
||
b.disabled = true;
|
||
const a = await hole(
|
||
`/workspace/api/entwicklung/person/${personId}/${pt.schluessel}/schritt`,
|
||
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' });
|
||
b.disabled = false;
|
||
if (!a.ok) {
|
||
const j = await a.json().catch(() => ({}));
|
||
melde(SCHRITT_ABSAGE[j.fehler] || 'Ging nicht.');
|
||
return;
|
||
}
|
||
const neu = await a.json();
|
||
melde(`Steht auf dem Aufgabenbrett: „${neu.titel}“, bis ${datum(neu.frist)}.`);
|
||
await karte(personId);
|
||
});
|
||
zeile.append(b);
|
||
return zeile;
|
||
}
|
||
|
||
/* ---- Deine eigene Karte -----------------------------------------------
|
||
|
||
WAS HIER STEHT UND WAS NICHT: die Antworten, nicht die Namen, und
|
||
nicht der Anlass. „2 × Läuft" oder „1 × Läuft, 1 × Wächst gerade".
|
||
|
||
Der Anlass ist für ein Gespräch aufgeschrieben, nicht zum Lesen
|
||
ohne den Menschen dazu — deshalb steht hier stattdessen der Satz,
|
||
dass man danach fragen soll. Ein Satz aus einer Notiz, aus dem
|
||
Zusammenhang gerissen, richtet mehr an, als er erklärt. */
|
||
async function meineKarte() {
|
||
let a;
|
||
try { a = await hole('/workspace/api/entwicklung/meine-karte'); } catch { return; }
|
||
if (!a.ok) return;
|
||
const r = await a.json();
|
||
if (!r.hat_karte) return; // DogFather hat keine
|
||
|
||
$('karte-block').hidden = false;
|
||
const satz = $('karte-satz');
|
||
const ziel = $('meine-karte');
|
||
ziel.textContent = '';
|
||
ziel.setAttribute('aria-busy', 'false');
|
||
|
||
if (!r.beurteiler) {
|
||
satz.textContent = 'Es gibt gerade niemanden, der sie führt. Sobald jemand '
|
||
+ 'da ist, steht hier etwas.';
|
||
return;
|
||
}
|
||
if (!r.fertig) {
|
||
/* EINE ZAHL IN EINEM SATZ MUSS SICH VORLESEN LASSEN. „wenn alle 1
|
||
sie gesetzt haben" ist keine Auskunft, sondern eine Rechnung --
|
||
und wer einen Satz liest, der falsch klingt, glaubt auch dem
|
||
Rest der Seite weniger. Derselbe Fall wie bei der Ampel und
|
||
beim Takt auf befinden.html. */
|
||
satz.textContent = r.beurteiler === 1
|
||
? 'Noch nichts fertig. Eine Beobachtung erscheint hier, sobald sie gesetzt ist '
|
||
+ '– eine halbe Karte wäre schlimmer als keine.'
|
||
: `Noch nichts fertig. Eine Beobachtung erscheint hier erst, `
|
||
+ `wenn alle ${r.beurteiler} sie gesetzt haben – eine halbe Karte ist `
|
||
+ `schlimmer als keine.`;
|
||
return;
|
||
}
|
||
|
||
satz.textContent = `${r.fertig} von ${r.gesamt} Beobachtungen sind durch. `
|
||
+ 'Du siehst die Antworten, nicht wer was gesetzt hat – und nicht, was '
|
||
+ 'danebengeschrieben steht. Das gehört ins Gespräch: frag danach.';
|
||
|
||
for (const b of r.bloecke) {
|
||
const fertige = b.punkte.filter((pt) => !pt.offen);
|
||
if (!fertige.length) continue;
|
||
const abschnitt = el('section', 'e-block');
|
||
abschnitt.append(el('h3', 'e-block__titel', b.name));
|
||
for (const pt of fertige) {
|
||
const zeile = el('article', 'e-punkt e-punkt--meine');
|
||
if (pt.einig) zeile.dataset.stufe = pt.antworten[0].stufe;
|
||
zeile.append(el('h4', 'e-punkt__titel', pt.titel));
|
||
const antw = el('div', 'e-meine__antworten');
|
||
for (const x of pt.antworten) {
|
||
const chip = el('span', 'e-meine__antwort', `${x.anzahl} × ${x.name}`);
|
||
chip.dataset.stufe = x.stufe;
|
||
antw.append(chip);
|
||
}
|
||
if (!pt.einig) {
|
||
const hin = el('span', 'e-meine__uneinig', 'darüber seid ihr euch nicht einig');
|
||
hin.title = 'Zwei Leute haben dasselbe verschieden gesehen. Das ist normal – '
|
||
+ 'und ein guter Anlass, danach zu fragen.';
|
||
antw.append(hin);
|
||
}
|
||
zeile.append(antw);
|
||
abschnitt.append(zeile);
|
||
}
|
||
ziel.append(abschnitt);
|
||
}
|
||
}
|
||
|
||
/* ---- Start ------------------------------------------------------------ */
|
||
(async () => {
|
||
try {
|
||
const a = await hole('/workspace/api/entwicklung/lage');
|
||
if (!a.ok) { melde('Ging nicht.'); return; }
|
||
const lage = await a.json();
|
||
stufen = lage.stufen;
|
||
|
||
if (lage.leitung) {
|
||
$('personen-block').hidden = false;
|
||
const ziel = $('personen');
|
||
ziel.textContent = '';
|
||
ziel.setAttribute('aria-busy', 'false');
|
||
if (!lage.personen.length) {
|
||
ziel.append(el('p', 'leise',
|
||
'Noch niemand im Team. Zugänge legst du in „Personen & Zugänge" an.'));
|
||
}
|
||
for (const p of lage.personen) ziel.append(personKarte(p, lage));
|
||
await ampel();
|
||
} else {
|
||
/* Für einen Modi ist DIESE Seite seine eigene Karte — das,
|
||
was die Leitung über ihn notiert hat, und was er selbst
|
||
dazu sagt. Nicht „Entwicklung" als Überschrift: Das liest
|
||
sich wie eine Beurteilung, und darum geht es hier nicht.
|
||
|
||
Bis zum 15.09.2026 stand hier „Wie geht's dir?" — damals
|
||
bestand die Seite für ihn aus den sechs Fragen. Die haben
|
||
jetzt ihre eigene Seite, also stimmte der Titel nicht mehr.
|
||
Ein Titel, der etwas anderes verspricht als die Seite zeigt,
|
||
ist derselbe Fehler wie der an der Kachel. */
|
||
$('titel').textContent = 'Deine Entwicklung';
|
||
$('unterzeile').textContent =
|
||
'Was im Team über deine Arbeit notiert ist – und was du selbst dazu sagst. '
|
||
+ 'Keine Noten, keine Punktzahl.';
|
||
}
|
||
|
||
await meineKarte();
|
||
/* Die sechs Fragen stehen seit dem 15.09.2026 auf einer eigenen
|
||
Seite. Hier bleibt nur der Verweis -- er wird fuer alle
|
||
gezeigt, die dort ueberhaupt etwas zu beantworten haben. */
|
||
if ($('meins-block')) $('meins-block').hidden = false;
|
||
} catch { /* umgeleitet */ }
|
||
})();
|
||
})();
|