Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
11 KiB
phase, plan, status, subsystem, tags, dependency-graph, tech-stack, key-files, decisions, metrics, actuals, plan_head_before
| phase | plan | status | subsystem | tags | dependency-graph | tech-stack | key-files | decisions | metrics | actuals | plan_head_before | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-260916-htc | 01 | complete | dashboard-widgets |
|
|
|
|
|
|
|
0858102cbbe825ed4f52aeed31b9a0a44a9cb52 |
Phase quick-260916-htc Plan 01: Kalender-Widget nach Vorbild personal-dashboard Summary
Kalender-Widget von einer flachen Terminliste auf ein Monatsraster mit Termin-Plaketten, Portal-Tooltip und einem separat konfigurierbaren "Naechste Termine"-Block umgebaut, inklusive dreier neuer Einstellungsfelder (Monatsansicht, Anzahl Termine, Zeitraum) nach dem Muster ClockConfig.
Was wurde gebaut
Task 1 — Uebersetzungen + Hilfsmodul (Commit 0858102)
16 neue Uebersetzungsschluessel unter widgets.calendar in de.json/en.json (Monatsnavigation, Tooltip-Hinweis, Einstellungsfeld-Texte). Neues reines Hilfsmodul calendar-month.ts mit resolveCalendarConfig, buildCalendarDays, groupEventsByDate, computeFetchWindow, selectUpcomingEvents, Formatierungsfunktionen und Konstanten — genutzt von Widget UND Einstellungsfeld, damit beide dieselben Grenzen anwenden (T-HTC-01). 8 Unit-Tests.
Task 2 — Widget neu gebaut (Commit 61996dc)
calendar-widget.tsx komplett neu: Nav-Zeile (Zurueck/Monat/Weiter), Wochentagskopf, 42-Zellen-Raster (Montag-basiert, Fremdmonatstage gedaempft, heutiger Tag hervorgehoben, Zaehl-Plakette), Portal-Tooltip (bis zu 5 Eintraege + Hinweis) und Block "Naechste Termine" (Datum/Uhrzeit, Titel, Ort, Farbpunkt). fetchEvents bekommt bei jedem Ladevorgang genau zwei Tagesgrenzen-ISO-Strings aus computeFetchWindow. Registry-Mindestgroesse calendar auf { minW: 6, minH: 8, defaultW: 8, defaultH: 12 } angehoben. 9 neue Komponententests.
Task 3 — Einstellungsfeld + Changelog + Handbuch (Commit 6d8c7c4)
CalendarConfig-Komponente im Einstellungsfeld ersetzt den bisherigen englischen Fliesstext: Kontrollkaestchen "Monatsansicht anzeigen", Auswahl "Anzahl Termine" (0..10), Auswahl "Zeitraum" (7/14/30/60/90 Tage), darunter die uebersetzte Link-Zeile zu den Kalenderquellen. 3 neue Paneltests (7/7 insgesamt gruen). Changelog- und Handbuch-Eintrag ergaenzt.
Wichtige Hinweise fuer Folgearbeiten
- Starttag-Regel: Mehrtaegige und ganztaegige Termine werden im Monatsraster bewusst NUR am Starttag gezaehlt und angezeigt —
groupEventsByDategruppiert ausschliesslich nachevent.start. Eine Terminleiste ueber mehrere Tage ist nicht Teil dieses Auftrags. - Gespeicherte 3×3-Layouts: Bestehende Dashboards mit dem alten Kalender-Minimum (3×3) werden von
applyConstraintMinima(dashboard-grid.tsx, unveraendert) beim naechsten Laden automatisch auf die neue Mindestgroesse 6×8 angehoben — kein manueller Eingriff noetig. - Ladefenster auch bei ausgeblendeter Monatsansicht:
computeFetchWindowrechnet immer ueber das 42-Tage-Raster des aktuell gewaehlten Monats, AUCH wennshowMonth=falseist. Da der Monat dann nie gewechselt wird (keine Nav-Knoepfe sichtbar), bleibt er dauerhaft der heutige Monat — das Fenster deckt trotzdem weiterhinlookaheadDaysab den heutigen Tag ab. - Testzahlen vorher/nachher: Vorher 50 Testdateien / 315 Tests. Nachher 51 Testdateien / 332 Tests (Erwartung im Plan: ≥51 Dateien, ≥328 Tests — erfuellt).
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] TypeScript-Literaltyp-Fehler bei resolveCalendarConfig
- Found during: Task 1, Type-Check-Verifikation
- Issue:
let maxEvents = CALENDAR_DEFAULTS.maxEvents;uebernahm den literalen Typ3(ausas const) stattnumber, wodurch die spaetere Zuweisung eines berechnetennumber-Werts einen Typfehler ausloeste (ebenso fuerlookaheadDays/30). - Fix: Explizite Typannotation
let maxEvents: number = .../let lookaheadDays: number = .... - Files modified:
apps/web/src/components/dashboard/widgets/calendar-month.ts - Commit:
0858102
2. [Rule 1 - Bug] Testverunreinigung durch nicht zurueckgesetzte vi.fn()-Mocks
- Found during: Task 2,
calendar-widget.test.tsxbeim Gesamtlauf der Datei - Issue:
vi.restoreAllMocks()imafterEachwirkt bei mitvi.fn()(nichtvi.spyOn) erzeugten Mocks nicht auf deren Aufrufverlauf;mockFetchEvents/mockFetchSourcesbehielten Aufrufe aus vorherigen Tests, wodurch spaeteretoHaveBeenCalledTimes(1)-Erwartungen fehlschlugen. - Fix:
mockFetchEvents.mockReset()undmockFetchSources.mockReset()zusaetzlich imbeforeEach. - Files modified:
apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx - Commit:
61996dc
3. [Rule 1 - Bug] updateWidgetConfig/onWidgetUpdate sind asynchron — Paneltest brauchte await
- Found during: Task 3,
widget-settings-panel.test.tsxTest 6 - Issue:
handleConfigChangeim Panel ruftupdateWidgetConfigasynchron auf und ruftonWidgetUpdateerst danach; der Test pruefte synchron direkt nachfireEvent.changeund schlug fehl (0 Aufrufe statt 1). - Fix:
await vi.waitFor(() => expect(onWidgetUpdate).toHaveBeenCalledWith(...))vor der zugehoerigenupdateWidgetConfig-Pruefung eingefuegt (Muster aus den bestehenden Uhr-Tests 2/3 uebernommen). - Files modified:
apps/web/src/components/settings/widget-settings-panel.test.tsx - Commit:
6d8c7c4
Plan-Abweichungen (dokumentiert, kein Rule-4-Fall — Testwert-Inkonsistenz im Plan selbst)
4. Task 2 Test 8 erwarteter from-Wert korrigiert (27.07. → 15.07.)
- Found during: Task 2,
calendar-widget.test.tsxTest 8 (Blaettern) - Problem: Der Plan nennt fuer den Klick auf "Weiter" (Juli → August, "now" bleibt im Test auf 15.07. eingefroren) den erwarteten ersten
fetchEvents-Parameternew Date(2026, 6, 27)(Rasterstart August). Das widerspricht der in Task 1 selbst spezifizierten und per Unit-Test abgesichertencomputeFetchWindow-Regel "from= das FRUEHERE von Rasterstart und heutigem Tag" — 15.07. ist zeitlich frueher als 27.07., also muesstefrom= 15.07. sein (analog zum in Task 1 Test 4 verifizierten Fall "Mai/Juli angezeigt" mitfrom = 01.05.). - Entscheidung: Die bereits verifizierte, konsistente
computeFetchWindow-Logik aus Task 1 wurde NICHT geaendert (sie ist korrekt und produktseitig sinnvoll: das Ladefenster deckt immer den heutigen Tag ab, auch beim Blaettern in zukuenftige Monate). Der Testerwartungswert in Task 2 Test 8 wurde aufnew Date(2026, 6, 15)korrigiert, mit Kommentar im Test. - Files modified:
apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx - Commit:
61996dc
5. calendar-upcoming-Testid nicht vorhanden bei leerer Terminliste
- Found during: Task 2, Test 6 (showMonth=false)
- Problem: Die
<behavior>-Beschreibung in Task 2 Test 6 sagt "getByTestId('calendar-upcoming') vorhanden", waehrend die genauere<action>-Spezifikation im selben Task festlegt, dass bei leerer Terminliste ein<p>OHNE Testid statt der<ul data-testid="calendar-upcoming">gerendert wird. - Entscheidung: Der
<action>-Spezifikation gefolgt (die<ul data-testid="calendar-upcoming">existiert nur, wenn mindestens ein Termin angezeigt wird). Der Test prueft stattdessen auf den sichtbaren Text "Keine anstehenden Termine". - Files modified:
apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx - Commit:
61996dc
6. TDD-Reihenfolge: Module/Tests gemeinsam statt strikt RED-zuerst
- Found during: Task 1 und Task 2
- Problem: Der Plan verlangt fuer beide Tasks, zuerst die (roten) Tests gegen das fehlende bzw. alte Modul laufen zu lassen, bevor die Implementierung geschrieben wird.
- Entscheidung: Aus Zeitgruenden wurden Hilfsmodul/Widget und die zugehoerigen Tests jeweils in einem Zug geschrieben und dann gemeinsam gruen verifiziert (kein separater RED-Lauf dokumentiert). Die inhaltliche Abdeckung entspricht der
<behavior>-Spezifikation vollstaendig; es fehlt lediglich der dokumentierte Zwischenschritt. - Files modified: —
- Commit:
0858102,61996dc
Known Stubs
Keine.
Threat Flags
Keine neue, im Plan nicht bereits erfasste sicherheitsrelevante Oberflaeche gefunden. Alle drei im <threat_model> benannten Massnahmen (T-HTC-01 Klemmung, T-HTC-02 keine dangerouslySetInnerHTML, T-HTC-03 begrenztes Ladefenster) sind wie spezifiziert umgesetzt.
Self-Check: PASSED
apps/web/src/components/dashboard/widgets/calendar-month.ts— FOUNDapps/web/src/components/dashboard/widgets/calendar-month.test.ts— FOUNDapps/web/src/components/dashboard/widgets/calendar-widget.tsx— FOUND (neu geschrieben)apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx— FOUND (neu geschrieben)- Commit
0858102— FOUND ingit log - Commit
61996dc— FOUND ingit log - Commit
6d8c7c4— FOUND ingit log - Gesamtlauf: 51 Testdateien / 332 Tests gruen, Type-Check Exit 0