From d3e8e6400a59f99a5a073c2295dcaac015a64720 Mon Sep 17 00:00:00 2001 From: Schalli Date: Sat, 27 Jun 2026 17:06:04 +0200 Subject: [PATCH] docs(07-06): complete SMTP settings UI plan --- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 19 +-- .../07-dkv-fleet-module/07-06-SUMMARY.md | 123 ++++++++++++++++++ 3 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 .planning/phases/07-dkv-fleet-module/07-06-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 6d86e24..de4b748 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -19,7 +19,7 @@ Decimal phases appear between their surrounding integers in numeric order. - [ ] **Phase 4: Marketplace & Portal Navigation** - Module catalog, licensing, activation, and sidebar integration - [x] **Phase 5: Dashboard & Calendar** - Configurable widget grid with drag-and-drop, core widgets, and calendar integration (completed 2026-06-24) - [ ] **Phase 6: Desktop Client & CI/CD** - Tauri wrapper for Windows/Linux and automated Gitea integration -- [ ] **Phase 7: DKV Fleet Module** - Automated DKV invoice processing via email monitoring, PDF parsing, and Excel export with driver mapping +- [x] **Phase 7: DKV Fleet Module** - Automated DKV invoice processing via email monitoring, PDF parsing, and Excel export with driver mapping (completed 2026-06-27) ## Phase Details @@ -239,7 +239,7 @@ Decimal phases appear between their surrounding integers in numeric order. - [x] 07-04-PLAN.md -- Pipeline integration: DkvService orchestration, dynamic scheduler, DkvController REST, module registry seed, i18n keys (DKV-01/03/04/05) - [x] 07-05-PLAN.md -- Module frontend: dkv-api client, main page (history + export download + "Jetzt prüfen"), inbox settings form, vehicle CRUD + CSV import (DKV-01/03/04) -- [ ] 07-06-PLAN.md -- SMTP settings frontend: settings-api client, SMTP config form + connection test, settings-sidebar "Allgemein" category (DKV-05) +- [x] 07-06-PLAN.md -- SMTP settings frontend: settings-api client, SMTP config form + connection test, settings-sidebar "Allgemein" category (DKV-05) **UI hint**: yes @@ -256,4 +256,4 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 | 4. Marketplace & Portal Navigation | 0/4 | Not started | - | | 5. Dashboard & Calendar | 5/5 | Complete | 2026-06-24 | | 6. Desktop Client & CI/CD | 2/3 | In Progress| | -| 7. DKV Fleet Module | 5/6 | In Progress| | +| 7. DKV Fleet Module | 6/6 | Complete | 2026-06-27 | diff --git a/.planning/STATE.md b/.planning/STATE.md index 46849ea..eba85ed 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -4,14 +4,14 @@ milestone: v1.0 milestone_name: milestone status: executing stopped_at: Phase 07 Plan 05 complete (DKV Fleet Module Frontend) -last_updated: "2026-06-26T22:41:27.000Z" -last_activity: 2026-06-26 -- Phase 07 Plan 05 completed (DKV frontend — dkv-api client + 3 UI surfaces) +last_updated: "2026-06-27T15:05:48.000Z" +last_activity: 2026-06-27 -- Phase 07 execution started progress: total_phases: 7 - completed_phases: 5 + completed_phases: 6 total_plans: 30 - completed_plans: 26 - percent: 93 + completed_plans: 29 + percent: 86 --- # Project State @@ -26,9 +26,9 @@ See: .planning/PROJECT.md (updated 2026-06-18) ## Current Position Phase: 07 (dkv-fleet-module) — EXECUTING -Plan: 6 of 6 -Status: Executing Phase 07 (Plan 05 complete) -Last activity: 2026-06-26 -- Phase 07 Plan 05 completed (DKV frontend surfaces A + B) +Plan: 2 of 6 +Status: Ready to execute +Last activity: 2026-06-27 -- Phase 07 execution started Progress: [█████████░] 93% @@ -63,6 +63,7 @@ Progress: [█████████░] 93% | Phase 07-dkv-fleet-module P03 | 5min | 4 tasks | 8 files | | Phase 07-dkv-fleet-module P04 | 7min | 3 tasks | 8 files | | Phase 07-dkv-fleet-module P05 | 8min | 3 tasks | 11 files | +| Phase 07-dkv-fleet-module P06 | 5min | 2 tasks | 7 files | ## Accumulated Context @@ -137,6 +138,6 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-06-26T22:41:27.000Z +Last session: 2026-06-27T15:05:47.993Z Stopped at: Phase 07 Plan 05 complete (DKV Fleet Module Frontend) Resume file: .planning/phases/07-dkv-fleet-module/07-06-PLAN.md diff --git a/.planning/phases/07-dkv-fleet-module/07-06-SUMMARY.md b/.planning/phases/07-dkv-fleet-module/07-06-SUMMARY.md new file mode 100644 index 0000000..0cb3b09 --- /dev/null +++ b/.planning/phases/07-dkv-fleet-module/07-06-SUMMARY.md @@ -0,0 +1,123 @@ +--- +phase: 07-dkv-fleet-module +plan: 06 +subsystem: dkv-smtp-settings-ui +tags: [dkv, nextjs, react, settings, smtp, tdd, api-client, i18n] +dependency_graph: + requires: [SettingsController REST surface (07-03), settings i18n keys (07-04), CalendarSourceForm pattern (05-02)] + provides: [settings-api.ts typed client, SmtpSettingsForm (Surface C), /settings/general/smtp page, SettingsSidebar Allgemein category] + affects: + - apps/web/src/lib/settings-api.ts + - apps/web/src/components/settings/smtp-settings-form.tsx + - apps/web/src/app/(portal)/settings/general/smtp/page.tsx + - apps/web/src/app/(portal)/settings/general/smtp/smtp-settings.test.tsx + - apps/web/src/components/settings/settings-sidebar.tsx + - apps/web/src/messages/de.json + - apps/web/src/messages/en.json +tech_stack: + added: [] + patterns: + - "T-07-17 password-never-prefilled: fetchSmtp returns hasPassword boolean; password state always starts as ''; only sent when user types" + - "T-07-19 XSS: all backend strings via React text nodes; no dangerouslySetInnerHTML" + - "test feedback auto-clear: setTimeout 6000ms stored in useRef; cleared on unmount via useEffect cleanup" + - "TDD RED/GREEN: smtp-settings.test.tsx committed before SmtpSettingsForm exists; all 5 tests pass after GREEN" + - "aria-hidden* removed from required labels: getByLabelText requires clean label text (aria-hidden child spans break text matching)" +key_files: + created: + - apps/web/src/lib/settings-api.ts + - apps/web/src/components/settings/smtp-settings-form.tsx + - apps/web/src/app/(portal)/settings/general/smtp/page.tsx + - apps/web/src/app/(portal)/settings/general/smtp/smtp-settings.test.tsx + modified: + - apps/web/src/components/settings/settings-sidebar.tsx + - apps/web/src/messages/de.json + - apps/web/src/messages/en.json +decisions: + - "Required-field asterisks omitted from label text: required attribute on inputs handles HTML5 validation; asterisks in labels break getByLabelText in @testing-library" + - "testFeedback auto-clear via useRef>: ref allows cleanup on unmount without extra state; timer restarted on each test click" + - "settings-api.ts returns null for 404 on GET /settings/smtp: allows forms to start empty when no config row exists yet" + - "SettingsSidebar Allgemein section uses identical link classes to Dashboard section: both sections share same active/inactive/aria-current pattern" +metrics: + duration: 5min + completed: "2026-06-27T15:04:29Z" + tasks: 2 + files_created: 4 + files_modified: 3 +--- + +# Phase 07 Plan 06: SMTP Settings UI (Surface C) — Summary + +Settings API client (`settings-api.ts`) and SMTP configuration UI delivered: Surface C form (`SmtpSettingsForm`) with show/hide password toggle, connection-test feedback with 6-second auto-clear, and the `/settings/general/smtp` route. SettingsSidebar extended with an "Allgemein" category linking to the SMTP page — placed above the existing Dashboard section. DKV-05 UI complete. 5 Vitest tests covering load, save, test success/failure, and password toggle pass after TDD RED→GREEN cycle. + +## Tasks Completed + +| Task | Name | Commit | Key Files | +|------|------|--------|-----------| +| 1 (RED) | Failing SMTP settings form tests | a96d79a | smtp-settings.test.tsx | +| 1 (GREEN) | settings-api client + SmtpSettingsForm + SMTP page | fd2dda6 | settings-api.ts, smtp-settings-form.tsx, smtp/page.tsx, de.json, en.json | +| 2 | Extend SettingsSidebar with Allgemein > SMTP | 75aec38 | settings-sidebar.tsx | + +## Architecture Notes + +### Test Feedback Auto-Clear + +The `testFeedback` state is set to `{ type: 'loading', message }` immediately on test click, then updated to success/error after `testSmtp()` resolves. A `setTimeout(() => setTestFeedback(null), 6000)` auto-clears the feedback. The timer handle is stored in a `useRef` so it can be: +1. Cancelled on re-click (prevents stale clear from a previous click) +2. Cleaned up on unmount via a `useEffect` return function + +### Password Never Pre-Filled (T-07-17) + +`fetchSmtp()` returns `SmtpConfig` with `hasPassword: boolean` but no password value. The form always initializes `password: ''`. On load success, `password` stays `''`. The password is only included in `saveSmtp` / `testSmtp` payloads when `form.password !== ''` (user has typed something). + +### SettingsSidebar Extension + +The new "Allgemein" section is inserted before the existing `
` Dashboard category block. It uses the identical link class string (`bg-sidebar-accent text-sidebar-accent-foreground font-medium` for active, `text-sidebar-foreground hover:bg-muted` for inactive) and the same `aria-current="page"` pattern. The `isActive` helper's `pathname.startsWith` branch handles `/settings/general/smtp` automatically. + +### TDD Gate Compliance + +- RED gate commit: `a96d79a` ✓ (`test(07-06): add failing SMTP settings form tests`) +- GREEN gate commit: `fd2dda6` ✓ (`feat(07-06): settings-api client + SmtpSettingsForm + SMTP page`) +- Tests: 5/5 passed ✓ + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Required-field asterisks in label text broke getByLabelText** +- **Found during:** Task 1 GREEN phase (first test run — 2/5 tests failed) +- **Issue:** Initial form implementation used `{t('smtp.host')} *` inside `