import 'dart:math' as math; import 'package:sysfarma_mobile/src/app/widgets/empty_state_panel.dart'; import 'package:sysfarma_mobile/src/core/theme/app_tokens.dart'; import 'package:flutter/material.dart'; class MiniTrendChart extends StatelessWidget { const MiniTrendChart({ required this.labels, required this.series, super.key, }); final List labels; final List series; @override Widget build(BuildContext context) { if (labels.isEmpty || series.isEmpty) { return const EmptyStatePanel( icon: Icons.bar_chart_rounded, title: 'Sin datos', subtitle: 'No hay suficientes datos para mostrar la tendencia.', ); } final maxValue = _resolveMaxValue(); return Column( children: [ for (var index = 0; index < labels.length; index++) ...[ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 42, child: Text( labels[index], style: Theme.of(context).textTheme.bodySmall?.copyWith( color: AppTokens.secondary, ), ), ), const SizedBox(width: 12), Expanded( child: Column( children: [ for (final item in series) ...[ _TrendBar( color: item.color, value: _valueAt(item, index), maxValue: maxValue, ), if (item != series.last) const SizedBox(height: 6), ], ], ), ), ], ), if (index != labels.length - 1) const SizedBox(height: 12), ], const SizedBox(height: 16), Wrap( spacing: 8, runSpacing: 8, children: [ for (final item in series) Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: item.color.withValues(alpha:0.10), borderRadius: BorderRadius.circular(999), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 8, height: 8, decoration: BoxDecoration( color: item.color, shape: BoxShape.circle, ), ), const SizedBox(width: 8), Text( item.name, style: Theme.of(context).textTheme.labelMedium?.copyWith( color: item.color, ), ), ], ), ), ], ), ], ); } double _resolveMaxValue() { final values = series.expand((item) => item.values); final maxValue = values.isEmpty ? 1.0 : values.reduce(math.max); return maxValue <= 0 ? 1.0 : maxValue; } double _valueAt(MiniTrendSeries item, int index) { if (index >= item.values.length) { return 0; } return item.values[index]; } } class MiniTrendSeries { const MiniTrendSeries({ required this.name, required this.values, required this.color, }); final String name; final List values; final Color color; } class _TrendBar extends StatelessWidget { const _TrendBar({ required this.color, required this.value, required this.maxValue, }); final Color color; final double value; final double maxValue; @override Widget build(BuildContext context) { final ratio = (value / maxValue).clamp(0.0, 1.0); return LayoutBuilder( builder: (context, constraints) { return Stack( children: [ Container( height: 8, decoration: BoxDecoration( color: AppTokens.border.withValues(alpha:0.45), borderRadius: BorderRadius.circular(999), ), ), AnimatedContainer( duration: const Duration(milliseconds: 240), curve: Curves.easeOutCubic, width: constraints.maxWidth * ratio, height: 8, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(999), ), ), ], ); }, ); } }