152 lines
7.9 KiB
Markdown
152 lines
7.9 KiB
Markdown
---
|
|
phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks
|
|
plan: 02
|
|
subsystem: ui, database, domain
|
|
tags: [flutter, drift, riverpod, pre-population, recurring-tasks, calendar, interval-window]
|
|
|
|
# Dependency graph
|
|
requires:
|
|
- phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks
|
|
plan: 11-01
|
|
provides: Always-enabled checkboxes and today-base completeTask behavior
|
|
|
|
provides:
|
|
- watchAllActiveRecurringTasks and watchAllActiveRecurringTasksInRoom DAO queries
|
|
- watchCompletionsInRange DAO query for period-completion filtering
|
|
- CalendarDayState.prePopulatedTasks field
|
|
- _isInCurrentIntervalWindow and _calculatePreviousDueDate pre-population helpers
|
|
- calendarDayProvider and roomCalendarDayProvider pre-population logic
|
|
- "Demnächst" section with 0.55 opacity rendering in CalendarDayList
|
|
|
|
affects:
|
|
- Home screen calendar day view (pre-populated tasks now visible)
|
|
- Room-scoped calendar view (same pre-population logic)
|
|
- Celebration state (now checks prePopulatedTasks.isEmpty too)
|
|
|
|
# Tech tracking
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "Interval window pre-population: query-time virtual instances, no schema migration"
|
|
- "Period-completion filtering: watchCompletionsInRange excludes already-completed tasks"
|
|
- "Total-month arithmetic for _subtractMonths: avoids year-boundary bugs with negative months"
|
|
- "0.55 opacity for pre-populated task rows via Opacity widget wrapper"
|
|
|
|
key-files:
|
|
created: []
|
|
modified:
|
|
- lib/features/home/data/calendar_dao.dart
|
|
- lib/features/home/domain/calendar_models.dart
|
|
- lib/features/home/presentation/calendar_providers.dart
|
|
- lib/features/home/presentation/calendar_day_list.dart
|
|
- lib/features/home/presentation/calendar_task_row.dart
|
|
- test/features/home/data/calendar_dao_test.dart
|
|
|
|
key-decisions:
|
|
- "D-03: Pre-population via query-time virtual instances — no schema migration, no stored virtual rows"
|
|
- "D-04: _subtractMonths uses total-month arithmetic (year*12+month-1) to correctly handle January-boundary crossings"
|
|
- "D-05: Pre-populated tasks rendered in 'Demnächst' section below day tasks with 0.55 Opacity"
|
|
- "D-06: Celebration state now includes prePopulatedTasks.isEmpty — pre-populated tasks prevent celebration"
|
|
|
|
patterns-established:
|
|
- "Interval window: selected date AFTER previousDue (exclusive) AND BEFORE nextDueDate (exclusive)"
|
|
- "Period completion filter: watchCompletionsInRange(taskId, prevDue, nextDue+1day)"
|
|
- "Muted pre-population UI: Opacity(0.55) wrapping ListTile, isPrePopulated flag propagated through widget tree"
|
|
|
|
requirements-completed:
|
|
- TM-03
|
|
- TM-04
|
|
- TM-05
|
|
|
|
# Metrics
|
|
duration: ~15min
|
|
completed: 2026-04-03
|
|
---
|
|
|
|
# Phase 11 Plan 02: Pre-populate Recurring Tasks on Interval Window Summary
|
|
|
|
**Interval-window pre-population via query-time virtual instances with period-completion filtering and 0.55 opacity muted visual distinction**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** ~15 min
|
|
- **Started:** 2026-04-03
|
|
- **Completed:** 2026-04-03
|
|
- **Tasks:** 2
|
|
- **Files modified:** 6
|
|
|
|
## Accomplishments
|
|
|
|
- Added `watchAllActiveRecurringTasks()` and `watchAllActiveRecurringTasksInRoom(roomId)` to `CalendarDao` — fetch all active tasks for pre-population source data
|
|
- Added `watchCompletionsInRange(taskId, start, end)` to `CalendarDao` — check if a task was completed in the current interval period (prevents re-showing completed tasks)
|
|
- Extended `CalendarDayState` with `prePopulatedTasks` field (default empty for backward compatibility); updated `isEmpty` getter to include `prePopulatedTasks.isEmpty`
|
|
- Added `_isInCurrentIntervalWindow()` helper: determines if a task's current interval window includes `selectedDate` (selected is after previousDue and before nextDueDate)
|
|
- Added `_calculatePreviousDueDate()` helper: reverse-calculates start of current interval window by subtracting one interval
|
|
- Rewrote `calendarDayProvider` and `roomCalendarDayProvider` to combine three streams: due-today, overdue, and pre-populated virtual instances with period-completion exclusion
|
|
- Added `isPrePopulated` parameter to `CalendarTaskRow` with `Opacity(0.55)` wrapper for muted visual style
|
|
- Rendered "Demnächst" section in `CalendarDayList` below day tasks, with muted section header and `isPrePopulated: true` rows
|
|
- Added 9 new DAO tests for `watchAllActiveRecurringTasks`, `watchAllActiveRecurringTasksInRoom`, `watchCompletionsInRange`
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically:
|
|
|
|
1. **Task 1: DAO queries, CalendarDayState model, pre-population provider** - `9a67c51` (feat)
|
|
2. **Task 2: UI rendering with muted visual distinction** - `8cbe989` (feat)
|
|
|
|
## Files Created/Modified
|
|
|
|
- `lib/features/home/data/calendar_dao.dart` — Added `watchAllActiveRecurringTasks()`, `watchAllActiveRecurringTasksInRoom()`, `watchCompletionsInRange()`
|
|
- `lib/features/home/domain/calendar_models.dart` — Added `prePopulatedTasks` field with default empty, updated `isEmpty`
|
|
- `lib/features/home/presentation/calendar_providers.dart` — Added `_isInCurrentIntervalWindow`, `_calculatePreviousDueDate`, `_subtractMonths` helpers; rewrote both providers with pre-population logic; added `IntervalType` and `database.dart` imports
|
|
- `lib/features/home/presentation/calendar_day_list.dart` — Added "Demnächst" section, updated `_buildAnimatedTaskRow` with `isPrePopulated`, updated `_CompletingTaskRow`, updated celebration check, updated cleanup loop
|
|
- `lib/features/home/presentation/calendar_task_row.dart` — Added `isPrePopulated` parameter and `Opacity(0.55)` wrapper
|
|
- `test/features/home/data/calendar_dao_test.dart` — Added 9 tests across 3 new test groups; added `drift/drift.dart` import for `Value`
|
|
|
|
## Decisions Made
|
|
|
|
- Pre-population uses query-time virtual instances — no schema migration, no stored virtual rows. Provider layer computes which tasks appear on a given day by checking their interval window.
|
|
- `_subtractMonths` uses total-month arithmetic (`year*12 + month - 1 - months`) instead of the plan's proposed formula, which had a year-boundary bug for months <= 0 (e.g. January - 1 month would incorrectly stay in the same year with Dart's truncation division).
|
|
- Celebration state updated to check `prePopulatedTasks.isEmpty` — a day with only pre-populated tasks does not show the celebration screen (tasks still need doing).
|
|
|
|
## Deviations from Plan
|
|
|
|
### Auto-fixed Issues
|
|
|
|
**1. [Rule 1 - Bug] Fixed _subtractMonths year-boundary arithmetic**
|
|
|
|
- **Found during:** Task 1
|
|
- **Issue:** The plan's proposed `_subtractMonths` formula used `(targetMonth - 1) ~/ 12` for year calculation. In Dart, `~/` is truncation-toward-zero division, so `(-1) ~/ 12 = 0` (not `-1`). This means subtracting 1 month from January 2026 would produce year 2026 instead of 2025.
|
|
- **Fix:** Replaced with total-month arithmetic: `totalMonths = date.year * 12 + (date.month - 1) - months`, then `targetYear = totalMonths ~/ 12`, `normalizedMonth = (totalMonths % 12) + 1`. This is always correct for any combination of year and months.
|
|
- **Files modified:** `lib/features/home/presentation/calendar_providers.dart`
|
|
- **Commit:** `9a67c51`
|
|
|
|
## Known Stubs
|
|
|
|
None.
|
|
|
|
## User Setup Required
|
|
|
|
None — no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
|
|
- Pre-population of recurring tasks fully implemented
|
|
- Phase 11 (Issue #3) complete — both plans executed
|
|
- No blockers
|
|
|
|
## 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: lib/features/home/presentation/calendar_day_list.dart
|
|
- FOUND: lib/features/home/presentation/calendar_task_row.dart
|
|
- FOUND: test/features/home/data/calendar_dao_test.dart
|
|
- FOUND: commit 9a67c51 (Task 1 - DAO queries + provider logic)
|
|
- FOUND: commit 8cbe989 (Task 2 - UI rendering)
|
|
|
|
---
|
|
*Phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks*
|
|
*Completed: 2026-04-03*
|