import 'dart:math' as math; import 'package:flutter/material.dart'; import '../../../utils/programmer_stats.dart'; import '../../../utils/programmer_task_ledger.dart'; import '../../../widgets/app_metric_card.dart'; /// A vertical list of KPI stat tiles for the programmer dashboard. /// /// When [showSheetStats] is false only the first two tiles (today's focus and /// completed-this-week) are shown; sheet-based tiles (streak, first-pass /// approval, help given) are hidden and badges are computed without sheet data. class StatTiles extends StatelessWidget { const StatTiles({ super.key, required this.stats, required this.showSheetStats, }); final ProgrammerStats stats; final bool showSheetStats; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final tiles = [ _buildFocusTile(context, cs), const SizedBox(height: 8), _buildCompletedTile(context), ]; if (showSheetStats) { tiles.addAll([ const SizedBox(height: 8), _buildStreakTile(context), const SizedBox(height: 8), _buildFirstPassTile(context), const SizedBox(height: 8), _buildHelpGivenTile(context), ]); } return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: tiles, ); } Widget _buildFocusTile(BuildContext context, ColorScheme cs) { final progressValue = math.min(1.0, stats.todayFocus.inSeconds / (8 * 3600)); final trailing = Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( width: 40, height: 40, child: CircularProgressIndicator( value: progressValue, strokeWidth: 6, backgroundColor: cs.surfaceContainerHighest, color: cs.primary, strokeCap: StrokeCap.round, ), ), const SizedBox(height: 4), Text( '/ 8h', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: cs.onSurfaceVariant, ), ), ], ); return AppMetricCard( title: "TODAY'S FOCUS", value: formatDurationHm(stats.todayFocus), trailing: trailing, ); } Widget _buildCompletedTile(BuildContext context) { final diff = stats.completedThisWeek - stats.completedLastWeek; final String trailingText; if (diff > 0) { trailingText = '↑$diff vs last week'; } else if (diff < 0) { trailingText = '↓${-diff} vs last week'; } else { trailingText = 'Same as last week'; } return AppMetricCard( title: 'COMPLETED THIS WEEK', value: stats.completedThisWeek.toString(), trailing: Text( trailingText, style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ); } Widget _buildStreakTile(BuildContext context) { final n = stats.currentStreak; final dayLabel = n == 1 ? '1 day' : '$n days'; return AppMetricCard( title: 'STREAK', value: dayLabel, icon: Icons.local_fire_department_outlined, trailing: Text( 'Best ${stats.bestStreak}', style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ); } Widget _buildFirstPassTile(BuildContext context) { final value = stats.firstPassRate != null ? '${(stats.firstPassRate! * 100).round()}%' : '—'; return AppMetricCard( title: 'FIRST-PASS APPROVAL', value: value, trailing: Text( 'Last 30 days', style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ); } Widget _buildHelpGivenTile(BuildContext context) { return AppMetricCard( title: 'HELP GIVEN', value: formatDurationHm(stats.helpGivenThisMonth), trailing: Text( 'This month', style: Theme.of(context).textTheme.labelMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ); } }