docs(05-04): complete calendar frontend plan
This commit is contained in:
@@ -43,15 +43,15 @@ Requirements for initial release. Each maps to roadmap phases.
|
|||||||
- [x] **DASH-02**: Widgets koennen frei positioniert und in der Groesse geaendert werden
|
- [x] **DASH-02**: Widgets koennen frei positioniert und in der Groesse geaendert werden
|
||||||
- [x] **DASH-03**: Uhr-Widget (analog oder digital)
|
- [x] **DASH-03**: Uhr-Widget (analog oder digital)
|
||||||
- [x] **DASH-04**: Suchleiste-Widget (oeffnet Google/Suchmaschine im Browser)
|
- [x] **DASH-04**: Suchleiste-Widget (oeffnet Google/Suchmaschine im Browser)
|
||||||
- [ ] **DASH-05**: Kalender-Widget mit Terminvorschau
|
- [x] **DASH-05**: Kalender-Widget mit Terminvorschau
|
||||||
- [x] **DASH-06**: Notiz-Widget (Freitext-Kachel)
|
- [x] **DASH-06**: Notiz-Widget (Freitext-Kachel)
|
||||||
- [x] **DASH-07**: Dashboard-Layout wird pro Benutzer gespeichert
|
- [x] **DASH-07**: Dashboard-Layout wird pro Benutzer gespeichert
|
||||||
|
|
||||||
### Kalender-Integration
|
### Kalender-Integration
|
||||||
|
|
||||||
- [ ] **CAL-01**: In Einstellungen koennen mehrere Kalenderquellen eingebunden werden (WebDAV, Exchange, ICS-Link)
|
- [ ] **CAL-01**: In Einstellungen koennen mehrere Kalenderquellen eingebunden werden (WebDAV, Exchange, ICS-Link)
|
||||||
- [ ] **CAL-02**: Benutzer kann waehlen welche Kalender im Widget angezeigt werden
|
- [x] **CAL-02**: Benutzer kann waehlen welche Kalender im Widget angezeigt werden
|
||||||
- [ ] **CAL-03**: Benutzer kann waehlen fuer welche Kalender Terminvorschauen angezeigt werden
|
- [x] **CAL-03**: Benutzer kann waehlen fuer welche Kalender Terminvorschauen angezeigt werden
|
||||||
|
|
||||||
### Module System
|
### Module System
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ Decimal phases appear between their surrounding integers in numeric order.
|
|||||||
|
|
||||||
**Wave 4** *(blocked on Wave 3 completion)*
|
**Wave 4** *(blocked on Wave 3 completion)*
|
||||||
|
|
||||||
- [ ] 05-04-PLAN.md -- Calendar frontend: calendar widget, calendar settings page, API client (CAL-01/02/03, DASH-05)
|
- [x] 05-04-PLAN.md -- Calendar frontend: calendar widget, calendar settings page, API client (CAL-01/02/03, DASH-05)
|
||||||
|
|
||||||
**Wave 5** *(blocked on Wave 4 completion)*
|
**Wave 5** *(blocked on Wave 4 completion)*
|
||||||
|
|
||||||
@@ -210,5 +210,5 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6
|
|||||||
| 2. Authentication & Multi-Tenancy | 2/5 | In Progress| |
|
| 2. Authentication & Multi-Tenancy | 2/5 | In Progress| |
|
||||||
| 3. Module System & Domaincheck | 3/4 | In Progress| |
|
| 3. Module System & Domaincheck | 3/4 | In Progress| |
|
||||||
| 4. Marketplace & Portal Navigation | 0/4 | Not started | - |
|
| 4. Marketplace & Portal Navigation | 0/4 | Not started | - |
|
||||||
| 5. Dashboard & Calendar | 3/5 | In Progress| |
|
| 5. Dashboard & Calendar | 4/5 | In Progress| |
|
||||||
| 6. Desktop Client & CI/CD | 0/TBD | Not started | - |
|
| 6. Desktop Client & CI/CD | 0/TBD | Not started | - |
|
||||||
|
|||||||
+10
-6
@@ -4,14 +4,14 @@ milestone: v1.0
|
|||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: executing
|
status: executing
|
||||||
stopped_at: Completed 05-03-PLAN.md
|
stopped_at: Completed 05-03-PLAN.md
|
||||||
last_updated: "2026-06-24T13:16:25Z"
|
last_updated: "2026-06-24T13:28:10.956Z"
|
||||||
last_activity: 2026-06-24 -- Calendar backend complete
|
last_activity: 2026-06-24 -- Calendar backend complete (Plan 03)
|
||||||
progress:
|
progress:
|
||||||
total_phases: 6
|
total_phases: 6
|
||||||
completed_phases: 3
|
completed_phases: 3
|
||||||
total_plans: 21
|
total_plans: 21
|
||||||
completed_plans: 18
|
completed_plans: 19
|
||||||
percent: 86
|
percent: 50
|
||||||
---
|
---
|
||||||
|
|
||||||
# Project State
|
# Project State
|
||||||
@@ -26,7 +26,7 @@ See: .planning/PROJECT.md (updated 2026-06-18)
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 05 (dashboard-calendar) — EXECUTING
|
Phase: 05 (dashboard-calendar) — EXECUTING
|
||||||
Plan: 4 of 5
|
Plan: 5 of 5
|
||||||
Status: Ready to execute
|
Status: Ready to execute
|
||||||
Last activity: 2026-06-24 -- Calendar backend complete (Plan 03)
|
Last activity: 2026-06-24 -- Calendar backend complete (Plan 03)
|
||||||
|
|
||||||
@@ -57,6 +57,7 @@ Progress: [████████░░] 86%
|
|||||||
| Phase 05-dashboard-calendar P01 | 14min | 4 tasks | 28 files |
|
| Phase 05-dashboard-calendar P01 | 14min | 4 tasks | 28 files |
|
||||||
| Phase 05-dashboard-calendar P02 | 4min | 4 tasks | 16 files |
|
| Phase 05-dashboard-calendar P02 | 4min | 4 tasks | 16 files |
|
||||||
| Phase 05-dashboard-calendar P03 | 11min | 4 tasks | 14 files |
|
| Phase 05-dashboard-calendar P03 | 11min | 4 tasks | 14 files |
|
||||||
|
| Phase 05-dashboard-calendar PP04 | 5min | 2 tasks | 11 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -84,6 +85,9 @@ Recent decisions affecting current work:
|
|||||||
- [05-03]: Dynamic imports for ews-javascript-api and @microsoft/microsoft-graph-client (lazy-load)
|
- [05-03]: Dynamic imports for ews-javascript-api and @microsoft/microsoft-graph-client (lazy-load)
|
||||||
- [05-03]: In-memory Map cache with 5-min TTL for calendar events (Redis not needed at current scale)
|
- [05-03]: In-memory Map cache with 5-min TTL for calendar events (Redis not needed at current scale)
|
||||||
- [05-03]: ews-javascript-api imported as any (no TypeScript definitions available)
|
- [05-03]: ews-javascript-api imported as any (no TypeScript definitions available)
|
||||||
|
- [Phase ?]: Optimistic UI for calendar visibility toggle — reverts on API error
|
||||||
|
- [Phase ?]: Auto-run testSource after adding new calendar source for immediate feedback
|
||||||
|
- [Phase ?]: URL constructor for client-side https-only validation (T-05-14)
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -103,6 +107,6 @@ Items acknowledged and carried forward from previous milestone close:
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-06-24T13:16:25Z
|
Last session: 2026-06-24T13:27:57.769Z
|
||||||
Stopped at: Completed 05-03-PLAN.md
|
Stopped at: Completed 05-03-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
---
|
||||||
|
phase: 05-dashboard-calendar
|
||||||
|
plan: 04
|
||||||
|
subsystem: ui
|
||||||
|
tags: [calendar, frontend, widget, settings, react, next-intl, tdd, caldav, ics, exchange]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 05-dashboard-calendar/01
|
||||||
|
provides: Dashboard grid + widget registry + Prisma models + settings layout + i18n
|
||||||
|
- phase: 05-dashboard-calendar/02
|
||||||
|
provides: Widget settings panel pattern + SearchProvider CRUD pattern
|
||||||
|
- phase: 05-dashboard-calendar/03
|
||||||
|
provides: Calendar backend API (source CRUD, event aggregation, encryption, providers)
|
||||||
|
provides:
|
||||||
|
- CalendarWidget component rendering upcoming events with source color dots
|
||||||
|
- CalendarSettingsPanel for managing calendar sources with visibility toggle
|
||||||
|
- CalendarSourceForm with type-specific fields and https-only validation
|
||||||
|
- calendar-api.ts client (fetchSources/addSource/updateSource/deleteSource/testSource/fetchEvents)
|
||||||
|
- Widget registry wired with real CalendarWidget (replaces placeholder)
|
||||||
|
affects: [05-dashboard-calendar/05]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [calendar-api-client-pattern, visibility-toggle-optimistic-update, source-form-type-conditional-fields, tdd-red-green-commit-flow]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- apps/web/src/lib/calendar-api.ts
|
||||||
|
- apps/web/src/components/dashboard/widgets/calendar-widget.tsx
|
||||||
|
- apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx
|
||||||
|
- apps/web/src/components/settings/calendar-settings-panel.tsx
|
||||||
|
- apps/web/src/components/settings/calendar-source-form.tsx
|
||||||
|
- apps/web/src/app/(portal)/settings/dashboard/calendar/page.tsx
|
||||||
|
- apps/web/src/app/(portal)/settings/dashboard/calendar/calendar-settings.test.tsx
|
||||||
|
modified:
|
||||||
|
- apps/web/src/components/dashboard/widget-registry.tsx
|
||||||
|
- apps/web/src/app/(portal)/page.tsx
|
||||||
|
- apps/web/src/messages/de.json
|
||||||
|
- apps/web/src/messages/en.json
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Optimistic UI update for visibility toggle — reverts on API error"
|
||||||
|
- "Auto-run testSource after adding a new source (connection test feedback)"
|
||||||
|
- "CalendarSourceForm uses URL constructor for client-side https validation (T-05-14)"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Calendar API client: separate module from dashboard-api following same credentials:'include' pattern"
|
||||||
|
- "Optimistic toggle: update local state immediately, revert on error for responsive UX"
|
||||||
|
- "Type-conditional form fields: Exchange-mode select only for exchange type, hide credentials for ICS"
|
||||||
|
|
||||||
|
requirements-completed: [DASH-05, CAL-02, CAL-03]
|
||||||
|
|
||||||
|
duration: 5min
|
||||||
|
completed: 2026-06-24
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 05 Plan 04: Calendar Frontend Summary
|
||||||
|
|
||||||
|
**Calendar widget displaying aggregated events with source color dots, plus settings page for CalDAV/ICS/Exchange source management with visibility toggle and connection testing**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 5 min
|
||||||
|
- **Started:** 2026-06-24T13:21:01Z
|
||||||
|
- **Completed:** 2026-06-24T13:26:32Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 11
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Calendar widget fetches and displays upcoming events from visible sources via `/api/calendar/events` with 5-min refresh cycle
|
||||||
|
- Three distinct empty states per UI-SPEC: no sources, no events, loading
|
||||||
|
- Source management settings page at `/settings/dashboard/calendar` with visibility toggle (CAL-02), type badges, color dots, connection status indicators
|
||||||
|
- Calendar source form with conditional fields: Exchange-mode select for Exchange type, hidden credentials for ICS, 8-color palette picker
|
||||||
|
- Delete confirmation dialog per UI-SPEC destructive pattern
|
||||||
|
- Client-side https-only URL validation (T-05-14 threat mitigation)
|
||||||
|
- All 6 tests passing with TDD RED/GREEN commit flow
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Calendar API client + calendar widget (RED)** - `2d8699e` (test)
|
||||||
|
2. **Task 1: Calendar API client + calendar widget (GREEN)** - `c0f2f4c` (feat)
|
||||||
|
3. **Task 2: Calendar settings page (RED)** - `f99ff9a` (test)
|
||||||
|
4. **Task 2: Calendar settings page (GREEN)** - `24de136` (feat)
|
||||||
|
|
||||||
|
## TDD Gate Compliance
|
||||||
|
|
||||||
|
- RED gate: `2d8699e` (test commit) exists before `c0f2f4c` (feat commit) for Task 1
|
||||||
|
- RED gate: `f99ff9a` (test commit) exists before `24de136` (feat commit) for Task 2
|
||||||
|
- Both tasks follow proper RED -> GREEN sequence
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `apps/web/src/lib/calendar-api.ts` - Calendar API client with typed interfaces mirroring 05-03 backend contract
|
||||||
|
- `apps/web/src/components/dashboard/widgets/calendar-widget.tsx` - Upcoming events list widget with color dots and three empty states
|
||||||
|
- `apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx` - 3 tests: events rendering, no-events, no-sources
|
||||||
|
- `apps/web/src/components/settings/calendar-settings-panel.tsx` - Source list with visibility toggle, edit/delete, connection status
|
||||||
|
- `apps/web/src/components/settings/calendar-source-form.tsx` - Add/edit form with type-conditional fields and https validation
|
||||||
|
- `apps/web/src/app/(portal)/settings/dashboard/calendar/page.tsx` - Route page for calendar settings
|
||||||
|
- `apps/web/src/app/(portal)/settings/dashboard/calendar/calendar-settings.test.tsx` - 3 tests: source list, visibility toggle, form validation
|
||||||
|
- `apps/web/src/components/dashboard/widget-registry.tsx` - Added wireCalendarWidget() function
|
||||||
|
- `apps/web/src/app/(portal)/page.tsx` - Wired CalendarWidget into registry
|
||||||
|
- `apps/web/src/messages/de.json` - Added calendar.loading i18n key
|
||||||
|
- `apps/web/src/messages/en.json` - Added calendar.loading i18n key
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **Optimistic UI for visibility toggle:** Local state updated immediately on click, reverted on API error. Provides responsive UX without waiting for network roundtrip.
|
||||||
|
- **Auto-run connection test after source creation:** After addSource succeeds, testSource is called automatically and result displayed via connection status indicator (green check / error icon).
|
||||||
|
- **URL validation via URL constructor:** Uses `new URL()` with protocol check rather than regex for robust https-only client-side validation (T-05-14). Server-side DTO validation remains authoritative.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 2 - Missing Critical] Added calendar.loading i18n key**
|
||||||
|
- **Found during:** Task 1
|
||||||
|
- **Issue:** Widget uses `t('calendar.loading')` for loading state but key was missing from i18n files
|
||||||
|
- **Fix:** Added `calendar.loading` to both de.json and en.json
|
||||||
|
- **Files modified:** de.json, en.json
|
||||||
|
- **Committed in:** c0f2f4c (Task 1 commit)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 1 auto-fixed (1 missing critical)
|
||||||
|
**Impact on plan:** Minor i18n key addition required for correctness. No scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None - all components implemented and tested without blocking issues.
|
||||||
|
|
||||||
|
## Threat Mitigations Implemented
|
||||||
|
|
||||||
|
| Threat ID | Mitigation |
|
||||||
|
|-----------|------------|
|
||||||
|
| T-05-14 | Client-side https-only URL validation via URL constructor before form submit |
|
||||||
|
| T-05-15 | CalendarWidget only consumes /api/calendar/events; no password fields in frontend types |
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required. Calendar backend from 05-03 must be running with CALENDAR_ENCRYPTION_KEY configured.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Calendar frontend complete: widget + settings page fully wired to 05-03 backend
|
||||||
|
- Ready for Plan 05 (E2E testing / integration verification)
|
||||||
|
- Widget registry now has all four widget types wired with real components
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- All 7 created files verified present on disk
|
||||||
|
- All 4 task commits verified in git log (2d8699e, c0f2f4c, f99ff9a, 24de136)
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 05-dashboard-calendar*
|
||||||
|
*Completed: 2026-06-24*
|
||||||
Reference in New Issue
Block a user