import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import '../../../../shared/theme/app_theme.dart'; class ChartCard extends StatelessWidget { final String title; final Widget chart; final String? subtitle; final VoidCallback? onTap; const ChartCard({ super.key, required this.title, required this.chart, this.subtitle, this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 15, offset: const Offset(0, 4), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), if (subtitle != null) ...[ const SizedBox(height: 4), Text( subtitle!, style: const TextStyle( fontSize: 14, color: AppTheme.textSecondary, ), ), ], ], ), ), if (onTap != null) const Icon( Icons.arrow_forward_ios, size: 16, color: AppTheme.textHint, ), ], ), const SizedBox(height: 20), SizedBox( height: 200, child: chart, ), ], ), ), ); } } class MembershipChart extends StatelessWidget { const MembershipChart({super.key}); @override Widget build(BuildContext context) { return LineChart( LineChartData( gridData: FlGridData( show: true, drawVerticalLine: false, horizontalInterval: 200, getDrawingHorizontalLine: (value) { return FlLine( color: AppTheme.borderColor.withOpacity(0.5), strokeWidth: 1, ); }, ), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), topTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, interval: 200, getTitlesWidget: (value, meta) { return Text( value.toInt().toString(), style: const TextStyle( color: AppTheme.textHint, fontSize: 12, ), ); }, ), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (value, meta) { const months = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Jun']; if (value.toInt() < months.length) { return Text( months[value.toInt()], style: const TextStyle( color: AppTheme.textHint, fontSize: 12, ), ); } return const Text(''); }, ), ), ), borderData: FlBorderData(show: false), minX: 0, maxX: 5, minY: 800, maxY: 1400, lineBarsData: [ LineChartBarData( spots: const [ FlSpot(0, 1000), FlSpot(1, 1050), FlSpot(2, 1100), FlSpot(3, 1180), FlSpot(4, 1220), FlSpot(5, 1247), ], color: AppTheme.primaryColor, barWidth: 3, isStrokeCapRound: true, dotData: FlDotData( show: true, getDotPainter: (spot, percent, barData, index) { return FlDotCirclePainter( radius: 4, color: AppTheme.primaryColor, strokeWidth: 2, strokeColor: Colors.white, ); }, ), belowBarData: BarAreaData( show: true, gradient: LinearGradient( colors: [ AppTheme.primaryColor.withOpacity(0.3), AppTheme.primaryColor.withOpacity(0.1), AppTheme.primaryColor.withOpacity(0.0), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), ], ), ); } } class CategoryChart extends StatelessWidget { const CategoryChart({super.key}); @override Widget build(BuildContext context) { return PieChart( PieChartData( sectionsSpace: 4, centerSpaceRadius: 50, sections: [ PieChartSectionData( color: AppTheme.primaryColor, value: 45, title: 'Actifs\n45%', radius: 60, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), PieChartSectionData( color: AppTheme.secondaryColor, value: 30, title: 'Retraités\n30%', radius: 60, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), PieChartSectionData( color: AppTheme.accentColor, value: 25, title: 'Étudiants\n25%', radius: 60, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ); } } class RevenueChart extends StatelessWidget { const RevenueChart({super.key}); @override Widget build(BuildContext context) { return BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, maxY: 15000, barTouchData: BarTouchData(enabled: false), titlesData: FlTitlesData( show: true, rightTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), topTitles: const AxisTitles( sideTitles: SideTitles(showTitles: false), ), leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, interval: 5000, getTitlesWidget: (value, meta) { return Text( '${(value / 1000).toInt()}k€', style: const TextStyle( color: AppTheme.textHint, fontSize: 12, ), ); }, ), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, getTitlesWidget: (value, meta) { const months = ['J', 'F', 'M', 'A', 'M', 'J']; if (value.toInt() < months.length) { return Text( months[value.toInt()], style: const TextStyle( color: AppTheme.textHint, fontSize: 12, ), ); } return const Text(''); }, ), ), ), borderData: FlBorderData(show: false), gridData: FlGridData( show: true, drawVerticalLine: false, horizontalInterval: 5000, getDrawingHorizontalLine: (value) { return FlLine( color: AppTheme.borderColor.withOpacity(0.5), strokeWidth: 1, ); }, ), barGroups: [ _buildBarGroup(0, 8000, AppTheme.primaryColor), _buildBarGroup(1, 9500, AppTheme.primaryColor), _buildBarGroup(2, 7800, AppTheme.primaryColor), _buildBarGroup(3, 11200, AppTheme.primaryColor), _buildBarGroup(4, 13500, AppTheme.primaryColor), _buildBarGroup(5, 12800, AppTheme.primaryColor), ], ), ); } BarChartGroupData _buildBarGroup(int x, double y, Color color) { return BarChartGroupData( x: x, barRods: [ BarChartRodData( toY: y, color: color, width: 16, borderRadius: const BorderRadius.only( topLeft: Radius.circular(4), topRight: Radius.circular(4), ), ), ], ); } }