import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../core/models/evenement_model.dart'; /// Widget carte pour afficher un événement class EvenementCard extends StatelessWidget { final EvenementModel evenement; final VoidCallback? onTap; final VoidCallback? onFavorite; final bool showActions; const EvenementCard({ super.key, required this.evenement, this.onTap, this.onFavorite, this.showActions = true, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final dateFormat = DateFormat('dd/MM/yyyy'); final timeFormat = DateFormat('HH:mm'); return Card( elevation: 2, margin: EdgeInsets.zero, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // En-tête avec type et statut Row( children: [ // Icône du type Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: theme.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Text( evenement.typeEvenement.icone, style: const TextStyle(fontSize: 20), ), ), const SizedBox(width: 12), // Type et statut Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( evenement.typeEvenement.libelle, style: theme.textTheme.bodySmall?.copyWith( color: theme.primaryColor, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 2), _buildStatutChip(context), ], ), ), // Actions if (showActions) ...[ if (onFavorite != null) IconButton( onPressed: onFavorite, icon: const Icon(Icons.favorite_border), iconSize: 20, ), PopupMenuButton( onSelected: (value) { switch (value) { case 'share': _shareEvenement(context); break; case 'calendar': _addToCalendar(context); break; } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'share', child: Row( children: [ Icon(Icons.share, size: 20), SizedBox(width: 8), Text('Partager'), ], ), ), const PopupMenuItem( value: 'calendar', child: Row( children: [ Icon(Icons.calendar_today, size: 20), SizedBox(width: 8), Text('Ajouter au calendrier'), ], ), ), ], child: const Icon(Icons.more_vert, size: 20), ), ], ], ), const SizedBox(height: 12), // Titre Text( evenement.titre, style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), if (evenement.description != null) ...[ const SizedBox(height: 8), Text( evenement.description!, style: theme.textTheme.bodyMedium?.copyWith( color: Colors.grey[600], ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], const SizedBox(height: 12), // Informations date et lieu Row( children: [ // Date Expanded( child: Row( children: [ Icon( Icons.schedule, size: 16, color: Colors.grey[600], ), const SizedBox(width: 4), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( dateFormat.format(evenement.dateDebut), style: theme.textTheme.bodySmall?.copyWith( fontWeight: FontWeight.w500, ), ), Text( timeFormat.format(evenement.dateDebut), style: theme.textTheme.bodySmall?.copyWith( color: Colors.grey[600], ), ), ], ), ), ], ), ), // Lieu if (evenement.lieu != null) Expanded( child: Row( children: [ Icon( Icons.location_on, size: 16, color: Colors.grey[600], ), const SizedBox(width: 4), Expanded( child: Text( evenement.lieu!, style: theme.textTheme.bodySmall, maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ), ], ), // Informations supplémentaires if (evenement.prix != null || evenement.capaciteMax != null || evenement.inscriptionRequise) ...[ const SizedBox(height: 12), Wrap( spacing: 8, runSpacing: 4, children: [ // Prix if (evenement.prix != null) _buildInfoChip( context, evenement.prix! > 0 ? '${evenement.prix!.toStringAsFixed(0)} €' : 'Gratuit', Icons.euro, evenement.prix! > 0 ? Colors.orange : Colors.green, ), // Capacité if (evenement.capaciteMax != null) _buildInfoChip( context, '${evenement.capaciteMax} places', Icons.people, Colors.blue, ), // Inscription requise if (evenement.inscriptionRequise) _buildInfoChip( context, evenement.inscriptionsOuvertes ? 'Inscriptions ouvertes' : 'Inscriptions fermées', Icons.how_to_reg, evenement.inscriptionsOuvertes ? Colors.green : Colors.red, ), ], ), ], // Durée si disponible if (evenement.duree != null) ...[ const SizedBox(height: 8), Row( children: [ Icon( Icons.timer, size: 16, color: Colors.grey[600], ), const SizedBox(width: 4), Text( 'Durée: ${evenement.dureeFormatee}', style: theme.textTheme.bodySmall?.copyWith( color: Colors.grey[600], ), ), ], ), ], ], ), ), ), ); } Widget _buildStatutChip(BuildContext context) { final color = Color(int.parse( evenement.statut.couleur.substring(1), radix: 16, ) + 0xFF000000); return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.3)), ), child: Text( evenement.statut.libelle, style: TextStyle( fontSize: 11, fontWeight: FontWeight.w500, color: color, ), ), ); } Widget _buildInfoChip( BuildContext context, String label, IconData icon, Color color, ) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( icon, size: 14, color: color, ), const SizedBox(width: 4), Text( label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: color, ), ), ], ), ); } void _shareEvenement(BuildContext context) { // TODO: Implémenter le partage ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Partage - À implémenter')), ); } void _addToCalendar(BuildContext context) { // TODO: Implémenter l'ajout au calendrier ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Ajout au calendrier - À implémenter')), ); } }