Files
unionflow-client-quarkus-pr…/unionflow-mobile-apps/lib/features/dashboard/presentation/widgets/quick_stats_section.dart

360 lines
9.1 KiB
Dart

import 'package:flutter/material.dart';
import 'common/section_header.dart';
import 'common/stat_card.dart';
/// Section des statistiques rapides du dashboard
///
/// Widget réutilisable pour afficher les KPIs et métriques principales
/// avec différents layouts et styles selon le contexte.
class QuickStatsSection extends StatelessWidget {
/// Titre de la section
final String title;
/// Sous-titre optionnel
final String? subtitle;
/// Liste des statistiques à afficher
final List<QuickStat> stats;
/// Layout des cartes (grid, row, column)
final StatsLayout layout;
/// Nombre de colonnes pour le layout grid
final int gridColumns;
/// Style des cartes de statistiques
final StatCardStyle cardStyle;
/// Taille des cartes
final StatCardSize cardSize;
/// Callback lors du tap sur une statistique
final Function(QuickStat)? onStatTap;
/// Afficher ou non l'en-tête de section
final bool showHeader;
const QuickStatsSection({
super.key,
required this.title,
this.subtitle,
required this.stats,
this.layout = StatsLayout.grid,
this.gridColumns = 2,
this.cardStyle = StatCardStyle.elevated,
this.cardSize = StatCardSize.compact,
this.onStatTap,
this.showHeader = true,
});
/// Constructeur pour les KPIs système (Super Admin)
const QuickStatsSection.systemKPIs({
super.key,
this.onStatTap,
}) : title = 'Métriques Système',
subtitle = null,
stats = const [
QuickStat(
title: 'Organisations',
value: '247',
subtitle: '+12 ce mois',
icon: Icons.business,
color: Color(0xFF0984E3),
),
QuickStat(
title: 'Utilisateurs',
value: '15,847',
subtitle: '+1,234 ce mois',
icon: Icons.people,
color: Color(0xFF00B894),
),
QuickStat(
title: 'Uptime',
value: '99.97%',
subtitle: '30 derniers jours',
icon: Icons.trending_up,
color: Color(0xFF00CEC9),
),
QuickStat(
title: 'Temps Réponse',
value: '1.2s',
subtitle: 'Moyenne 24h',
icon: Icons.speed,
color: Color(0xFFE17055),
),
],
layout = StatsLayout.grid,
gridColumns = 2,
cardStyle = StatCardStyle.elevated,
cardSize = StatCardSize.compact,
showHeader = true;
/// Constructeur pour les statistiques d'organisation
const QuickStatsSection.organizationStats({
super.key,
this.onStatTap,
}) : title = 'Vue d\'ensemble',
subtitle = null,
stats = const [
QuickStat(
title: 'Membres',
value: '156',
subtitle: '+12 ce mois',
icon: Icons.people,
color: Color(0xFF00B894),
),
QuickStat(
title: 'Événements',
value: '23',
subtitle: '8 à venir',
icon: Icons.event,
color: Color(0xFFE17055),
),
QuickStat(
title: 'Projets',
value: '8',
subtitle: '3 actifs',
icon: Icons.work,
color: Color(0xFF0984E3),
),
QuickStat(
title: 'Taux engagement',
value: '78%',
subtitle: '+5% ce mois',
icon: Icons.trending_up,
color: Color(0xFF6C5CE7),
),
],
layout = StatsLayout.grid,
gridColumns = 2,
cardStyle = StatCardStyle.elevated,
cardSize = StatCardSize.compact,
showHeader = true;
/// Constructeur pour les métriques de performance
const QuickStatsSection.performanceMetrics({
super.key,
this.onStatTap,
}) : title = 'Performance',
subtitle = 'Métriques temps réel',
stats = const [
QuickStat(
title: 'CPU',
value: '23%',
subtitle: 'Normal',
icon: Icons.memory,
color: Color(0xFF00B894),
),
QuickStat(
title: 'RAM',
value: '67%',
subtitle: 'Élevé',
icon: Icons.storage,
color: Color(0xFFE17055),
),
QuickStat(
title: 'Réseau',
value: '12 MB/s',
subtitle: 'Stable',
icon: Icons.network_check,
color: Color(0xFF0984E3),
),
],
layout = StatsLayout.row,
gridColumns = 3,
cardStyle = StatCardStyle.outlined,
cardSize = StatCardSize.normal,
showHeader = true;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showHeader) ...[
SectionHeader.section(
title: title,
subtitle: subtitle,
),
],
_buildStatsLayout(),
],
);
}
/// Construction du layout des statistiques
Widget _buildStatsLayout() {
switch (layout) {
case StatsLayout.grid:
return _buildGridLayout();
case StatsLayout.row:
return _buildRowLayout();
case StatsLayout.column:
return _buildColumnLayout();
case StatsLayout.wrap:
return _buildWrapLayout();
}
}
/// Layout en grille
Widget _buildGridLayout() {
return GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: gridColumns,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: _getChildAspectRatio(),
),
itemCount: stats.length,
itemBuilder: (context, index) => _buildStatCard(stats[index]),
);
}
/// Layout en ligne
Widget _buildRowLayout() {
return Row(
children: stats.map((stat) => Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: _buildStatCard(stat),
),
)).toList(),
);
}
/// Layout en colonne
Widget _buildColumnLayout() {
return Column(
children: stats.map((stat) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildStatCard(stat),
)).toList(),
);
}
/// Layout wrap (adaptatif)
Widget _buildWrapLayout() {
return LayoutBuilder(
builder: (context, constraints) {
return Wrap(
spacing: 8,
runSpacing: 8,
children: stats.map((stat) => SizedBox(
width: (constraints.maxWidth - 8) / 2, // 2 colonnes avec espacement
child: _buildStatCard(stat),
)).toList(),
);
},
);
}
/// Construction d'une carte de statistique
Widget _buildStatCard(QuickStat stat) {
return StatCard(
title: stat.title,
value: stat.value,
subtitle: stat.subtitle,
icon: stat.icon,
color: stat.color,
size: cardSize,
style: cardStyle,
onTap: onStatTap != null ? () => onStatTap!(stat) : null,
);
}
/// Ratio d'aspect selon la taille des cartes
double _getChildAspectRatio() {
switch (cardSize) {
case StatCardSize.compact:
return 1.4;
case StatCardSize.normal:
return 1.2;
case StatCardSize.large:
return 1.0;
}
}
}
/// Modèle de données pour une statistique rapide
class QuickStat {
final String title;
final String value;
final String subtitle;
final IconData icon;
final Color color;
final Map<String, dynamic>? metadata;
const QuickStat({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
required this.color,
this.metadata,
});
/// Constructeur pour une métrique système
const QuickStat.system({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = const Color(0xFF6C5CE7),
metadata = null;
/// Constructeur pour une métrique utilisateur
const QuickStat.user({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = const Color(0xFF00B894),
metadata = null;
/// Constructeur pour une métrique d'organisation
const QuickStat.organization({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = const Color(0xFF0984E3),
metadata = null;
/// Constructeur pour une métrique d'événement
const QuickStat.event({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = const Color(0xFFE17055),
metadata = null;
/// Constructeur pour une alerte
const QuickStat.alert({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = Colors.orange,
metadata = null;
/// Constructeur pour une erreur
const QuickStat.error({
required this.title,
required this.value,
required this.subtitle,
required this.icon,
}) : color = Colors.red,
metadata = null;
}
/// Types de layout pour les statistiques
enum StatsLayout {
grid,
row,
column,
wrap,
}