timetracker/lib/features/reports/presentation/widgets/duration_bar_chart.dart
2026-08-03 21:51:48 +02:00

78 lines
2.3 KiB
Dart

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class DurationBarChart extends StatelessWidget {
const DurationBarChart({
super.key,
required this.values,
required this.labels,
});
/// Values in minutes (one per bar)
final List<double> values;
/// X-axis labels (e.g. ['Mon', 'Tue', …])
final List<String> labels;
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final maxY = values.isEmpty
? 60.0
: (values.reduce((a, b) => a > b ? a : b) * 1.2).clamp(30.0, double.infinity);
return BarChart(
BarChartData(
maxY: maxY,
barGroups: List.generate(values.length, (i) {
return BarChartGroupData(
x: i,
barRods: [
BarChartRodData(
toY: values[i],
color: colorScheme.primary,
width: 16,
borderRadius: const BorderRadius.vertical(top: Radius.circular(4)),
),
],
);
}),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 36,
getTitlesWidget: (value, meta) => Text(
'${(value / 60).toStringAsFixed(0)}h',
style: Theme.of(context).textTheme.labelSmall,
),
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
final idx = value.toInt();
if (idx < 0 || idx >= labels.length) return const SizedBox.shrink();
return Text(
labels[idx],
style: Theme.of(context).textTheme.labelSmall,
);
},
),
),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
gridData: FlGridData(
drawVerticalLine: false,
getDrawingHorizontalLine: (value) => FlLine(
color: colorScheme.outlineVariant,
strokeWidth: 0.5,
),
),
borderData: FlBorderData(show: false),
),
);
}
}