import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import '../../../../shared/theme/app_theme.dart'; class DashboardPage extends StatelessWidget { const DashboardPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.backgroundLight, appBar: AppBar( title: const Text('Tableau de bord'), backgroundColor: AppTheme.primaryColor, elevation: 0, actions: [ IconButton( icon: const Icon(Icons.notifications_outlined), onPressed: () {}, ), IconButton( icon: const Icon(Icons.settings_outlined), onPressed: () {}, ), ], ), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Message de bienvenue _buildWelcomeSection(context), const SizedBox(height: 24), // Cartes KPI principales _buildKPICards(context), const SizedBox(height: 24), // Graphiques et statistiques _buildChartsSection(context), const SizedBox(height: 24), // Actions rapides _buildQuickActions(context), const SizedBox(height: 24), // Activités récentes _buildRecentActivities(context), ], ), ), ), ); } Widget _buildWelcomeSection(BuildContext context) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [AppTheme.primaryColor, AppTheme.primaryLight], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), ), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Bonjour !', style: TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( 'Voici un aperçu de votre association', style: TextStyle( color: Colors.white.withOpacity(0.9), fontSize: 16, ), ), ], ), ), Container( width: 60, height: 60, decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(30), ), child: const Icon( Icons.dashboard, color: Colors.white, size: 30, ), ), ], ), ); } Widget _buildKPICards(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Indicateurs clés', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: _buildKPICard( context, 'Membres', '1,247', '+5.2%', Icons.people, AppTheme.primaryColor, ), ), const SizedBox(width: 12), Expanded( child: _buildKPICard( context, 'Revenus', '€45,890', '+12.8%', Icons.euro, AppTheme.successColor, ), ), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildKPICard( context, 'Événements', '23', '+3', Icons.event, AppTheme.accentColor, ), ), const SizedBox(width: 12), Expanded( child: _buildKPICard( context, 'Cotisations', '89.5%', '+2.1%', Icons.payments, AppTheme.infoColor, ), ), ], ), ], ); } Widget _buildKPICard( BuildContext context, String title, String value, String change, IconData icon, Color color, ) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: color, size: 20, ), ), const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppTheme.successColor.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Text( change, style: const TextStyle( color: AppTheme.successColor, fontSize: 12, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 12), Text( value, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(height: 4), Text( title, style: const TextStyle( fontSize: 14, color: AppTheme.textSecondary, ), ), ], ), ); } Widget _buildChartsSection(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Analyses', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: _buildLineChart(context), ), const SizedBox(width: 12), Expanded( child: _buildPieChart(context), ), ], ), ], ); } Widget _buildLineChart(BuildContext context) { return Container( height: 200, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Évolution des membres', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const SizedBox(height: 16), Expanded( child: LineChart( LineChartData( gridData: const FlGridData(show: false), titlesData: const FlTitlesData(show: false), borderData: FlBorderData(show: false), lineBarsData: [ LineChartBarData( spots: const [ FlSpot(0, 1000), FlSpot(1, 1050), FlSpot(2, 1100), FlSpot(3, 1180), FlSpot(4, 1247), ], color: AppTheme.primaryColor, barWidth: 3, isStrokeCapRound: true, dotData: const FlDotData(show: false), belowBarData: BarAreaData( show: true, color: AppTheme.primaryColor.withOpacity(0.1), ), ), ], ), ), ), ], ), ); } Widget _buildPieChart(BuildContext context) { return Container( height: 200, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Répartition des membres', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const SizedBox(height: 16), Expanded( child: PieChart( PieChartData( sectionsSpace: 0, centerSpaceRadius: 40, sections: [ PieChartSectionData( color: AppTheme.primaryColor, value: 45, title: '45%', radius: 50, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), PieChartSectionData( color: AppTheme.secondaryColor, value: 30, title: '30%', radius: 50, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), PieChartSectionData( color: AppTheme.accentColor, value: 25, title: '25%', radius: 50, titleStyle: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ), ), ], ), ); } Widget _buildQuickActions(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Actions rapides', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: _buildActionCard( context, 'Nouveau membre', 'Ajouter un membre', Icons.person_add, AppTheme.primaryColor, ), ), const SizedBox(width: 12), Expanded( child: _buildActionCard( context, 'Créer événement', 'Organiser un événement', Icons.event_available, AppTheme.secondaryColor, ), ), ], ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildActionCard( context, 'Suivi cotisations', 'Gérer les cotisations', Icons.payment, AppTheme.accentColor, ), ), const SizedBox(width: 12), Expanded( child: _buildActionCard( context, 'Rapports', 'Générer des rapports', Icons.analytics, AppTheme.infoColor, ), ), ], ), ], ); } Widget _buildActionCard( BuildContext context, String title, String subtitle, IconData icon, Color color, ) { return InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('$title - En cours de développement'), backgroundColor: color, ), ); }, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.2)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Icon( icon, color: color, size: 24, ), ), const SizedBox(height: 12), Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), textAlign: TextAlign.center, ), const SizedBox(height: 4), Text( subtitle, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), textAlign: TextAlign.center, ), ], ), ), ); } Widget _buildRecentActivities(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Activités récentes', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), TextButton( onPressed: () {}, child: const Text('Voir tout'), ), ], ), const SizedBox(height: 16), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ _buildActivityItem( 'Nouveau membre inscrit', 'Marie Dupont a rejoint l\'association', Icons.person_add, AppTheme.successColor, 'Il y a 2h', ), const Divider(height: 1), _buildActivityItem( 'Cotisation reçue', 'Jean Martin a payé sa cotisation annuelle', Icons.payment, AppTheme.primaryColor, 'Il y a 4h', ), const Divider(height: 1), _buildActivityItem( 'Événement créé', 'Assemblée générale 2024 programmée', Icons.event, AppTheme.accentColor, 'Hier', ), ], ), ), ], ); } Widget _buildActivityItem( String title, String description, IconData icon, Color color, String time, ) { return Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: color, size: 16, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const SizedBox(height: 2), Text( description, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), ), ], ), ), Text( time, style: const TextStyle( fontSize: 12, color: AppTheme.textHint, ), ), ], ), ); } }