fix(approvals): show — instead of 0m·0 tasks for pending/disapproved sheets

approvedSnapshot is only populated at approval time; pending and disapproved
sheets had null snapshot so the card always displayed 0m · 0 tasks.

Now totalSecs/taskCount are passed as nullable params from the parent; the
card renders — when no snapshot is available yet.

Also accept camelCase 'daySheets' URL param in parseProgrammerTasksTab
alongside the existing hyphenated 'day-sheets' spelling.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-09-28 21:05:58 +08:00
parent 68817a70f0
commit 4f60e23003
2 changed files with 14 additions and 4 deletions
@@ -269,6 +269,8 @@ class _ApprovalsTabState extends ConsumerState<ApprovalsTab> {
profile: profileById[sheet.programmerId], profile: profileById[sheet.programmerId],
showCheckbox: _filter == DaySheetStatus.pending, showCheckbox: _filter == DaySheetStatus.pending,
selected: _selected.contains(sheet.id), selected: _selected.contains(sheet.id),
totalSecs: sheet.approvedSnapshot?.totalSeconds,
taskCount: sheet.approvedSnapshot?.rows.length,
onToggle: _filter == DaySheetStatus.pending onToggle: _filter == DaySheetStatus.pending
? (v) => setState(() { ? (v) => setState(() {
if (v == true) { if (v == true) {
@@ -324,6 +326,8 @@ class _SheetApprovalCard extends StatelessWidget {
required this.selected, required this.selected,
required this.onToggle, required this.onToggle,
required this.onTap, required this.onTap,
this.totalSecs,
this.taskCount,
}); });
final ProgrammerDaySheet sheet; final ProgrammerDaySheet sheet;
@@ -332,11 +336,12 @@ class _SheetApprovalCard extends StatelessWidget {
final bool selected; final bool selected;
final ValueChanged<bool?>? onToggle; final ValueChanged<bool?>? onToggle;
final VoidCallback onTap; final VoidCallback onTap;
/// Null when no approved snapshot exists yet (pending/disapproved sheets).
final int? totalSecs;
final int? taskCount;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final totalSecs = sheet.approvedSnapshot?.totalSeconds ?? 0;
final taskCount = sheet.approvedSnapshot?.rows.length ?? 0;
final roundNum = sheet.resubmissions + 1; final roundNum = sheet.resubmissions + 1;
return Card( return Card(
@@ -369,9 +374,13 @@ class _SheetApprovalCard extends StatelessWidget {
runSpacing: 4, runSpacing: 4,
children: [ children: [
TechChip( TechChip(
formatDurationHm(Duration(seconds: totalSecs)), totalSecs != null
? formatDurationHm(Duration(seconds: totalSecs!))
: '—',
),
TechChip(
taskCount != null ? '$taskCount tasks' : '—',
), ),
TechChip('$taskCount tasks'),
if (sheet.autoSubmitted) if (sheet.autoSubmitted)
const TechChip('Auto', status: StatusKind.info) const TechChip('Auto', status: StatusKind.info)
else else
@@ -42,6 +42,7 @@ ProgrammerTasksTab? parseProgrammerTasksTab(String? q) {
case 'all': case 'all':
return ProgrammerTasksTab.all; return ProgrammerTasksTab.all;
case 'day-sheets': case 'day-sheets':
case 'daySheets':
return ProgrammerTasksTab.daySheets; return ProgrammerTasksTab.daySheets;
default: default:
return null; return null;