Tagesblick: Termine als Karten, und vier Fehler, die dabei auffielen

Filipe zu der Liste mit einem einzigen Termin darin: "das soll viel
geiler und krasser aussehen bitte."

Er hatte recht, und der Grund war der Einzelfall. Ein Zeitstrahl lebt
davon, dass er etwas VERBINDET -- bei einem Eintrag verbindet er nichts.
Uebrig blieben eine magere Zeile, ein Strich ins Leere und Weissraum bis
zur Plakette am rechten Rand.

Jetzt traegt jede Karte fuer sich: eigene Flaeche mit farbiger Kante,
die Uhrzeit gross und in der Farbe der Terminart (vorher war sie
kleiner als der Titel -- dabei ist sie das, was man sucht), ein Balken
fuer die Dauer, und "JETZT" am naechsten Termin statt eines etwas
helleren Hintergrunds. Erledigtes bekommt einen Haken und verliert die
Farbe, bleibt aber voll lesbar; vorher wurde alles blasser, was auch
den Text traf.

Kein Neon dazu. Die Wirkung kommt aus Kontrast und Hierarchie.

VIER FEHLER, DIE DIE PRUEFUNGEN GEFUNDEN HABEN

1. ZEITZONE, in NEUN Pruefungen. Um 00:10 meldete pruef-teilnehmer
   ploetzlich 13 Fehlschlaege an einer Datei, die seit Stunden niemand
   angefasst hatte:

       Ortszeit:  06.09.2026, 00:10
       UTC:       05.09.2026, 22:10

   Sie bildeten ihr Tagesdatum mit toISOString() -- also UTC -- legten
   ihre Termine auf gestern und suchten heute. ZWEI STUNDEN AM TAG waren
   sie damit rot, im Winter eine. Wer nur tagsueber laeuft, sieht das
   nie. Jetzt gibt es helfer-zeit.mjs mit derselben Rechenweise wie die
   Anwendung, und pruef-struktur sucht das Muster kuenftig automatisch.

2. MEIN UMSTELL-SKRIPT VERSAGTE STILL. Es pruefte
   `if "helfer-zeit.mjs" not in s` -- und mein eigener Kommentar
   enthielt den Dateinamen. Ergebnis: keine einzige der neun Dateien
   bekam den Import, alle waeren zur Laufzeit abgestuerzt. `node --check`
   findet das nicht. Aufgefallen, weil danach nachgezaehlt wurde statt
   der Erfolgsmeldung zu glauben.

3. DIE KACHEL LIESS DIE SEITE SPRINGEN. Der Layout-Sprung auf
   start.html stieg von 0 auf 0,96 -- zweimal bestaetigt. Sie erschien
   erst nach dem Laden und schob alles darunter weg. Das ist kein
   Schoenheitsfehler, sondern der Grund, warum man auf den falschen
   Knopf drueckt.

   Gemessen wurden die echten Hoehen (1 Termin 169 px, 3 → 327, 5 →
   486). Daraus zwei Konsequenzen: Platz vorher reservieren, und
   hoechstens DREI Termine zeigen -- das halbiert die Spanne und ist
   die klarere Aussage. Der Rest steht als "1 weiterer Termin heute"
   darunter, nicht stillschweigend abgeschnitten. Von 0,96 auf 0,163.

4. SCHRIFTGROESSE, zweimal am selben Tag: erst die Art-Plaketten mit
   10,56 px, dann -- nach der Korrektur -- die neue Jetzt-Marke mit
   10,88. Beide Male gemeldet von pruef-handy und pruef-grosscheck,
   beide Male erst nach einem mehrminuetigen Browserlauf.

ZWEI PRUEFUNGEN, DIE SICH SELBST IM WEG STANDEN

pruef-tempo-workspace meldete "NEUE Doppelabfrage: start.html 2x
/workspace/api/termine". Nachgemessen an einem einzelnen Seitenaufruf:
genau eine Anfrage. Die Pruefung startete ihren Zaehler, bevor die
Anmeldung zur Ruhe gekommen war, und schrieb der Seite an, was die
vorherige noch offen hatte.

