--- 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)