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>
15 KiB
phase, verified, status, score, human_verification
| phase | verified | status | score | human_verification | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-calendar-strip | 2026-03-16T21:00:00Z | human_needed | 10/10 must-haves verified |
|
Phase 5: Calendar Strip Verification Report
Phase Goal: Users navigate their tasks through a horizontal date-strip that replaces the stacked daily plan, seeing today's tasks by default and any day's tasks on tap Verified: 2026-03-16T21:00:00Z Status: human_needed — all automated checks pass; 6 visual/interactive behaviors need human confirmation Re-verification: No — initial verification
Goal Achievement
Observable Truths
| # | Truth | Status | Evidence |
|---|---|---|---|
| 1 | Home screen shows a horizontal scrollable strip of day cards with German abbreviation (Mo, Di...) and date number | VERIFIED | calendar_strip.dart L265: DateFormat('E', 'de').format(date) produces German abbreviations; 181-card ListView.builder scroll direction horizontal |
| 2 | Tapping a day card updates the task list below to show that day's tasks | VERIFIED | _onCardTapped calls ref.read(selectedDateProvider.notifier).selectDate(tappedDate); CalendarDayList watches calendarDayProvider which watches selectedDateProvider |
| 3 | On app launch the strip auto-scrolls so today's card is centered | VERIFIED | initState calls WidgetsBinding.instance.addPostFrameCallback → _animateToToday() which calls _scrollController.animateTo(..., duration: 200ms, curve: Curves.easeOut) |
| 4 | A subtle wider gap and month label appears at month boundaries | VERIFIED | _kMonthBoundaryGap = 16.0 vs _kCardMargin = 4.0; _isFirstOfMonth triggers DateFormat('MMM', 'de').format(date) text label; non-boundary cards reserve SizedBox(height: 16) to prevent jitter |
| 5 | Overdue tasks appear in a separate coral-accented section when viewing today | VERIFIED | calendarDayProvider fetches watchOverdueTasks only when isToday; _buildTaskList renders a coral-colored "Uberfaellig" header via _overdueColor = Color(0xFFE07A5F) when state.overdueTasks.isNotEmpty |
| 6 | Overdue tasks do NOT appear when viewing past or future days | VERIFIED | calendarDayProvider: isToday guard — past/future sets overdueTasks = const []; 101-test suite includes does not show overdue section for non-today date test passing |
| 7 | Completing a task via checkbox triggers slide-out animation | VERIFIED | _CompletingTaskRow in calendar_day_list.dart implements SizeTransition + SlideTransition (300ms, Curves.easeInOut); _onTaskCompleted adds to _completingTaskIds and calls taskActionsProvider.notifier.completeTask |
| 8 | Floating Today button appears when scrolled away from today, hidden when today is visible | VERIFIED | CalendarStrip.onTodayVisibilityChanged callback drives _showTodayButton in HomeScreen; _onScroll computes viewport bounds vs today card position |
| 9 | First-run empty state (no rooms/tasks) still shows the create-room prompt | VERIFIED | CalendarDayList._buildFirstRunEmpty shows checklist icon + l10n.dailyPlanNoTasks + l10n.homeEmptyAction FilledButton.tonal navigating to /rooms; gated by totalTaskCount == 0 |
| 10 | Celebration state shows when all tasks for the selected day are done | VERIFIED | _buildCelebration renders Icons.celebration_outlined + dailyPlanAllClearTitle + dailyPlanAllClearMessage; triggered by isToday && dayTasks.isEmpty && overdueTasks.isEmpty && totalTaskCount > 0 |
Score: 10/10 truths verified
Required Artifacts
Plan 01 Artifacts
| Artifact | Expected | Lines | Status | Details |
|---|---|---|---|---|
lib/features/home/data/calendar_dao.dart |
Date-parameterized task queries | 87 | VERIFIED | watchTasksForDate, watchOverdueTasks, getTaskCount all implemented; @DriftAccessor(tables: [Tasks, Rooms, TaskCompletions]) annotation present |
lib/features/home/data/calendar_dao.g.dart |
Generated Drift mixin | 25 | VERIFIED | _$CalendarDaoMixin generated, part of calendar_dao.dart |
lib/features/home/domain/calendar_models.dart |
CalendarDayState model | 25 | VERIFIED | CalendarDayState with selectedDate, dayTasks, overdueTasks, totalTaskCount, isEmpty getter |
lib/features/home/presentation/calendar_providers.dart |
Riverpod providers | 69 | VERIFIED | selectedDateProvider (NotifierProvider), calendarDayProvider (StreamProvider.autoDispose) with overdue-today-only logic |
test/features/home/data/calendar_dao_test.dart |
DAO unit tests (min 50 lines) | 286 | VERIFIED | 11 tests: 5 for watchTasksForDate, 6 for watchOverdueTasks; all pass |
Plan 02 Artifacts
| Artifact | Expected | Lines | Status | Details |
|---|---|---|---|---|
lib/features/home/presentation/calendar_strip.dart |
Horizontal scrollable date strip (min 100 lines) | 348 | VERIFIED | 181-card ListView, German abbreviations, CalendarStripController, today-visibility callback, month boundary labels |
lib/features/home/presentation/calendar_day_list.dart |
Day task list with states (min 80 lines) | 310 | VERIFIED | 5-state machine (loading/first-run/celebration/empty/tasks), overdue section, _CompletingTaskRow animation |
lib/features/home/presentation/calendar_task_row.dart |
Task row (min 30 lines) | 69 | VERIFIED | Name + room chip + checkbox; isOverdue coral styling; no relative date |
lib/features/home/presentation/home_screen.dart |
Rewritten HomeScreen (min 40 lines) | 69 | VERIFIED | Stack with Column(CalendarStrip + CalendarDayList) + conditional floating FAB |
Key Link Verification
Plan 01 Links
| From | To | Via | Status | Details |
|---|---|---|---|---|
calendar_dao.dart |
database.dart |
CalendarDao registered in @DriftDatabase daos | WIRED | database.dart L49: daos: [RoomsDao, TasksDao, DailyPlanDao, CalendarDao]; database.g.dart L1249: late final CalendarDao calendarDao = CalendarDao(this as AppDatabase) |
calendar_providers.dart |
calendar_dao.dart |
Provider reads CalendarDao from AppDatabase via db.calendarDao |
WIRED | calendar_providers.dart L46: db.calendarDao.watchTasksForDate(selectedDate); L53–54: db.calendarDao.watchOverdueTasks(selectedDate).first; L60: db.calendarDao.getTaskCount() |
Plan 02 Links
| From | To | Via | Status | Details |
|---|---|---|---|---|
home_screen.dart |
calendar_strip.dart |
HomeScreen composes CalendarStrip | WIRED | home_screen.dart L37: CalendarStrip(controller: _stripController, ...) |
home_screen.dart |
calendar_day_list.dart |
HomeScreen composes CalendarDayList | WIRED | home_screen.dart L43: const Expanded(child: CalendarDayList()) |
calendar_strip.dart |
calendar_providers.dart |
Strip reads/writes selectedDateProvider | WIRED | calendar_strip.dart L193: ref.read(selectedDateProvider.notifier).selectDate(tappedDate); L199: ref.watch(selectedDateProvider) |
calendar_day_list.dart |
calendar_providers.dart |
Day list watches calendarDayProvider | WIRED | calendar_day_list.dart L46: final dayState = ref.watch(calendarDayProvider) |
calendar_day_list.dart |
task_providers.dart |
Task completion via taskActionsProvider | WIRED | calendar_day_list.dart L39: ref.read(taskActionsProvider.notifier).completeTask(taskId) |
Requirements Coverage
| Requirement | Source Plan | Description | Status | Evidence |
|---|---|---|---|---|
| CAL-01 | Plan 02 | User sees horizontal scrollable date-strip with day abbreviation (Mo, Di...) and date number per card | SATISFIED | calendar_strip.dart: 181-card horizontal ListView; DateFormat('E', 'de') for German abbreviations; date.day.toString() for date number |
| CAL-02 | Plan 01 | User can tap a day card to see that day's tasks in a list below the strip | SATISFIED | _onCardTapped → selectedDateProvider → calendarDayProvider → CalendarDayList reactive update |
| CAL-03 | Plan 02 | User sees a subtle color shift at month boundaries for visual orientation | SATISFIED | _isFirstOfMonth check triggers _kMonthBoundaryGap = 16.0 (vs 4px normal) and DateFormat('MMM', 'de') month label in theme.colorScheme.primary |
| CAL-04 | Plan 02 | Calendar strip auto-scrolls to today on app launch | SATISFIED | addPostFrameCallback → _animateToToday() → animateTo(200ms, Curves.easeOut) centered on today's index |
| CAL-05 | Plans 01+02 | Undone tasks carry over to the next day with red/orange color accent | SATISFIED | watchOverdueTasks returns tasks with nextDueDate < today; calendarDayProvider includes them only for isToday; _overdueColor = Color(0xFFE07A5F) applied to section header and task name text |
All 5 CAL requirements: SATISFIED
No orphaned requirements — REQUIREMENTS.md maps CAL-01 through CAL-05 exclusively to Phase 5, all accounted for.
Anti-Patterns Found
No anti-patterns detected. Scan of all 7 phase-created/modified files found:
- No TODO/FIXME/XXX/HACK/PLACEHOLDER comments
- No empty implementations (
return null,return {},return []) - No stub handlers (
() => {}or() => console.log(...)) - No unimplemented API routes
Test Results
| Suite | Result | Count |
|---|---|---|
flutter test test/features/home/data/calendar_dao_test.dart |
All passed | 11/11 |
flutter test (full suite) |
All passed | 101/101 |
flutter analyze --no-fatal-infos |
No issues | 0 errors, 0 warnings |
Commit Verification
All 5 commits documented in SUMMARY files confirmed to exist in git history:
| Hash | Description |
|---|---|
f5c4b49 |
test(05-01): add failing tests for CalendarDao |
c666f9a |
feat(05-01): implement CalendarDao with date-parameterized task queries |
68ba7c6 |
feat(05-01): add CalendarDayState model, Riverpod providers, and l10n strings |
f718ee8 |
feat(05-02): build CalendarStrip, CalendarTaskRow, CalendarDayList widgets |
88ef248 |
feat(05-02): replace HomeScreen with calendar composition and floating Today button |
Human Verification Required
All automated checks pass. The following items require a device or emulator to confirm:
1. Calendar Strip Visual Rendering
Test: Launch the app, navigate to the home tab. Expected: Horizontal row of day cards each showing a German day abbreviation (Mo, Di, Mi, Do, Fr, Sa, So) and a date number. All cards have a light sage/green tint background. Today's card has bold text and a 2px green underline accent bar below the date number. Why human: Color fidelity, card proportions, and font weight treatment are visual properties.
2. Day Selection Updates Task List
Test: Tap several different day cards in the strip. Expected: The tapped card becomes highlighted (stronger green background + border, centered in the strip), and the task list below immediately updates to show that day's scheduled tasks. Why human: Interactive responsiveness and smooth centering animation require a running device.
3. Floating Today Button Behavior
Test: Scroll the strip well past today (e.g., 30+ days forward). Then tap the floating "Heute" button. Expected: The "Heute" FAB appears when today's card is no longer in the viewport. Tapping it re-centers today's card with a smooth scroll animation and resets the task list to today's tasks. The FAB then disappears. Why human: FAB visibility toggling based on scroll position and imperative scroll-back require real interaction.
4. Month Boundary Labels
Test: Scroll through a month boundary in the strip. Expected: At the boundary, a small month name label (e.g., "Apr") appears above the first card of the new month, and the gap between the last card of the old month and the first card of the new month is visibly wider than the normal gap. Why human: Gap width and label placement are visual properties.
5. Overdue Section Today-Only
Test: With at least one task whose nextDueDate is before today in the database, view the home screen on today's date, then tap a past or future date. Expected: On today's view, a coral-colored "Uberfaellig" section header appears above the overdue task(s) with coral-colored task names. Switching to any other day hides the overdue section entirely — only that day's scheduled tasks appear. Why human: Requires real data in the database and navigation between dates.
6. Task Completion Slide-Out Animation
Test: Tap a checkbox on any task in the day list. Expected: The task row slides out to the right while simultaneously collapsing its height to zero, over approximately 300ms, then disappears from the list. Why human: Animation smoothness, duration, and visual quality require observation on a running device.
Summary
Phase 5 goal is fully achieved at the code level. The horizontal calendar strip replaces the stacked daily plan, the data layer correctly handles date-parameterized queries and overdue isolation, all UI widgets are substantive and properly wired, all key links are connected, all 5 CAL requirements are satisfied, and the full 101-test suite passes with zero analysis issues.
The human_needed status reflects that 6 visual and interactive behaviors (strip appearance, tap selection, Today button scroll-back, month boundary labels, overdue section isolation, and task completion animation) require a running device to confirm their real-world quality. No code gaps were found.
Verified: 2026-03-16T21:00:00Z Verifier: Claude (gsd-verifier)