Files
dogfather-universe/server/workspace-termin-regel.js
T
DogFatherGitandClaude Opus 5 5e628e0078 Brett und Kalender kennen einander jetzt in beide Richtungen
Der Kalender zeigt seit heute, was auf den Brettern steht und einen
Termin hat. Die Verbindung war aber EINSEITIG, und beide Halften
fehlten:

  Beim SCHREIBEN konnte niemand wissen, dass ein Tag in der Zukunft den
  Zettel in den Kalender bringt. Das Feld heisst "Datum" und ist mit
  HEUTE vorbelegt -- die Funktion war vorhanden und unauffindbar. Eine
  Funktion, die niemand findet, ist keine.

  Beim LESEN sagte die Karte nichts. Am Fuss stand bloss ein Datum, und
  "24.09.2026" sieht aus wie "17.09.2026" -- obwohl das eine ein Termin
  ist und das andere der Tag, an dem jemand getippt hat.

EINE REGEL, ZWEI VERWENDER -> server/workspace-termin-regel.js.
Der Kalender fragt "welche gehoeren hinein?" (SQL, ganze Tabelle), die
Brettkarte fragt "stehe ICH drin?" (JavaScript, je Zeile). Beide Fassungen
stehen jetzt nebeneinander in EINER Datei, importfrei wie
treff-tabellen.js.

Das ist kein Vorsichtsprinzip, sondern Erfahrung: Zwei Fassungen
derselben Regel sind im Haus dreimal auseinandergelaufen -- die
abgeschriebene Spaltenliste (11.09., drei Spalten samt Inhalt weg), die
zweite Artenliste neben ARTNAME (ein BigMatch liess sich anlegen und
war unsichtbar) und `.teilen` heute frueh.

server/pruef-terminregel.mjs, 35 Pruefungen. Der Kern ist Abschnitt 2:
Er prueft die beiden Fassungen GEGENEINANDER, nicht jede fuer sich --
zwei Pruefungen, die je eine Seite bestaetigen, finden genau diesen
Fehler nicht. Verglichen wird beides: WELCHE Zettel und WELCHER Tag.
Neun Faelle, davon vier, die zu Recht wegbleiben.

Vier Gegenproben, jede in ihre eigene Richtung:
  JS laesst mehr durch -> "die Karte behauptet einen Termin, den der
                           Kalender nicht kennt"
  JS nennt anderen Tag -> "verschiedene Tage: Kalender 22., Karte 17."
  SQL laesst mehr durch-> "steht im Kalender, aber die Karte sagt nichts"
  Marke ausgebaut      -> 0 statt 1

EIN ECHTER FEHLER DABEI BEHOBEN, und er war aelter als diese Arbeit:
Das Formularraster gibt jedem Feld GENAU ZWEI Zeilen (Schild dehnbar,
Eingabe fest 44 px) -- deshalb sitzen die Eingaben auf einer Linie. Ein
Hinweisabsatz erzeugt eine dritte Zeile, und weil das Raster alle
Felder auf gleiche Hoehe dehnt, rutscht ausgerechnet diese Eingabe nach
oben. Gemessen: 328..372 gegen 351..395. 23 px -- genau das, was man
als "verzogen" sieht.

Mit `git stash` getrennt: aufgaben.html war dadurch SCHON VORHER rot
(ein anderes Feld hat dort ebenfalls einen Hinweis), bereich.html hatte
ich neu verursacht. Der Hinweis haengt jetzt absolut unter dem Feld --
beide sind gruen, und zwar an der Wurzel, nicht symptomatisch.
`pointer-events: none`, sonst faengt der Satz Klicks ab, die dem
Element darunter galten.

Am Handy gemessen statt geschaetzt: 0 Ueberschneidungen mit anderen
Feldern. Gegenprobe (row-gap auf 2 px): 1 Ueberschneidung.

Und noch zwei eigene Pruefungsfehler behoben, beide von derselben Sorte:
ein falscher Selektor samt `.catch(() => {})`, der den Fehlgriff
lautlos verschluckte (danach war das Hinweisfeld leer und die Zeile
darunter trotzdem gruen, weil "" nun einmal nicht "ja" ist) -- und die
Marke wurde ueber `textContent` gezaehlt statt ueber ihre Sichtbarkeit.
Aufgefallen ist das am Bildschirmfoto, auf dem ich sie fuer fehlend
hielt; deshalb macht die Pruefung jetzt zusaetzlich einen AUSSCHNITT
der Karte -- auf einem Vollbild von 2000 px ist eine Pille von 28 px
nicht zu beurteilen.

Gruen: terminregel, kalender, formulare, ueberlappung, countdown,
namen, css-klassen, struktur.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 23:53:05 +02:00

110 lines
4.7 KiB
JavaScript

