diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 093f6a8..1a5e3b0 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -9,10 +9,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 +- [x] **CAL-01**: User sees a horizontal scrollable date-strip with day abbreviation (Mo, Di...) and date number per card - [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 +- [x] **CAL-03**: User sees a subtle color shift at month boundaries for visual orientation +- [x] **CAL-04**: Calendar strip auto-scrolls to today on app launch - [x] **CAL-05**: Undone tasks carry over to the next day with a red/orange color accent marking them as overdue ### Task History @@ -60,10 +60,10 @@ Which phases cover which requirements. Updated during roadmap creation. | Requirement | Phase | Status | |-------------|-------|--------| -| CAL-01 | Phase 5 | Pending | +| CAL-01 | Phase 5 | Complete | | CAL-02 | Phase 5 | Complete | -| CAL-03 | Phase 5 | Pending | -| CAL-04 | Phase 5 | Pending | +| CAL-03 | Phase 5 | Complete | +| CAL-04 | Phase 5 | Complete | | CAL-05 | Phase 5 | Complete | | HIST-01 | Phase 6 | Pending | | HIST-02 | Phase 6 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index ce9c045..90f7550 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -21,7 +21,7 @@ See `milestones/v1.0-ROADMAP.md` for full phase details. **v1.1 Calendar & Polish (Phases 5-7):** -- [ ] **Phase 5: Calendar Strip** - Replace the stacked daily plan home screen with a horizontal scrollable date-strip and day-task list +- [x] **Phase 5: Calendar Strip** - Replace the stacked daily plan home screen with a horizontal scrollable date-strip and day-task list (completed 2026-03-16) - [ ] **Phase 6: Task History** - Record every task completion with a timestamp and expose a per-task history view - [ ] **Phase 7: Task Sorting** - Add alphabetical, interval, and effort sort options to task lists @@ -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:** 1/2 plans executed +**Plans:** 2/2 plans complete 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 | 1/2 | In Progress| | - | +| 5. Calendar Strip | 2/2 | Complete | 2026-03-16 | - | | 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 9a4eba3..84feaeb 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,16 +2,16 @@ gsd_state_version: 1.0 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) +status: executing +stopped_at: Completed 05-calendar-strip 05-02-PLAN.md +last_updated: "2026-03-16T20:37:30.052Z" +last_activity: 2026-03-16 — Completed Phase 5 Plan 01 (CalendarDao + providers) progress: total_phases: 3 - completed_phases: 0 + completed_phases: 1 total_plans: 2 - completed_plans: 1 - percent: 0 + completed_plans: 2 + percent: 50 --- # Project State @@ -26,12 +26,12 @@ See: .planning/PROJECT.md (updated 2026-03-16) ## Current Position Phase: 5 — Calendar Strip -Plan: 1/2 complete (Plan 01 done) -Status: In Progress -Last activity: 2026-03-16 — Completed Phase 5 Plan 01 (CalendarDao + providers) +Plan: 2/2 complete (Phase 5 done) +Status: Phase Complete +Last activity: 2026-03-16 — Completed Phase 5 Plan 02 (calendar strip UI) ``` -Progress: [█████░░░░░] 50% (1/2 plans in Phase 5) +Progress: [██████████] 100% (2/2 plans in Phase 5) ``` ## Performance Metrics @@ -43,6 +43,7 @@ Progress: [█████░░░░░] 50% (1/2 plans in Phase 5) | LOC (lib) | 7,773 | TBD | | Tests | 89 | TBD | | Phase 05-calendar-strip P01 | 5 | 2 tasks | 10 files | +| Phase 05-calendar-strip P02 | 8 | 3 tasks | 9 files | ## Accumulated Context @@ -57,6 +58,8 @@ Progress: [█████░░░░░] 50% (1/2 plans in Phase 5) | 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 | +| CalendarStripController as VoidCallback holder | Avoids GlobalKey for single imperative scroll-to-today action — simpler | +| Tests use pump()+pump(Duration) instead of pumpAndSettle() | CalendarStrip animation controllers cause pumpAndSettle timeout — fixed-duration pump steps are reliable | ### Pending Todos @@ -64,12 +67,11 @@ None. ### Blockers/Concerns -- 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. +- Phase 5 complete. daily_plan_providers.dart, daily_plan_task_row.dart, and progress_card.dart are now dead code (safe to clean up in a future phase). DailyPlanDao must NOT be deleted — still used by the notification service. ## Session Continuity -Last session: 2026-03-16T20:25:46.916Z -Stopped at: Completed 05-calendar-strip 05-01-PLAN.md +Last session: 2026-03-16T20:37:30.050Z +Stopped at: Completed 05-calendar-strip 05-02-PLAN.md Resume file: None Next action: `/gsd:plan-phase 5` diff --git a/.planning/phases/05-calendar-strip/05-02-SUMMARY.md b/.planning/phases/05-calendar-strip/05-02-SUMMARY.md new file mode 100644 index 0000000..858a72f --- /dev/null +++ b/.planning/phases/05-calendar-strip/05-02-SUMMARY.md @@ -0,0 +1,148 @@ +--- +phase: 05-calendar-strip +plan: 02 +subsystem: ui +tags: [flutter, riverpod, dart, intl, animation, calendar] + +# Dependency graph +requires: + - phase: 05-calendar-strip plan 01 + provides: CalendarDao, CalendarDayState, selectedDateProvider, calendarDayProvider +provides: + - CalendarStrip widget (181-day horizontal scroll, German abbreviations, month boundary labels) + - CalendarTaskRow widget (task name + room tag chip + checkbox, no relative date) + - CalendarDayList widget (loading/empty/celebration/tasks states, overdue section today-only) + - Rewritten HomeScreen composing strip + day list with floating Today button + - totalTaskCount field on CalendarDayState and getTaskCount() on CalendarDao + - Updated home screen and app shell tests for new calendar providers +affects: + - 06-task-history (uses CalendarStrip as the navigation surface) + - 07-task-sorting (task display within CalendarDayList) + +# Tech tracking +tech-stack: + added: [] + patterns: + - "CalendarStrip uses CalendarStripController (simple VoidCallback holder) for parent-to-child imperative scrolling" + - "CalendarDayList manages _completingTaskIds Set for slide-out animation the same way as old HomeScreen" + - "Tests use tester.pump() + pump(Duration) instead of pumpAndSettle() to avoid timeout from animation controllers" + +key-files: + created: + - lib/features/home/presentation/calendar_strip.dart + - lib/features/home/presentation/calendar_task_row.dart + - lib/features/home/presentation/calendar_day_list.dart + modified: + - lib/features/home/presentation/home_screen.dart + - lib/features/home/domain/calendar_models.dart + - lib/features/home/data/calendar_dao.dart + - lib/features/home/presentation/calendar_providers.dart + - test/features/home/presentation/home_screen_test.dart + - test/shell/app_shell_test.dart + +key-decisions: + - "CalendarStripController holds a VoidCallback instead of using GlobalKey — simpler for this one-direction imperative call" + - "totalTaskCount fetched via getTaskCount() inside calendarDayProvider asyncMap — avoids a third stream, consistent with existing pattern" + - "Tests use pump() + pump(Duration) instead of pumpAndSettle() — CalendarStrip's ScrollController postFrameCallback and animation controllers cause pumpAndSettle to timeout" + - "month label height always reserved with SizedBox(height:16) on non-boundary cards — prevents strip height jitter as you scroll through months" + +patterns-established: + - "ImperativeController pattern: class with VoidCallback? _action; void action() => _action?.call(); widget sets _action in initState" + - "CalendarDayList state machine: first-run (totalTaskCount==0) > celebration (isToday + isEmpty + totalTaskCount>0) > emptyDay (isEmpty) > hasTasks" + +requirements-completed: [CAL-01, CAL-03, CAL-04, CAL-05] + +# Metrics +duration: 8min +completed: 2026-03-16 +--- + +# Phase 5 Plan 02: Calendar Strip UI Summary + +**Horizontal 181-day calendar strip with German day cards, month boundaries, floating Today button, and day task list with overdue section — replaces the stacked daily-plan HomeScreen** + +## Performance + +- **Duration:** 8 min +- **Started:** 2026-03-16T20:27:39Z +- **Completed:** 2026-03-16T20:35:55Z +- **Tasks:** 3 (Task 3 auto-approved in auto-advance mode) +- **Files modified:** 9 + +## Accomplishments +- CalendarStrip: horizontal ListView with 181 day cards (90 past + today + 90 future), German abbreviations via `DateFormat('E', 'de')`, selected card highlighted (stronger primaryContainer + border), today card with bold text + 2px accent underline, month boundary wider gap + month label, auto-scrolls to center today on init, CalendarStripController enables Today-button → strip communication +- CalendarDayList: five-state machine (loading, first-run empty, celebration, empty day, has tasks) with overdue section when viewing today, slide-out completion animation reusing the same SizeTransition + SlideTransition pattern from the old HomeScreen +- CalendarTaskRow: simplified from DailyPlanTaskRow — no relative date, name + room chip + checkbox, coral text when isOverdue +- HomeScreen rewritten: Stack with Column(CalendarStrip + Expanded(CalendarDayList)) and conditionally-visible FloatingActionButton.extended for "Heute" navigation +- Added totalTaskCount to CalendarDayState and getTaskCount() SELECT COUNT to CalendarDao for first-run vs. celebration disambiguation +- Updated 2 test files (home_screen_test.dart, app_shell_test.dart) to test new providers; test count grew from 100 to 101 + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Build CalendarStrip, CalendarTaskRow, CalendarDayList widgets** - `f718ee8` (feat) +2. **Task 2: Replace HomeScreen with calendar composition** - `88ef248` (feat) +3. **Task 3: Verify calendar strip visually** - auto-approved (checkpoint:human-verify in auto-advance mode) + +## Files Created/Modified +- `lib/features/home/presentation/calendar_strip.dart` - 181-day horizontal scrollable strip with German abbreviations, today/selected highlights, month boundary labels +- `lib/features/home/presentation/calendar_task_row.dart` - Task row: name + room chip + checkbox, isOverdue coral styling, no relative date +- `lib/features/home/presentation/calendar_day_list.dart` - Day task list with 5-state machine, overdue section (today only), slide-out animation +- `lib/features/home/presentation/home_screen.dart` - Rewritten: CalendarStrip + CalendarDayList + floating Today FAB +- `lib/features/home/domain/calendar_models.dart` - Added totalTaskCount field +- `lib/features/home/data/calendar_dao.dart` - Added getTaskCount() query +- `lib/features/home/presentation/calendar_providers.dart` - calendarDayProvider now fetches and includes totalTaskCount +- `test/features/home/presentation/home_screen_test.dart` - Rewritten for CalendarDayState / calendarDayProvider +- `test/shell/app_shell_test.dart` - Updated from dailyPlanProvider to calendarDayProvider + +## Decisions Made +- **CalendarStripController as simple VoidCallback holder:** Avoids GlobalKey complexity for a single imperative scroll-to-today action; parent holds controller, widget registers its implementation in initState. +- **totalTaskCount fetched in asyncMap:** Consistent with existing calendarDayProvider asyncMap pattern; avoids a third reactive stream just for a count. +- **Tests use pump() + pump(Duration) instead of pumpAndSettle():** ScrollController's postFrameCallback animation and _completingTaskIds AnimationController keep the tester busy indefinitely; fixed-duration pump steps are reliable. +- **Month label height always reserved:** Non-boundary cards get `SizedBox(height: 16)` to match the label row height — prevents strip height from changing as you scroll across month edges. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Updated existing tests broken by the HomeScreen rewrite** +- **Found during:** Task 2 verification (flutter test) +- **Issue:** `home_screen_test.dart` and `app_shell_test.dart` both imported `dailyPlanProvider` and `DailyPlanState` and used `pumpAndSettle()`, which now times out because CalendarStrip animation controllers never settle +- **Fix:** Rewrote both test files to use `calendarDayProvider`/`CalendarDayState` and replaced `pumpAndSettle()` with `pump() + pump(Duration(milliseconds: 500))`; updated all assertions to match new UI (removed progress card / tomorrow section assertions, added strip-visible assertion) +- **Files modified:** test/features/home/presentation/home_screen_test.dart, test/shell/app_shell_test.dart +- **Verification:** `flutter test` — 101 tests all pass; `flutter analyze --no-fatal-infos` — zero issues +- **Committed in:** f718ee8 (Task 1 commit, as tests were fixed alongside widget creation) + +--- + +**Total deviations:** 1 auto-fixed (Rule 1 - Bug) +**Impact on plan:** Required to maintain working test suite. The new tests cover the same behaviors (empty state, overdue section, celebration, checkboxes) but against the calendar API. No scope creep. + +## Issues Encountered +- None beyond the test migration documented above. + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- HomeScreen is fully replaced; CalendarStrip and CalendarDayList are composable widgets ready for Phase 6/7 integration +- The old daily_plan_providers.dart, daily_plan_task_row.dart, and progress_card.dart are now dead code; safe to clean up in a future phase +- DailyPlanDao is still used by the notification service and must NOT be deleted + +--- +*Phase: 05-calendar-strip* +*Completed: 2026-03-16* + +## Self-Check: PASSED + +- FOUND: lib/features/home/presentation/calendar_strip.dart +- FOUND: lib/features/home/presentation/calendar_task_row.dart +- FOUND: lib/features/home/presentation/calendar_day_list.dart +- FOUND: lib/features/home/presentation/home_screen.dart (rewritten) +- FOUND: lib/features/home/domain/calendar_models.dart (updated) +- FOUND: lib/features/home/data/calendar_dao.dart (updated) +- FOUND: lib/features/home/presentation/calendar_providers.dart (updated) +- FOUND: .planning/phases/05-calendar-strip/05-02-SUMMARY.md +- FOUND: commit f718ee8 (Task 1) +- FOUND: commit 88ef248 (Task 2)