Tab switching: _buildTabs was recreating TabController on every build
because `_tabs == tabs` compares List by reference identity, not content.
programmerTasksTabsFor() always returns a new list, so the guard was
always false, resetting the controller to initialIndex 0 on every tap.
Fixed by using listEquals from flutter/foundation.
Help given: computeProgrammerStats accumulated helpGivenThisMonth only
from approvedSnapshot rows, which only exist after admin approval.
Programmers who helped others but had pending sheets saw 0m indefinitely.
Fixed by adding helpGivenThisMonthProvider (FutureProvider.family) that
queries programmer_task_work_logs directly for the current Manila month,
and passing it as liveHelpThisMonthSec to computeProgrammerStats.
Co-Authored-By: claude-flow <ruv@ruv.net>
- Wire daySheetsForUserProvider(userId) into ProgrammerDashboard so
computeProgrammerStats/computeBadges receive real sheet data instead of
the placeholder const <ProgrammerDaySheet>[].
- Monitor tab: watch allDaySheetsProvider and build sheetStatusByUser map
for today; pass it to buildMonitorEntries; add "Sheets pending" chip
(pending + disapproved today) to the summary row.
- ProgrammerDrillDownScreen: add _RecentDaySheetsPanel below the dashboard
showing the last 10 sheets (date + status pill) with tap-to-daySheetDetail.
- DaySheetDetailScreen (T17 gaps): replace const [] liveRows with
programmerDayDataProvider(sheet.workDate) built rows for non-approved
sheets; fix _onApprove timer check to filter only the sheet programmer's
own tasks (QN-1).
- Add test/programmer_drill_down_test.dart (3 tests, all passing).
Co-Authored-By: claude-flow <ruv@ruv.net>
Add StatTiles and BadgesStrip widgets wired into ProgrammerDashboard.
StatTiles shows 2 tiles (focus + completed) when showSheetStats is false,
and 5 tiles (+ streak, first-pass approval, help given) when the viewing
user's role is programmer. BadgesStrip renders earned/locked chips in a
horizontal Wrap with tap-to-dialog detail.
Dashboard feeds todayFocus via buildDayRows/totalSeconds, leaveDays via
approvedLeaveDays, and sheets: const [] until Task 20 wires real data.
Co-Authored-By: claude-flow <ruv@ruv.net>
NowWorkingCard was watching clockTickerProvider but received pre-computed
Duration values from ProgrammerDashboard, which never rebuilt on ticks.
Move ref.watch(clockTickerProvider) to ProgrammerDashboard.build() so
the parent rebuilds every 30 s and passes fresh durations to the card.
Remove the now-unused clockTickerProvider watch (and its import) from
NowWorkingCard.
Co-Authored-By: claude-flow <ruv@ruv.net>
Replace the Mine tab flat list with ProgrammerDashboard — a NowWorkingCard
hero (running task with Pause/Complete, or idle with nextUp Start), a
TODO stub for Task 8 stat tiles/badges, and collapsible TaskSections
(In progress, Paused, Not started always-visible; Completed/Cancelled
start collapsed with Show-all at 10+). groupTasksForDashboard excludes
other assignees and sorts completed/cancelled by terminal date desc.
Co-Authored-By: claude-flow <ruv@ruv.net>