Archive v1.1 Calendar & Polish milestone artifacts (roadmap, requirements, phase directories) to milestones/. Evolve PROJECT.md with validated requirements and new key decisions. Update RETROSPECTIVE.md with v1.1 section and cross-milestone trends. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
143 lines
7.0 KiB
Markdown
143 lines
7.0 KiB
Markdown
---
|
|
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<AppDatabase>"
|
|
- "Manual NotifierProvider<SelectedDateNotifier, DateTime> 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<SelectedDateNotifier, DateTime> 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<SelectedDateNotifier, DateTime>` 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<DateTime>` but flutter_riverpod 3.3.1 removed StateProvider; analyzer reported `undefined_function`
|
|
- **Fix:** Replaced with `NotifierProvider<SelectedDateNotifier, DateTime>` 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)
|