From 01de2d0f9c3edf93c10847e0a30f43a34b34595f Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Mon, 16 Mar 2026 21:26:28 +0100 Subject: [PATCH] =?UTF-8?q?docs(05-01):=20complete=20calendar=20data=20lay?= =?UTF-8?q?er=20plan=20=E2=80=94=20CalendarDao,=20providers,=20l10n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 05-01-SUMMARY.md: execution results with deviations, decisions, self-check - STATE.md: current position updated to Plan 01 complete, 3 new decisions - ROADMAP.md: Phase 5 in progress (1/2 plans complete) - REQUIREMENTS.md: CAL-02 and CAL-05 marked complete --- .planning/REQUIREMENTS.md | 8 +- .planning/ROADMAP.md | 4 +- .planning/STATE.md | 36 +++-- .../phases/05-calendar-strip/05-01-SUMMARY.md | 142 ++++++++++++++++++ 4 files changed, 168 insertions(+), 22 deletions(-) create mode 100644 .planning/phases/05-calendar-strip/05-01-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 04e158e..093f6a8 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -10,10 +10,10 @@ Requirements for milestone v1.1 Calendar & Polish. Each maps to roadmap phases. ### Calendar UI - [ ] **CAL-01**: User sees a horizontal scrollable date-strip with day abbreviation (Mo, Di...) and date number per card -- [ ] **CAL-02**: User can tap a day card to see that day's tasks in a list below the strip +- [x] **CAL-02**: User can tap a day card to see that day's tasks in a list below the strip - [ ] **CAL-03**: User sees a subtle color shift at month boundaries for visual orientation - [ ] **CAL-04**: Calendar strip auto-scrolls to today on app launch -- [ ] **CAL-05**: Undone tasks carry over to the next day with a red/orange color accent marking them as overdue +- [x] **CAL-05**: Undone tasks carry over to the next day with a red/orange color accent marking them as overdue ### Task History @@ -61,10 +61,10 @@ Which phases cover which requirements. Updated during roadmap creation. | Requirement | Phase | Status | |-------------|-------|--------| | CAL-01 | Phase 5 | Pending | -| CAL-02 | Phase 5 | Pending | +| CAL-02 | Phase 5 | Complete | | CAL-03 | Phase 5 | Pending | | CAL-04 | Phase 5 | Pending | -| CAL-05 | Phase 5 | Pending | +| CAL-05 | Phase 5 | Complete | | HIST-01 | Phase 6 | Pending | | HIST-02 | Phase 6 | Pending | | SORT-01 | Phase 7 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 5f2c8fc..ce9c045 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -37,7 +37,7 @@ See `milestones/v1.0-ROADMAP.md` for full phase details. 3. On app launch the strip auto-scrolls so today's card is centered and selected by default 4. When two adjacent day cards span a month boundary, a subtle color shift or divider makes the boundary visible without extra chrome 5. Tasks that were not completed on their due date appear in subsequent days' lists with a red/orange accent marking them as overdue -**Plans:** 2 plans +**Plans:** 1/2 plans executed Plans: - [ ] 05-01-PLAN.md — Data layer: CalendarDao, CalendarDayState model, Riverpod providers, localization, DAO tests - [ ] 05-02-PLAN.md — UI: CalendarStrip, CalendarDayList, CalendarTaskRow widgets, HomeScreen replacement @@ -71,6 +71,6 @@ Plans: | 2. Rooms and Tasks | v1.0 | 5/5 | Complete | 2026-03-15 | | 3. Daily Plan and Cleanliness | v1.0 | 3/3 | Complete | 2026-03-16 | | 4. Notifications | v1.0 | 3/3 | Complete | 2026-03-16 | -| 5. Calendar Strip | v1.1 | 0/2 | Planned | - | +| 5. Calendar Strip | 1/2 | In Progress| | - | | 6. Task History | v1.1 | 0/? | Not started | - | | 7. Task Sorting | v1.1 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index e3335ee..9a4eba3 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,16 +1,16 @@ --- gsd_state_version: 1.0 -milestone: v1.1 -milestone_name: Calendar & Polish -status: ready -stopped_at: Roadmap created — ready for Phase 5 -last_updated: "2026-03-16T21:00:00.000Z" -last_activity: 2026-03-16 — Roadmap created for v1.1 (phases 5-7) +milestone: v1.0 +milestone_name: milestone +status: planning +stopped_at: Completed 05-calendar-strip 05-01-PLAN.md +last_updated: "2026-03-16T20:25:46.918Z" +last_activity: 2026-03-16 — Roadmap for v1.1 written (phases 5-7) progress: total_phases: 3 completed_phases: 0 - total_plans: 0 - completed_plans: 0 + total_plans: 2 + completed_plans: 1 percent: 0 --- @@ -26,12 +26,12 @@ See: .planning/PROJECT.md (updated 2026-03-16) ## Current Position Phase: 5 — Calendar Strip -Plan: Not started -Status: Ready to plan Phase 5 -Last activity: 2026-03-16 — Roadmap for v1.1 written (phases 5-7) +Plan: 1/2 complete (Plan 01 done) +Status: In Progress +Last activity: 2026-03-16 — Completed Phase 5 Plan 01 (CalendarDao + providers) ``` -Progress: [ ░░░░░░░░░░░░░░░░░░░░ ] 0% (0/3 phases) +Progress: [█████░░░░░] 50% (1/2 plans in Phase 5) ``` ## Performance Metrics @@ -42,6 +42,7 @@ Progress: [ ░░░░░░░░░░░░░░░░░░░░ ] 0% (0 | Plans | 13 | TBD | | LOC (lib) | 7,773 | TBD | | Tests | 89 | TBD | +| Phase 05-calendar-strip P01 | 5 | 2 tasks | 10 files | ## Accumulated Context @@ -53,6 +54,9 @@ Progress: [ ░░░░░░░░░░░░░░░░░░░░ ] 0% (0 | Phase 5 before Phase 6 and 7 | Calendar strip is the primary UI surface; history and sorting operate within or alongside it | | Phase 6 and 7 both depend on Phase 5 only | History and sorting are independent of each other — could execute in either order | | HIST-01 and HIST-02 in same phase | Data layer (HIST-01) is only 1-2 DAO additions; grouping with the UI (HIST-02) keeps the phase coherent | +| Used NotifierProvider instead of deprecated StateProvider | Riverpod 3.x removed StateProvider; NotifierProvider is the correct replacement | +| calendarDayProvider fetches overdue tasks with .first in asyncMap when isToday | Consistent with dailyPlanProvider pattern; avoids combining two streams | +| watchTasksForDate sorts alphabetically by task name | Same-day tasks have no meaningful time-based order; alpha sort is deterministic and user-friendly | ### Pending Todos @@ -60,12 +64,12 @@ None. ### Blockers/Concerns -- The existing HomeScreen (daily plan with overdue/today/upcoming) will be replaced entirely in Phase 5. Verify no other screen references the daily plan provider before deleting it, or migrate references. -- CAL-05 (overdue carry-over with color accent) requires a query that returns tasks by their original due date relative to a selected day — confirm the existing DailyPlanDao can be adapted or a new CalendarDao is needed. +- The existing HomeScreen (daily plan with overdue/today/upcoming) will be replaced entirely in Phase 5. Plan 02 will handle migrating or removing the dailyPlanProvider reference. +- CAL-05 resolved: new CalendarDao created with date-parameterized queries; overdue tasks shown only when viewing today. ## Session Continuity -Last session: 2026-03-16 -Stopped at: Roadmap created, ready for Phase 5 planning +Last session: 2026-03-16T20:25:46.916Z +Stopped at: Completed 05-calendar-strip 05-01-PLAN.md Resume file: None Next action: `/gsd:plan-phase 5` diff --git a/.planning/phases/05-calendar-strip/05-01-SUMMARY.md b/.planning/phases/05-calendar-strip/05-01-SUMMARY.md new file mode 100644 index 0000000..602c0b9 --- /dev/null +++ b/.planning/phases/05-calendar-strip/05-01-SUMMARY.md @@ -0,0 +1,142 @@ +--- +phase: 05-calendar-strip +plan: 01 +subsystem: database +tags: [drift, riverpod, dart, flutter, localization, tdd] + +# Dependency graph +requires: [] +provides: + - CalendarDao with watchTasksForDate and watchOverdueTasks date-parameterized queries + - CalendarDayState domain model with selectedDate/dayTasks/overdueTasks + - selectedDateProvider (NotifierProvider, persists while app is alive) + - calendarDayProvider (StreamProvider.autoDispose, overdue only for today) + - calendarTodayButton l10n string in ARB and generated dart files + - 11 DAO unit tests covering all query behaviors +affects: + - 05-calendar-strip plan 02 (calendar strip UI uses these providers and state model) + +# Tech tracking +tech-stack: + added: [] + patterns: + - "CalendarDao follows @DriftAccessor pattern with DatabaseAccessor" + - "Manual NotifierProvider instead of @riverpod (Riverpod 3.x pattern)" + - "StreamProvider.autoDispose with asyncMap for combining day + overdue streams" + - "TDD: failing test commit, then implementation commit" + +key-files: + created: + - lib/features/home/data/calendar_dao.dart + - lib/features/home/data/calendar_dao.g.dart + - lib/features/home/domain/calendar_models.dart + - lib/features/home/presentation/calendar_providers.dart + - test/features/home/data/calendar_dao_test.dart + modified: + - lib/core/database/database.dart + - lib/core/database/database.g.dart + - lib/l10n/app_de.arb + - lib/l10n/app_localizations.dart + - lib/l10n/app_localizations_de.dart + +key-decisions: + - "Used NotifierProvider instead of deprecated StateProvider — Riverpod 3.x removed StateProvider in favour of Notifier-based providers" + - "calendarDayProvider fetches overdue tasks with .first when isToday, keeping asyncMap pattern consistent with dailyPlanProvider" + - "watchTasksForDate sorts alphabetically by name (not by due time) — arbitrary due time on same day has no meaningful sort order" + +patterns-established: + - "CalendarDao: @DriftAccessor with join + where filter + orderBy, mapped to TaskWithRoom — same shape as DailyPlanDao" + - "Manual Notifier subclass for simple value-holding state provider (not @riverpod) to avoid code gen constraints" + +requirements-completed: [CAL-02, CAL-05] + +# Metrics +duration: 5min +completed: 2026-03-16 +--- + +# Phase 5 Plan 01: Calendar Data Layer Summary + +**CalendarDao with date-exact and overdue-before-date Drift queries, CalendarDayState model, Riverpod providers for selected date and day state, and "Heute" l10n string — full data foundation for the calendar strip UI** + +## Performance + +- **Duration:** 5 min +- **Started:** 2026-03-16T20:18:55Z +- **Completed:** 2026-03-16T20:24:12Z +- **Tasks:** 2 +- **Files modified:** 10 + +## Accomplishments +- CalendarDao registered in AppDatabase with two reactive Drift streams: `watchTasksForDate` (exact day, sorted by name) and `watchOverdueTasks` (strictly before reference date, sorted by due date) +- CalendarDayState domain model separating dayTasks and overdueTasks with isEmpty helper +- selectedDateProvider (NotifierProvider, keeps alive) + calendarDayProvider (StreamProvider.autoDispose) following existing Riverpod patterns +- 11 unit tests passing via TDD red-green cycle; full 100-test suite passes with no regressions + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: RED - CalendarDao tests** - `f5c4b49` (test) +2. **Task 1: GREEN - CalendarDao implementation** - `c666f9a` (feat) +3. **Task 2: CalendarDayState, providers, l10n** - `68ba7c6` (feat) + +## Files Created/Modified +- `lib/features/home/data/calendar_dao.dart` - CalendarDao with watchTasksForDate and watchOverdueTasks +- `lib/features/home/data/calendar_dao.g.dart` - Generated Drift mixin for CalendarDao +- `lib/features/home/domain/calendar_models.dart` - CalendarDayState model +- `lib/features/home/presentation/calendar_providers.dart` - selectedDateProvider and calendarDayProvider +- `test/features/home/data/calendar_dao_test.dart` - 11 DAO unit tests (TDD RED phase) +- `lib/core/database/database.dart` - Added CalendarDao import and registration in @DriftDatabase +- `lib/core/database/database.g.dart` - Regenerated with CalendarDao accessor +- `lib/l10n/app_de.arb` - Added calendarTodayButton: "Heute" +- `lib/l10n/app_localizations.dart` - Regenerated with calendarTodayButton getter +- `lib/l10n/app_localizations_de.dart` - Regenerated with calendarTodayButton implementation + +## Decisions Made +- **NotifierProvider instead of StateProvider:** Riverpod 3.x dropped `StateProvider` — replaced with `NotifierProvider` pattern (manual, not @riverpod) to keep consistent with the codebase's non-generated providers. +- **Overdue fetched with .first inside asyncMap:** When isToday, the overdue tasks stream's first emission is awaited inside asyncMap on the day tasks stream. This avoids combining two streams and stays consistent with the `dailyPlanProvider` pattern. +- **watchTasksForDate sorts alphabetically by name:** Tasks due on the same calendar day have no meaningful relative order by time. Alphabetical name sort gives deterministic, user-friendly ordering. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] StateProvider unavailable in Riverpod 3.x** +- **Found during:** Task 2 (calendar providers) +- **Issue:** Plan specified `StateProvider` but flutter_riverpod 3.3.1 removed StateProvider; analyzer reported `undefined_function` +- **Fix:** Replaced with `NotifierProvider` using a minimal `Notifier` subclass with a `selectDate(DateTime)` method +- **Files modified:** lib/features/home/presentation/calendar_providers.dart +- **Verification:** `flutter analyze --no-fatal-infos` reports no issues +- **Committed in:** 68ba7c6 (Task 2 commit) + +--- + +**Total deviations:** 1 auto-fixed (Rule 1 - Bug) +**Impact on plan:** Fix was required for compilation. The API surface is equivalent — consumers call `ref.watch(selectedDateProvider)` to read the date and `ref.read(selectedDateProvider.notifier).selectDate(date)` to update it. No scope creep. + +## Issues Encountered +- None beyond the StateProvider API change documented above. + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- CalendarDao, CalendarDayState, selectedDateProvider, and calendarDayProvider are all ready for consumption by Plan 02 (calendar strip UI) +- The `selectDate` method on SelectedDateNotifier is the correct way to update the selected date from the UI +- Existing dailyPlanProvider is unchanged — Plan 02 will decide whether to replace or retain it in the HomeScreen + +--- +*Phase: 05-calendar-strip* +*Completed: 2026-03-16* + +## Self-Check: PASSED + +- FOUND: lib/features/home/data/calendar_dao.dart +- FOUND: lib/features/home/domain/calendar_models.dart +- FOUND: lib/features/home/presentation/calendar_providers.dart +- FOUND: test/features/home/data/calendar_dao_test.dart +- FOUND: .planning/phases/05-calendar-strip/05-01-SUMMARY.md +- FOUND: commit f5c4b49 (test RED phase) +- FOUND: commit c666f9a (feat GREEN phase) +- FOUND: commit 68ba7c6 (feat Task 2)