docs(08-01): complete widget registry foundation + Calculator plan summary

- 3/3 tasks executed (RED/GREEN/verify)
- 16 tests added and passing (67 total web suite)
- SUMMARY.md created with self-check PASSED
This commit is contained in:
2026-07-01 10:01:15 +02:00
parent 63ec93bd35
commit 5e8b2c2c39
@@ -0,0 +1,119 @@
---
phase: 08-dashboard-widgets-vollimplementierung
plan: "01"
subsystem: dashboard-widgets
tags: [calculator, widget-registry, tdd, dashboard, i18n, validation]
status: complete
dependency_graph:
requires: []
provides:
- WidgetType union with calculator/favorites/link/stopwatch
- WIDGET_CONSTRAINTS for all 8 widget types (DASH-11)
- wireCalculatorWidget / wireFavoritesWidget / wireLinkWidget / wireStopwatchWidget
- CalculatorWidget component (fully functional)
affects:
- apps/web/src/components/dashboard/widget-registry.tsx
- apps/web/src/components/dashboard/widget-catalog-modal.tsx
- apps/web/src/app/(portal)/page.tsx
- apps/api/src/dashboard/dto/create-widget.dto.ts
tech_stack:
added: []
patterns:
- TDD Red/Green cycle for widget + registry tests
- Arithmetic logic ported from personal-dashboard (parseDisplay/formatNumber/calculate)
- Tailwind-only styling (no CSS modules)
- wireXWidget() lazy-loading pattern extended to 4 new widget types
- @IsIn() allow-list in DTO updated (T-08-01 threat mitigated)
key_files:
created:
- apps/web/src/components/dashboard/widgets/calculator-widget.tsx
- apps/web/src/components/dashboard/widgets/calculator-widget.test.tsx
- apps/web/src/components/dashboard/widget-registry.test.tsx
modified:
- apps/web/src/components/dashboard/widget-registry.tsx
- apps/web/src/components/dashboard/widget-catalog-modal.tsx
- apps/web/src/app/(portal)/page.tsx
- apps/web/src/messages/de.json
- apps/web/src/messages/en.json
- apps/api/src/dashboard/dto/create-widget.dto.ts
decisions:
- "Grid constraints defined per-widget (D-01): calculator minW:2 minH:4 defaultW:3 defaultH:5; favorites minW:2 minH:3 defaultW:3 defaultH:5; link minW:2 minH:2 defaultW:2 defaultH:2; stopwatch minW:2 minH:2 defaultW:3 defaultH:3"
- "Calculator keyboard handler uses stopPropagation() in all handled branches (T-08-02 / Pitfall 1)"
- "Pre-existing API TypeScript errors (avatarPath) out of scope — not introduced by this plan"
metrics:
duration: "~10 minutes"
completed: "2026-07-01"
tasks_completed: 3
tests_added: 16
files_created: 3
files_modified: 7
---
# Phase 08 Plan 01: Widget Registry Foundation + Calculator Summary
Widget-Registry-Grundlage fuer alle Phase-8-Typen (DASH-11) und voll funktionsfaehiger Calculator-Widget (DASH-08) via TDD Red/Green-Zyklus.
## What Was Built
- **Calculator Widget** (`calculator-widget.tsx`): Vollstaendige Implementierung portiert aus personal-dashboard. Grundrechenarten (+, −, ×, ÷), Tastatureingabe, Dezimalkomma, Division-durch-Null-Schutz ("Fehler"), Memory-Funktionen (MC/MR/M+/M−/MS). `stopPropagation()` in jedem Keyboard-Handler-Branch verhindert react-grid-layout-Interferenz.
- **Widget Registry Foundation**: `WidgetType`-Union auf 8 Typen erweitert. `WIDGET_CONSTRAINTS` mit einheitlicher Feldstruktur (minW/minH/defaultW/defaultH) fuer alle 8 Typen. Vier neue SVG-Icons, vier neue WIDGET_REGISTRY-Eintraege, vier neue `wireXWidget()`-Funktionen fuer spaetere Plaene.
- **Catalog Modal**: `WIDGET_TYPES`-Array auf alle 8 Typen erweitert — neue Widgets erscheinen im Dashboard-Katalog.
- **API DTO**: `@IsIn()`-Allowlist auf alle 8 WidgetTypes erweitert — POST `/dashboard/widgets` akzeptiert neue Typen ohne 400-Fehler.
- **i18n**: Schluesselsatz fuer calculator/favorites/link/stopwatch in `de.json` und `en.json` ergaenzt.
## Tasks
| Task | Description | Status | Commit |
|------|-------------|--------|--------|
| 1 | RED: Failing tests fuer Calculator und Registry-Constraints | Complete | b751ae7 |
| 2 | GREEN: Registry-Foundation + Calculator-Implementierung | Complete | 63ec93b |
| 3 | Full Suite + TypeCheck-Gate | Complete | — (no changes needed) |
## Test Results
- **calculator-widget.test.tsx**: 6 Tests — initiales Display "0", 7+3=10, 8×2=16, Division-durch-Null=Fehler, Keyboard 5*6Enter=30, Dezimalkomma 1,5+1,5=3
- **widget-registry.test.tsx**: 10 Tests — alle 8 WidgetTypes haben 4 numerische Constraint-Felder
- **Full Web Suite**: 67/67 Tests bestehen
- **Web TypeScript**: sauber (0 Fehler)
- **API TypeScript**: 6 Pre-existing-Fehler (avatarPath — nicht durch diesen Plan verursacht)
## Deviations from Plan
### Pre-Existing Issue (out of scope)
**API TypeScript-Fehler (avatarPath):** `src/auth/auth.service.ts` und `src/user/user.controller.ts` referenzieren `avatarPath` das noch nicht im Prisma-Client generiert wurde (Quick Plan 260630-gbh fugte Avatar-Feature hinzu, aber `prisma generate` wurde nach `db push` nicht in den Commit aufgenommen). Diese 6 Fehler existieren identisch im Main-Branch und wurden durch Plan 01 nicht eingefuehrt. Scope: DEFERRED.
### Node Modules (worktree setup)
Symlinks von `apps/web/node_modules` und `apps/api/node_modules` im Worktree auf Main-Repo-node_modules wurden erstellt um Tests lauffaehig zu machen. Die Symlinks sind in `.gitignore` (`node_modules/`) und werden nicht committed.
### Test-Ausführungsbefehl (auto-fix)
Der Plan spezifiziert `pnpm --filter @tessera/web test --run` — dieser Befehl existiert im Worktree nicht (`node_modules` fehlen initial). Fix: Symlinks erstellt, dann direkt `node_modules/.bin/vitest run` aufgerufen. Gleiches Ergebnis.
### "Gleich"-Button ariaLabel
Der `=`-Button hat `ariaLabel={`Gleich ${getOperatorLabel(pendingOperator)}`}`. Die Tests nutzen `getByRole('button', { name: /gleich/i })` (case-insensitive regex) statt des genauen Labels, was mit dem dynamischen Label kompatibel ist.
## Known Stubs
Keine Stubs. Calculator-Widget ist vollstaendig implementiert. Die Placeholder-Komponente fuer favorites/link/stopwatch in WIDGET_REGISTRY ist bewusst — diese Widgets werden in Plaenen 02-04 implementiert.
## Threat Surface Scan
Keine neuen Sicherheitsoberflaechen eingefuehrt. T-08-01 (Tampering via widgetType) und T-08-02 (DoS via Keyboard-Events) wurden gemaess Threat Model mitigiert.
## Self-Check: PASSED
| Item | Status |
|------|--------|
| calculator-widget.tsx | FOUND |
| calculator-widget.test.tsx | FOUND |
| widget-registry.test.tsx | FOUND |
| Commit b751ae7 (RED) | FOUND |
| Commit 63ec93b (GREEN) | FOUND |