docs(11-02): complete pre-populate-recurring-tasks plan — interval-window pre-population with muted UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 21:28:23 +02:00
parent 8cbe989aeb
commit 673f27ad38
4 changed files with 169 additions and 14 deletions

View File

@@ -29,9 +29,9 @@ Requirements for milestone v1.2 Polish & Task Management. Each maps to roadmap p
- [x] **TM-01**: User can check off (complete) a task on any calendar day — checkboxes are never disabled for future dates - [x] **TM-01**: User can check off (complete) a task on any calendar day — checkboxes are never disabled for future dates
- [x] **TM-02**: When completing a task on a non-due day, nextDueDate is recalculated from today (not from the original due date) - [x] **TM-02**: When completing a task on a non-due day, nextDueDate is recalculated from today (not from the original due date)
- [ ] **TM-03**: Recurring tasks are pre-populated on all applicable days within their current interval window (e.g., a weekly task shows every day in the 7-day window leading up to its due date) - [x] **TM-03**: Recurring tasks are pre-populated on all applicable days within their current interval window (e.g., a weekly task shows every day in the 7-day window leading up to its due date)
- [ ] **TM-04**: Pre-populated tasks that have already been completed in the current interval period are hidden from the calendar view - [x] **TM-04**: Pre-populated tasks that have already been completed in the current interval period are hidden from the calendar view
- [ ] **TM-05**: Pre-populated tasks not yet due have a muted visual distinction (reduced opacity) compared to due-today and overdue tasks - [x] **TM-05**: Pre-populated tasks not yet due have a muted visual distinction (reduced opacity) compared to due-today and overdue tasks
## Future Requirements ## Future Requirements

View File

@@ -36,7 +36,7 @@ See `milestones/v1.1-ROADMAP.md` for full phase details.
- [x] **Phase 8: Task Delete** - Add smart delete action to tasks — hard delete if never completed, soft delete (deactivate) if completed at least once (completed 2026-03-18) - [x] **Phase 8: Task Delete** - Add smart delete action to tasks — hard delete if never completed, soft delete (deactivate) if completed at least once (completed 2026-03-18)
- [x] **Phase 9: Task Creation UX** - Rework the frequency picker from flat preset chips to an intuitive "Every N units" interface with quick-select shortcuts (completed 2026-03-18) - [x] **Phase 9: Task Creation UX** - Rework the frequency picker from flat preset chips to an intuitive "Every N units" interface with quick-select shortcuts (completed 2026-03-18)
- [x] **Phase 10: Dead Code Cleanup** - Remove orphaned v1.0 daily plan files and verify no regressions (completed 2026-03-19) - [x] **Phase 10: Dead Code Cleanup** - Remove orphaned v1.0 daily plan files and verify no regressions (completed 2026-03-19)
- [ ] **Phase 11: Tasks Management** - Allow task checking anytime and pre-populate recurring tasks within their interval window - [x] **Phase 11: Tasks Management** - Allow task checking anytime and pre-populate recurring tasks within their interval window (completed 2026-04-03)
## Phase Details ## Phase Details
@@ -86,10 +86,10 @@ Plans:
**Goal**: Users can complete tasks on any day regardless of schedule, and recurring tasks appear on all applicable days within their interval window — making the app feel like a consistent checklist rather than a rigid scheduler **Goal**: Users can complete tasks on any day regardless of schedule, and recurring tasks appear on all applicable days within their interval window — making the app feel like a consistent checklist rather than a rigid scheduler
**Depends on**: Phase 10 **Depends on**: Phase 10
**Requirements**: TM-01, TM-02, TM-03, TM-04, TM-05 **Requirements**: TM-01, TM-02, TM-03, TM-04, TM-05
**Plans:** 1/2 plans executed **Plans:** 2/2 plans complete
Plans: Plans:
- [x] 11-01-PLAN.md — Anytime completion: remove checkbox restrictions, recalculate nextDueDate from today on non-due-day completion - [x] 11-01-PLAN.md — Anytime completion: remove checkbox restrictions, recalculate nextDueDate from today on non-due-day completion
- [ ] 11-02-PLAN.md — Pre-population: virtual task instances in provider layer, period-completion filtering, muted visual styling - [x] 11-02-PLAN.md — Pre-population: virtual task instances in provider layer, period-completion filtering, muted visual styling
**Success Criteria** (what must be TRUE): **Success Criteria** (what must be TRUE):
1. Checkboxes are always enabled on all calendar days (past, today, future) and in room task lists 1. Checkboxes are always enabled on all calendar days (past, today, future) and in room task lists
2. Completing a task on a non-due day recalculates nextDueDate from today, not the original due date 2. Completing a task on a non-due day recalculates nextDueDate from today, not the original due date
@@ -114,4 +114,4 @@ Plans:
| 8. Task Delete | v1.2 | 2/2 | Complete | 2026-03-18 | | 8. Task Delete | v1.2 | 2/2 | Complete | 2026-03-18 |
| 9. Task Creation UX | v1.2 | 1/1 | Complete | 2026-03-18 | | 9. Task Creation UX | v1.2 | 1/1 | Complete | 2026-03-18 |
| 10. Dead Code Cleanup | v1.2 | 1/1 | Complete | 2026-03-19 | | 10. Dead Code Cleanup | v1.2 | 1/1 | Complete | 2026-03-19 |
| 11. Tasks Management | v1.2 | 1/2 | In Progress| | | 11. Tasks Management | v1.2 | 2/2 | Complete | 2026-04-03 |

