import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import '../../consts.dart'; import '../../utils/format_month.dart'; class BarData extends StatefulWidget { const BarData({super.key}); @override State<StatefulWidget> createState() => _BarDataState(); } class _BarDataState extends State<BarData> { static const double barWidth = 30; // Allocate bar data dynamically from selected subdivision var barData = <int, List<double>>{}; double totalHeight = 0; int touchedIndex = -1; @override void initState() { super.initState(); // Allocate bar data dynamically based from the selected subdivision for (int i = 0; i < 7; i++) { var entry = selectedSubDiv?.iceStats[i]; if (entry != null) { barData[i] = [ entry.slushIce, entry.blackIce, entry.snowDepth, ]; // Find tallest layer if (entry.totalIce > totalHeight) { totalHeight = entry.totalIce; } } else { barData[i] = [0.0, 0.0, 0.0]; } } } BarChartGroupData generateGroup( int x, double value1, double value2, double value3, ) { final sum = value1 + value2 + value3; final isTouched = touchedIndex == x; return BarChartGroupData( x: x, showingTooltipIndicators: isTouched ? [0] : [], barRods: [ BarChartRodData( y: sum, width: barWidth, borderRadius: const BorderRadius.only( topLeft: Radius.circular(6), topRight: Radius.circular(6), ), rodStackItems: [ BarChartRodStackItem( 0, value1, const Color(0xFF13dbff), ), BarChartRodStackItem( value1, value1 + value2, const Color(0xFF3766E0), ), BarChartRodStackItem( value1 + value2, value1 + value2 + value3, Colors.white60, ), ], ), ], ); } // _buildLegendItem renders a colored circle and text to form a legend Widget _buildLegendItem(Color color, String text) { return Row( children: [ Container( width: 20, height: 20, decoration: BoxDecoration( color: color, shape: BoxShape.circle, ), ), const SizedBox(width: 8), Text( text, style: const TextStyle( fontSize: 14, color: Colors.white, ), ), ], ); } @override Widget build(BuildContext context) { return Column( children: [ SizedBox( width: MediaQuery.of(context).size.width, // Set the desired width child: BarChart( BarChartData( alignment: BarChartAlignment.center, maxY: totalHeight + totalHeight/4, // NB Set minY: 0, titlesData: FlTitlesData( show: true, bottomTitles: SideTitles( showTitles: true, reservedSize: 20, getTextStyles: (value) => const TextStyle(color: Colors.white60), getTitles: (value) { // Convert bar indexes to dates if (barData.isNotEmpty && value >= 0 && value < barData.length) { int index = value.toInt(); DateTime today = DateTime.now(); // Subtract index from the day of the month of the current date int day = today.day - (6-index); String date = day.toString(); String month = formatMonth(today.month); return '$month $date'; } return ''; }, ), leftTitles: SideTitles( showTitles: true, getTextStyles: (value) => const TextStyle(color: Colors.white60), margin: 5, reservedSize: 30, interval: totalHeight/5, ), rightTitles: SideTitles( showTitles: true, getTextStyles: (value) => const TextStyle(color: Colors.white60), margin: 5, reservedSize: 30, interval: totalHeight/5, ), ), groupsSpace: 14, gridData: FlGridData( show: true, ), borderData: FlBorderData( show: false, ), barGroups: barData.entries .map( (e) => generateGroup( e.key, e.value[0], e.value[1], e.value[2], ), ).toList(), ), ), ), Padding( // Legend items padding: const EdgeInsets.only(top: 20), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildLegendItem(const Color(0xFF13dbff), "Black ice"), _buildLegendItem(const Color(0xFF3766E0), "Slush ice"), _buildLegendItem(Colors.white60, "Snow"), ], ), ), ), ], ); } }