import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../providers/reports_provider.dart'; import 'report_card_wrapper.dart'; /// Grouped vertical bar chart — assigned vs completed tasks per IT staff member. class StaffWorkloadChart extends ConsumerWidget { const StaffWorkloadChart({super.key, this.repaintKey}); final GlobalKey? repaintKey; @override Widget build(BuildContext context, WidgetRef ref) { final asyncData = ref.watch(staffWorkloadReportProvider); return asyncData.when( loading: () => ReportCardWrapper( title: 'IT Staff Workload', isLoading: true, height: 300, repaintBoundaryKey: repaintKey, child: const SizedBox.shrink(), ), error: (e, _) => ReportCardWrapper( title: 'IT Staff Workload', error: e.toString(), repaintBoundaryKey: repaintKey, child: const SizedBox.shrink(), ), data: (data) => _build(context, data), ); } Widget _build(BuildContext context, List data) { if (data.isEmpty) { return ReportCardWrapper( title: 'IT Staff Workload', repaintBoundaryKey: repaintKey, child: const SizedBox( height: 200, child: Center(child: Text('No data for selected period')), ), ); } final colors = Theme.of(context).colorScheme; final text = Theme.of(context).textTheme; final maxY = data.fold( 0, (m, e) => [ m, e.assignedCount, e.completedCount, ].reduce((a, b) => a > b ? a : b), ); return ReportCardWrapper( title: 'IT Staff Workload', repaintBoundaryKey: repaintKey, height: 320, child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _LegendDot(color: colors.primary, label: 'Assigned'), const SizedBox(width: 16), _LegendDot(color: colors.tertiary, label: 'Completed'), ], ), const SizedBox(height: 12), Expanded( child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, maxY: maxY * 1.2, barTouchData: BarTouchData( touchTooltipData: BarTouchTooltipData( getTooltipItem: (group, groupIdx, rod, rodIdx) { final item = data[group.x]; final label = rodIdx == 0 ? 'Assigned' : 'Completed'; return BarTooltipItem( '${item.staffName}\n$label: ${rod.toY.toInt()}', text.bodySmall!.copyWith( color: colors.onInverseSurface, ), ); }, ), ), titlesData: FlTitlesData( leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 36, getTitlesWidget: (value, meta) => Text( value.toInt().toString(), style: text.labelSmall, ), ), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (value, meta) { final idx = value.toInt(); if (idx < 0 || idx >= data.length) { return const SizedBox.shrink(); } final name = data[idx].staffName; // Show first name only to save space final short = name.split(' ').first; return Padding( padding: const EdgeInsets.only(top: 6), child: Text( short.length > 10 ? '${short.substring(0, 8)}…' : short, style: text.labelSmall, ), ); }, ), ), topTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), rightTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), ), gridData: FlGridData( drawVerticalLine: false, horizontalInterval: maxY > 0 ? (maxY / 4).ceilToDouble() : 1, ), borderData: FlBorderData(show: false), barGroups: List.generate(data.length, (i) { return BarChartGroupData( x: i, barsSpace: 4, barRods: [ BarChartRodData( toY: data[i].assignedCount.toDouble(), width: 14, borderRadius: const BorderRadius.vertical( top: Radius.circular(4), ), color: colors.primary, ), BarChartRodData( toY: data[i].completedCount.toDouble(), width: 14, borderRadius: const BorderRadius.vertical( top: Radius.circular(4), ), color: colors.tertiary, ), ], ); }), ), ), ), ], ), ); } } class _LegendDot extends StatelessWidget { const _LegendDot({required this.color, required this.label}); final Color color; final String label; @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 10, height: 10, decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), const SizedBox(width: 4), Text(label, style: Theme.of(context).textTheme.bodySmall), ], ); } }