/* =====================================================================
WANN EIN ZETTEL EINEN TERMIN HAT (17.09.2026)
EINE Regel, zwei Verwender -- und deshalb eine eigene Datei.
Seit heute zeigt der Kalender, was auf den Brettern steht und einen
Termin hat. Die Bedingung dafuer stand als SQL mitten in
workspace-kalender.js. Sobald die Brettkarte dasselbe sagen soll
("steht im Kalender am 24."), braeuchte sie eine zweite Fassung --
und zwei Fassungen derselben Regel laufen auseinander. Nicht sofort,
sondern beim naechsten Nachschaerfen, und dann zeigt die Karte etwas
anderes als der Kalender. Das ist schlimmer als beides wegzulassen:
Man glaubt der Anzeige ja.
Dieselbe Krankheit gab es im Haus schon zweimal -- die abgeschriebene
Spaltenliste (11.09., drei Spalten samt Inhalt verloren) und die
zweite Artenliste neben ARTNAME (im Kalender, ein BigMatch liess
sich anlegen und war danach unsichtbar).
DIE DATEI IMPORTIERT NICHTS. Muster wie treff-tabellen.js und
workspace-bewerbung-rollen.js: Ein Blatt ohne eigene Importe kann von
ueberall gelesen werden, ohne einen Ring zu bauen -- und ein Ring
aeussert sich in JavaScript nicht als Fehler, sondern als
`undefined` an einer Stelle, an der niemand damit rechnet.
-------------------------------------------------------------------
WARUM GENAU DIESE VIER FAELLE
`eintraege.datum` ist ein PFLICHTFELD und faellt auf HEUTE zurueck,
wenn niemand eins waehlt. Alle Eintraege in den Kalender zu nehmen
hiesse also: jeder je getippte Zettel steht an dem Tag, an dem ihn
jemand getippt hat. Nach einem Monat waere der Kalender ein
Protokoll und kein Plan -- und einer, in dem alles steht, sagt
nichts mehr.
geplant Eine Zusage: "Wird gemacht -- am 24.09." Das ist ein
Termin, den jemand jemandem gegeben hat.
event_ende Ein Zeitraum. Wer ein Ende eintraegt, meint eine
Veranstaltung, keine Notiz.
uhrzeit Wer eine Uhrzeit tippt, meint einen Zeitpunkt.
Niemand traegt aus Versehen 20:00 ein.
datum > heute Der Rueckfall ist IMMER heute oder frueher. Ein Datum
in der Zukunft kann nur Absicht sein.
Der letzte Fall ist der wichtigste und der unauffaelligste: Er
braucht kein neues Feld und keine Umgewoehnung.
===================================================================== */
/** Der massgebliche Tag eines Eintrags -- als SQL-Ausdruck.
*
* Eine Zusage schlaegt das Erfassungsdatum: Wer "am 24." sagt, meint
* den 24., auch wenn der Zettel am 3. entstanden ist. */
export const TERMIN_TAG_SQL = "COALESCE(e.geplant, e.datum)";
/** Die Bedingung als SQL. Erwartet GENAU EINEN Platzhalter: den
* heutigen Tag in Ortszeit (`heuteLokal()`).
*
* UTC waere hier falsch: Zwischen Mitternacht und zwei Uhr morgens
* liefert es in Deutschland den Vortag, und ein Zettel von heute
* staende dann ploetzlich im Kalender. */
export const TERMIN_BEDINGUNG_SQL = `(
e.geplant IS NOT NULL
OR e.event_ende IS NOT NULL
OR e.uhrzeit IS NOT NULL
OR e.datum > ?
)`;
/** Warum er drinsteht -- als SQL-Ausdruck. Die Reihenfolge ist die
* Rangfolge: Eine Zusage ist mehr als ein Zeitraum, ein Zeitraum mehr
* als eine Uhrzeit. */
export const TERMIN_GRUND_SQL = `CASE
WHEN e.geplant IS NOT NULL THEN 'zugesagt'
WHEN e.event_ende IS NOT NULL THEN 'zeitraum'
WHEN e.uhrzeit IS NOT NULL THEN 'uhrzeit'
ELSE 'termin'
END`;
/** Welche Zustaende NICHT in den Kalender gehoeren.
*
* Ein Kalender zeigt, was ansteht. Was gemacht oder abgelehnt ist,
* gehoert auf sein Brett -- nicht in die Planung der naechsten Woche. */
export const OHNE_ZUSTAENDE = ["erledigt", "abgelehnt"];
/** Dieselbe Frage in JavaScript -- fuer einen einzelnen Eintrag.
*
* Sie wird beim Ausliefern der Brettkarten gebraucht: Dort steht seit
* heute "im Kalender am 24.", und diese Auskunft MUSS dieselbe sein
* wie die des Kalenders. Beide Fassungen stehen deshalb in dieser
* Datei nebeneinander, damit eine Aenderung an der einen die andere
* ins Auge springen laesst -- und pruef-terminregel.mjs weist nach,
* dass sie fuer dieselben Zeilen dasselbe sagen.
*
* @param e Zeile aus `eintraege` (mit geplant, event_ende, uhrzeit,
* datum, status)
* @param heute Heutiger Tag in Ortszeit, "JJJJ-MM-TT"
* @returns {null|{tag, grund}} */
export function terminVon(e, heute) {
if (!e) return null;
if (OHNE_ZUSTAENDE.includes(e.status)) return null;
const grund = e.geplant ? "zugesagt"
: e.event_ende ? "zeitraum"
: e.uhrzeit ? "uhrzeit"
: (e.datum && heute && e.datum > heute) ? "termin"
: null;
if (!grund) return null;
return { tag: e.geplant || e.datum, grund };
}