import 'package:flutter/material.dart'; import '../../core/constants/design_system.dart'; import 'animated_widgets.dart'; /// Widget moderne pour afficher un état vide avec illustration et animation. /// /// Ce widget affiche un état vide élégant avec : /// - Une illustration personnalisée (icône ou widget custom) /// - Un titre et une description /// - Un bouton d'action optionnel /// - Des animations fluides /// /// **Usage:** /// ```dart /// ModernEmptyState( /// illustration: EmptyStateIllustration.friends, /// title: 'Aucun ami trouvé', /// description: 'Commencez à ajouter des amis', /// actionLabel: 'Ajouter un ami', /// onAction: () => _addFriend(), /// ) /// ``` class ModernEmptyState extends StatelessWidget { const ModernEmptyState({ required this.illustration, required this.title, this.description, this.actionLabel, this.onAction, super.key, }); /// Type d'illustration à afficher final EmptyStateIllustration illustration; /// Titre principal final String title; /// Description optionnelle final String? description; /// Label du bouton d'action final String? actionLabel; /// Callback du bouton d'action final VoidCallback? onAction; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Center( child: SingleChildScrollView( padding: DesignSystem.paddingAll(DesignSystem.spacingXl), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Illustration animée FadeInWidget( duration: DesignSystem.durationMedium, child: PulseAnimation( duration: const Duration(seconds: 2), child: _buildIllustration(theme), ), ), const SizedBox(height: 32), // Titre FadeInWidget( delay: const Duration(milliseconds: 200), duration: DesignSystem.durationMedium, child: Text( title, style: theme.textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onSurface, ), textAlign: TextAlign.center, ), ), // Description if (description != null) ...[ const SizedBox(height: 12), FadeInWidget( delay: const Duration(milliseconds: 300), duration: DesignSystem.durationMedium, child: Text( description!, style: theme.textTheme.bodyLarge?.copyWith( color: theme.colorScheme.onSurface.withOpacity(0.7), ), textAlign: TextAlign.center, ), ), ], // Bouton d'action if (actionLabel != null && onAction != null) ...[ const SizedBox(height: 32), FadeInWidget( delay: const Duration(milliseconds: 400), duration: DesignSystem.durationMedium, child: AnimatedScaleButton( onTap: onAction!, child: ElevatedButton.icon( onPressed: onAction, icon: const Icon(Icons.add), label: Text(actionLabel!), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 16, ), shape: RoundedRectangleBorder( borderRadius: DesignSystem.borderRadiusMd, ), ), ), ), ), ], ], ), ), ); } /// Construit l'illustration selon le type Widget _buildIllustration(ThemeData theme) { final config = _getIllustrationConfig(illustration); return Container( width: 200, height: 200, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ config.color.withOpacity(0.1), config.color.withOpacity(0.02), ], ), ), child: Center( child: Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, color: config.color.withOpacity(0.15), ), child: Icon( config.icon, size: 64, color: config.color, ), ), ), ); } /// Retourne la configuration de l'illustration _IllustrationConfig _getIllustrationConfig(EmptyStateIllustration type) { switch (type) { case EmptyStateIllustration.friends: return _IllustrationConfig( icon: Icons.people_outline, color: Colors.blue, ); case EmptyStateIllustration.requests: return _IllustrationConfig( icon: Icons.person_add_outlined, color: Colors.orange, ); case EmptyStateIllustration.events: return _IllustrationConfig( icon: Icons.event_note_outlined, color: Colors.purple, ); case EmptyStateIllustration.notifications: return _IllustrationConfig( icon: Icons.notifications_none_outlined, color: Colors.teal, ); case EmptyStateIllustration.messages: return _IllustrationConfig( icon: Icons.chat_bubble_outline, color: Colors.green, ); case EmptyStateIllustration.search: return _IllustrationConfig( icon: Icons.search_off_outlined, color: Colors.grey, ); case EmptyStateIllustration.social: return _IllustrationConfig( icon: Icons.forum_outlined, color: Colors.pink, ); case EmptyStateIllustration.reservations: return _IllustrationConfig( icon: Icons.bookmark_border_outlined, color: Colors.amber, ); case EmptyStateIllustration.establishments: return _IllustrationConfig( icon: Icons.store_outlined, color: Colors.deepOrange, ); } } } /// Types d'illustrations disponibles pour les états vides enum EmptyStateIllustration { friends, requests, events, notifications, messages, search, social, reservations, establishments, } /// Configuration d'une illustration class _IllustrationConfig { const _IllustrationConfig({ required this.icon, required this.color, }); final IconData icon; final Color color; }