/// UnionFlow Stat Card - Card de statistiques /// /// Card affichant une statistique avec icône, titre, valeur et sous-titre optionnel /// Utilisé dans le dashboard pour afficher les métriques clés library uf_stat_card; import 'package:flutter/material.dart'; import '../../unionflow_design_system.dart'; /// Card de statistiques UnionFlow /// /// Usage: /// ```dart /// UFStatCard( /// title: 'Membres', /// value: '142', /// icon: Icons.people, /// iconColor: ColorTokens.primary, /// subtitle: '+5 ce mois', /// onTap: () => navigateToMembers(), /// ) /// ``` class UFStatCard extends StatelessWidget { /// Titre de la statistique (ex: "Membres") final String title; /// Valeur de la statistique (ex: "142") final String value; /// Icône représentant la statistique final IconData icon; /// Couleur de l'icône (par défaut: primary) final Color? iconColor; /// Sous-titre optionnel (ex: "+5 ce mois") final String? subtitle; /// Callback appelé lors du clic sur la card final VoidCallback? onTap; /// Couleur de fond de l'icône (par défaut: iconColor avec opacité) final Color? iconBackgroundColor; const UFStatCard({ super.key, required this.title, required this.value, required this.icon, this.iconColor, this.subtitle, this.onTap, this.iconBackgroundColor, }); @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final effectiveIconColor = iconColor ?? AppColors.primary; final effectiveIconBgColor = iconBackgroundColor ?? effectiveIconColor.withOpacity(0.1); return Card( elevation: SpacingTokens.elevationSm, shadowColor: AppColors.borderDark.withOpacity(0.1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), child: Padding( padding: const EdgeInsets.all(SpacingTokens.lg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ // Header avec icône et flèche Row( children: [ // Icône avec background coloré Container( padding: const EdgeInsets.all(SpacingTokens.sm), decoration: BoxDecoration( color: effectiveIconBgColor, borderRadius: BorderRadius.circular(SpacingTokens.radiusSm), ), child: Icon( icon, color: effectiveIconColor, size: 18, ), ), const Spacer(), // Flèche si cliquable if (onTap != null) Icon( Icons.arrow_forward_ios, size: 16, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, ), ], ), const SizedBox(height: SpacingTokens.md), // Titre Text( title, style: AppTypography.badgeText.copyWith( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, ), ), const SizedBox(height: SpacingTokens.sm), // Valeur Text( value, style: AppTypography.headerSmall.copyWith( color: isDark ? AppColors.textPrimaryDark : AppColors.textPrimary, ), ), // Sous-titre optionnel if (subtitle != null) ...[ const SizedBox(height: SpacingTokens.sm), Text( subtitle!, style: AppTypography.subtitleSmall.copyWith( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, ), ), ], ], ), ), ), ); } }