View File

@@ -2,14 +2,14 @@
gsd_state_version: 1.0 gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: Ready to execute status: Phase complete — ready for verification
stopped_at: Completed 11-01-PLAN.md stopped_at: Completed 11-02-PLAN.md
last_updated: "2026-03-24T08:49:28.728Z" last_updated: "2026-04-03T19:28:12.418Z"
progress: progress:
total_phases: 4 total_phases: 4
completed_phases: 3 completed_phases: 4
total_plans: 6 total_plans: 6
completed_plans: 5 completed_plans: 6
--- ---
# Project State # Project State
@@ -39,6 +39,7 @@ Plan: 2 of 2
| Phase 09-task-creation-ux P01 | 2 | 1 tasks | 4 files | | Phase 09-task-creation-ux P01 | 2 | 1 tasks | 4 files |
| Phase 10-dead-code-cleanup P01 | 5 | 2 tasks | 4 files | | Phase 10-dead-code-cleanup P01 | 5 | 2 tasks | 4 files |
| Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks P01 | 219 | 2 tasks | 4 files | | Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks P01 | 219 | 2 tasks | 4 files |
| Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks P02 | 15 | 2 tasks | 6 files |
## Accumulated Context ## Accumulated Context
@@ -56,6 +57,9 @@ Decisions archived to PROJECT.md Key Decisions table.
- [Phase 10-dead-code-cleanup]: TaskWithRoom retained in daily_plan_models.dart — actively used by calendar_dao.dart, calendar_providers.dart, and related calendar files - [Phase 10-dead-code-cleanup]: TaskWithRoom retained in daily_plan_models.dart — actively used by calendar_dao.dart, calendar_providers.dart, and related calendar files
- [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-01: Remove isFuture/canComplete restrictions — checkboxes always enabled across all UI; calendar_task_row.dart unchanged (caller was applying restriction) - [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-01: Remove isFuture/canComplete restrictions — checkboxes always enabled across all UI; calendar_task_row.dart unchanged (caller was applying restriction)
- [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-02: When completing on non-due day, use today as baseDate for nextDueDate calculation (todayStart == taskDueDay pattern) - [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-02: When completing on non-due day, use today as baseDate for nextDueDate calculation (todayStart == taskDueDay pattern)
- [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-03: Pre-population via query-time virtual instances — no schema migration
- [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-04: _subtractMonths uses total-month arithmetic to handle January-boundary year crossings correctly
- [Phase 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks]: D-05: Pre-populated tasks rendered in Demnächst section below day tasks with 0.55 Opacity
### Pending Todos ### Pending Todos
@@ -71,7 +75,7 @@ None.
## Session Continuity ## Session Continuity
Last session: 2026-03-24T08:49:28.726Z Last session: 2026-04-03T19:28:12.416Z
Stopped at: Completed 11-01-PLAN.md Stopped at: Completed 11-02-PLAN.md
Resume file: None Resume file: None
Next action: Phase 10 complete Next action: Phase 10 complete

View File

@@ -0,0 +1,151 @@
---
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*