import 'package:flutter/material.dart'; import '../../../../core/models/membre_model.dart'; import '../../../../shared/theme/app_theme.dart'; /// Widget de statistiques pour la liste des membres class MembresStatsOverview extends StatelessWidget { final List membres; final String searchQuery; const MembresStatsOverview({ super.key, required this.membres, this.searchQuery = '', }); @override Widget build(BuildContext context) { final stats = _calculateStats(); return Container( margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), 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: [ // En-tête Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppTheme.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.analytics, color: AppTheme.primaryColor, size: 20, ), ), const SizedBox(width: 12), const Text( 'Vue d\'ensemble', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), const Spacer(), if (searchQuery.isNotEmpty) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppTheme.infoColor.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Text( 'Filtré', style: TextStyle( fontSize: 12, color: AppTheme.infoColor, fontWeight: FontWeight.w500, ), ), ), ], ), const SizedBox(height: 16), // Statistiques principales Row( children: [ Expanded( child: _buildStatCard( 'Total', stats['total'].toString(), Icons.people, AppTheme.primaryColor, ), ), const SizedBox(width: 12), Expanded( child: _buildStatCard( 'Actifs', stats['actifs'].toString(), Icons.check_circle, AppTheme.successColor, ), ), const SizedBox(width: 12), Expanded( child: _buildStatCard( 'Âge moyen', '${stats['ageMoyen']} ans', Icons.cake, AppTheme.warningColor, ), ), ], ), if (stats['total'] > 0) ...[ const SizedBox(height: 16), // Statistiques détaillées Row( children: [ Expanded( child: _buildDetailedStat( 'Nouveaux (30j)', stats['nouveaux'].toString(), stats['nouveauxPourcentage'], AppTheme.infoColor, ), ), const SizedBox(width: 16), Expanded( child: _buildDetailedStat( 'Anciens (>1an)', stats['anciens'].toString(), stats['anciensPourcentage'], AppTheme.secondaryColor, ), ), ], ), ], ], ), ); } Map _calculateStats() { if (membres.isEmpty) { return { 'total': 0, 'actifs': 0, 'ageMoyen': 0, 'nouveaux': 0, 'nouveauxPourcentage': 0.0, 'anciens': 0, 'anciensPourcentage': 0.0, }; } final now = DateTime.now(); final total = membres.length; final actifs = membres.where((m) => m.statut.toUpperCase() == 'ACTIF').length; // Calcul de l'âge moyen final ages = membres.map((m) => m.age).where((age) => age > 0).toList(); final ageMoyen = ages.isNotEmpty ? (ages.reduce((a, b) => a + b) / ages.length).round() : 0; // Nouveaux membres (moins de 30 jours) final nouveaux = membres.where((m) { final daysDiff = now.difference(m.dateAdhesion).inDays; return daysDiff <= 30; }).length; final nouveauxPourcentage = total > 0 ? (nouveaux / total * 100) : 0.0; // Anciens membres (plus d'un an) final anciens = membres.where((m) { final daysDiff = now.difference(m.dateAdhesion).inDays; return daysDiff > 365; }).length; final anciensPourcentage = total > 0 ? (anciens / total * 100) : 0.0; return { 'total': total, 'actifs': actifs, 'ageMoyen': ageMoyen, 'nouveaux': nouveaux, 'nouveauxPourcentage': nouveauxPourcentage, 'anciens': anciens, 'anciensPourcentage': anciensPourcentage, }; } Widget _buildStatCard(String label, String value, IconData icon, Color color) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: color.withOpacity(0.2)), ), child: Column( children: [ Icon(icon, color: color, size: 20), const SizedBox(height: 4), Text( value, style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: color, ), ), Text( label, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), textAlign: TextAlign.center, ), ], ), ); } Widget _buildDetailedStat(String label, String value, double percentage, Color color) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey[200]!), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 8, height: 8, decoration: BoxDecoration( color: color, shape: BoxShape.circle, ), ), const SizedBox(width: 8), Text( label, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), ), ], ), const SizedBox(height: 4), Row( children: [ Text( value, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppTheme.textPrimary, ), ), const SizedBox(width: 8), Text( '(${percentage.toStringAsFixed(1)}%)', style: TextStyle( fontSize: 12, color: color, fontWeight: FontWeight.w500, ), ), ], ), ], ), ); } }