feat(programmer): day sheets + approvals tabs

- day_sheet_snapshot_builder.dart: buildSnapshotForSheet (approved →
  stored snapshot, else live buildDayRows), groupSheetsByDate (descending
  keys), approvalCounts (pending/awaiting/approved)
- approvals_tab.dart: status filter chips, programmer dropdown,
  ReportDateFilter.controlled, date-grouped cards with Auto/Early/Round
  badges, checkbox multi-select, bulk Approve selected (n) flow
- day_sheets_tab.dart: Today card (live rows, total, status, Submit day),
  Needs your attention (disapproved), history with AppStatusSummaryRow
  All/Pending/Disapproved/Approved filter
- programmerTasksTabsFor: admin → [monitor, approvals, mine, all];
  programmer → [mine, all, daySheets]
- programmer_tasks_list_screen.dart: wire approvals + daySheets cases

Tests: 15 passing (day_sheet_tabs_test + programmer_tabs_test)

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-09-28 14:43:52 +08:00
parent 1fe9653bdf
commit 54ce528b02
7 changed files with 1038 additions and 4 deletions
+10 -2
View File
@@ -49,18 +49,26 @@ void main() {
setUpAll(AppTime.initialize);
group('programmerTasksTabsFor', () {
test('tabs in this slice', () {
test('admin gets monitor + approvals + mine + all', () {
expect(
programmerTasksTabsFor(isStrictAdmin: true),
[
ProgrammerTasksTab.monitor,
ProgrammerTasksTab.approvals,
ProgrammerTasksTab.mine,
ProgrammerTasksTab.all,
],
);
});
test('programmer gets mine + all + daySheets', () {
expect(
programmerTasksTabsFor(isStrictAdmin: false),
[ProgrammerTasksTab.mine, ProgrammerTasksTab.all],
[
ProgrammerTasksTab.mine,
ProgrammerTasksTab.all,
ProgrammerTasksTab.daySheets,
],
);
});
});