pruef-tagesblick fiel zum zweiten Mal auf dieselbe Falle herein: Sie
mass die Artfarbe an einem vorbeigezogenen Termin, der absichtlich grau
ist. Diesmal an der Wurzel geloest -- die Daempfung wird fuer die
Messung kurz abgeschaltet und sofort zurueckgesetzt. Damit ist die
Zuordnung fuer JEDEN Termin geprueft, unabhaengig von der Uhrzeit des
Laufs, und zusaetzlich beweist die Pruefung, dass die Daempfung greift.

NEU: Schriftgroessen werden jetzt AN DER QUELLE geprueft, in Sekunden
statt Minuten. Im Bestand stehen 43 solche Stellen; sie alle rot zu
melden haette die Pruefung ab Tag eins wertlos gemacht. Deshalb eine
Grundlinie wie beim Layout-Sprung: Sie haelt den Stand fest und
schlaegt an, sobald es MEHR werden. Heute haette das zweimal gegriffen.
Die Browserpruefung bleibt daneben -- sie sieht, was am Ende auf dem
Schirm steht, die CSS-Pruefung nur, was gemeint war.

Gesamtlauf: 56 von 56 Dateien, 2002 von 2002 Punkten.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-06 01:32:33 +02:00
co-authored by Claude Opus 5
parent 6541ecbfa7
commit e0d8e6d55d
32 changed files with 832 additions and 297 deletions
+74 -15
View File
@@ -535,11 +535,13 @@
const etwasRechts = $('tagestermine').childElementCount > 0;
/* Solange die Termine noch unterwegs sind, wird nicht versteckt --
sonst blitzt die Kachel auf und verschwindet wieder. */
if (!tagesterminGeladen) {
if (etwasLinks) $('dran-block').hidden = false;
return;
}
$('dran-block').hidden = !etwasLinks && !etwasRechts;
const kachel = $('dran-block');
if (!tagesterminGeladen) return; /* der Platzhalter haelt die Hoehe */
/* Jetzt steht beides fest: Der Platzhalter wird abgeraeumt, und die
Kachel bleibt nur, wenn sie etwas zu zeigen hat. */
delete kachel.dataset.laedt;
kachel.hidden = !etwasLinks && !etwasRechts;
}
/** hh:mm aus einem Zeitstempel, ohne Zeitzonen-Rechnerei.
@@ -587,7 +589,34 @@
return !Number.isNaN(ende.getTime()) ? ende >= jetzt : uhrzeit(t.beginn) >= jetztText;
});
for (const t of termine) {
/* HÖCHSTENS FÜNF. Zwei Gründe, und beide zählen:
Fachlich: Eine Kachel auf der Startseite beantwortet "was kommt
als Nächstes", nicht "was war alles". Wer zwanzig Termine hat,
will die nächsten sehen und dann in den Kalender -- eine Liste,
die den halben Bildschirm füllt, nimmt den Blick auf alles
darunter.
Technisch: Ohne Grenze hängt die Höhe der Kachel an der Zahl der
Termine, und der reservierte Platz kann nie passen. Der
Layout-Sprung lag deshalb bei 0,93 -- alles unterhalb rutschte
beim Laden nach unten. Mit einer Obergrenze ist die Höhe
planbar.
Warum DREI und nicht fuenf: Gemessen wurde die Kachelhoehe --
ein Termin 169 px, drei 327 px, fuenf 486 px. Je weiter die
Spanne, desto weniger kann der reservierte Platz passen, und
desto staerker springt die Seite. Bei drei liegt die Spanne bei
gut 150 Pixeln statt bei 320.
Die weggelassenen werden GENANNT, nicht verschwiegen: Eine
Liste, die stillschweigend abschneidet, liest sich wie der
ganze Tag -- und man verpasst den Termin um sechs. */
const ZEIGE_HOECHSTENS = 3;
const gezeigt = termine.slice(0, ZEIGE_HOECHSTENS);
const weitere = termine.length - gezeigt.length;
for (const t of gezeigt) {
const li = el('li', 'tagesliste__punkt');
li.dataset.art = t.art || 'termin';
@@ -597,19 +626,30 @@
hinter sich hat. Es tritt nur zurück. */
else if (beginn < jetztText) li.dataset.vorbei = 'ja';
/* ---- Links: Uhrzeit, Dauerbalken, Dauer ---- */
const zeit = el('span', 'tagesliste__zeit');
zeit.append(el('span', 'tagesliste__stunde', beginn));
if (t.dauer_min) {
zeit.append(el('span', 'tagesliste__dauer', `${t.dauer_min} min`));
/* DER BALKEN ZEIGT DIE LÄNGE. Bezugsgröße sind zwei Stunden --
darüber ist er voll. Das ist keine Skala, sondern ein
Verhältnis: Man soll auf einen Blick sehen, ob ein Termin
kurz oder lang ist, ohne "30 min" zu lesen.
Zwei Stunden als Vollausschlag, weil darüber im Alltag
kaum etwas liegt; ein Ganztagestermin würde jeden anderen
Balken sonst auf einen Strich zusammendrücken. */
const anteil = Math.max(12, Math.min(100, (Number(t.dauer_min) / 120) * 100));
const balken = el('span', 'tagesliste__balken');
balken.style.setProperty('--laenge', `${Math.round(anteil)}%`);
balken.setAttribute('aria-hidden', 'true'); // die Zahl daneben sagt es
const laenge = el('span', 'tagesliste__laenge');
laenge.append(balken, el('span', 'tagesliste__dauer', `${t.dauer_min} min`));
zeit.append(laenge);
}
li.append(zeit);
/* Der Punkt auf der Linie. Er trägt die Farbe der Terminart --
dieselbe wie im Kalender, damit man sie nicht zweimal lernt. */
const marke = el('span', 'tagesliste__marke');
marke.setAttribute('aria-hidden', 'true');
li.append(marke);
/* ---- Mitte: Titel und Beteiligte ---- */
const text = el('div', 'tagesliste__text');
text.append(el('p', 'tagesliste__titel', t.titel));
@@ -620,8 +660,14 @@
if (unten.length) text.append(el('p', 'tagesliste__unter', unten.join(' · ')));
li.append(text);
const art = el('span', 'tagesliste__art', ART_NAME[t.art] || t.art || '');
li.append(art);
/* ---- Rechts: Art und, beim nächsten, die Jetzt-Marke ---- */
const rechts = el('div', 'tagesliste__rechts');
rechts.append(el('span', 'tagesliste__art', ART_NAME[t.art] || t.art || ''));
/* Steht im Markup immer, wird aber nur beim nächsten Termin
eingeblendet (CSS). Ein Wort sagt hier mehr als ein hellerer
Hintergrund -- und ein Vorleseprogramm bekommt es ebenfalls. */
rechts.append(el('span', 'tagesliste__jetzt', 'Jetzt'));
li.append(rechts);
/* Der ganze Eintrag führt in den Kalender, auf den richtigen Tag.
Ein Termin, den man nur anschauen kann, ist eine Sackgasse. */
@@ -633,6 +679,19 @@
liste.append(li);
}
/* Was nicht mehr hineinpasste, wird gesagt -- mit dem Weg dorthin.
Eine Liste, die stillschweigend abschneidet, liest sich wie der
ganze Tag, und man verpasst den Termin um sechs. */
if (weitere > 0) {
const mehr = el('li', 'tagesliste__mehr');
const a = el('a', 'tagesliste__mehr-link',
`${weitere} weitere${weitere === 1 ? 'r Termin' : ' Termine'} heute →`);
a.href = 'kalender.html';
mehr.append(a);
liste.append(mehr);
}
tagesblickPruefen();
}