import 'package:flutter/material.dart'; import 'package:afterwork/data/datasources/event_remote_data_source.dart'; /// Widget pour afficher une carte d'événement. /// Cette classe est utilisée pour afficher les détails d'un événement, /// incluant son titre, sa description, son image, et des actions possibles /// telles que réagir, commenter, partager, participer, et fermer ou rouvrir l'événement. class EventCard extends StatelessWidget { // Identifiant unique de l'événement final String eventId; // Source de données distante pour les opérations sur l'événement final EventRemoteDataSource eventRemoteDataSource; // Identifiant de l'utilisateur final String userId; // Nom de l'utilisateur final String userName; // Prénom de l'utilisateur final String userLastName; // URL de l'image de profil de l'utilisateur final String profileImage; // Nom complet de l'utilisateur (nom + prénom) final String name; // Date de publication de l'événement final String datePosted; // Titre de l'événement final String eventTitle; // Description de l'événement final String eventDescription; // URL de l'image de l'événement final String eventImageUrl; // Statut de l'événement (e.g., "OPEN", "CLOSED") final String eventStatus; // Catégorie de l'événement final String eventCategory; // Nombre de réactions à l'événement final int reactionsCount; // Nombre de commentaires sur l'événement final int commentsCount; // Nombre de partages de l'événement final int sharesCount; // Callback pour l'action "Réagir" final VoidCallback onReact; // Callback pour l'action "Commenter" final VoidCallback onComment; // Callback pour l'action "Partager" final VoidCallback onShare; // Callback pour l'action "Participer" final VoidCallback onParticipate; // Callback pour afficher plus d'options final VoidCallback onMoreOptions; // Callback pour fermer l'événement final VoidCallback onCloseEvent; // Callback pour rouvrir l'événement final VoidCallback onReopenEvent; const EventCard({ Key? key, required this.eventId, required this.eventRemoteDataSource, required this.userId, required this.userName, required this.userLastName, required this.profileImage, required this.name, required this.datePosted, required this.eventTitle, required this.eventDescription, required this.eventImageUrl, required this.eventStatus, required this.eventCategory, required this.reactionsCount, required this.commentsCount, required this.sharesCount, required this.onReact, required this.onComment, required this.onShare, required this.onParticipate, required this.onMoreOptions, required this.onCloseEvent, required this.onReopenEvent, }) : super(key: key); @override Widget build(BuildContext context) { // Log du rendu de la carte d'événement print('Rendu de l\'EventCard pour l\'événement $eventId avec statut $eventStatus'); return AnimatedOpacity( opacity: 1.0, duration: const Duration(milliseconds: 300), child: Dismissible( key: ValueKey(eventId), direction: eventStatus == 'CLOSED' ? DismissDirection.endToStart // Permet de rouvrir avec un swipe à gauche : DismissDirection.startToEnd, // Permet de fermer avec un swipe à droite onDismissed: (direction) { if (direction == DismissDirection.startToEnd) { // Log du déclenchement de la fermeture de l'événement print('Tentative de fermeture de l\'événement $eventId'); onCloseEvent(); } else if (direction == DismissDirection.endToStart && eventStatus == 'CLOSED') { // Log du déclenchement de la réouverture de l'événement print('Tentative de réouverture de l\'événement $eventId'); onReopenEvent(); } }, background: Container( color: Colors.red, alignment: Alignment.centerLeft, padding: const EdgeInsets.only(left: 20.0), child: const Icon(Icons.delete, color: Colors.white), ), secondaryBackground: Container( color: Colors.green, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 20.0), child: const Icon(Icons.replay, color: Colors.white), ), child: Stack( children: [ Card( color: const Color(0xFF2C2C3E), margin: const EdgeInsets.symmetric(vertical: 10.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15.0), ), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildHeader(context), const SizedBox(height: 10), _buildEventCategory(), const SizedBox(height: 5), _buildEventDetails(), const SizedBox(height: 10), _buildEventImage(), const SizedBox(height: 10), Divider(color: Colors.white.withOpacity(0.2)), _buildInteractionRow(), const SizedBox(height: 5), _buildParticipateButton(), ], ), ), ), ], ), ), ); } /// Construire l'en-tête de la carte avec les informations de l'utilisateur. /// Cette méthode affiche l'image de profil, le nom de l'utilisateur, la date /// de publication de l'événement, et le statut de l'événement. Widget _buildHeader(BuildContext context) { // Log du rendu de l'en-tête de la carte print('Rendu de l\'en-tête pour l\'événement $eventId'); return Row( children: [ CircleAvatar( backgroundImage: AssetImage(profileImage), radius: 25, ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( name, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), Row( children: [ Text( datePosted, style: const TextStyle(color: Colors.white70, fontSize: 14), ), const SizedBox(width: 10), _buildStatusBadge(), // Badge de statut aligné sur la même ligne que la date du post ], ), ], ), ), IconButton( icon: const Icon(Icons.more_vert, color: Colors.white), onPressed: () { // Log du déclenchement du bouton "Plus d'options" print('Plus d\'options déclenché pour l\'événement $eventId'); onMoreOptions(); }, ), if (eventStatus != 'CLOSED') // Masquer le bouton de fermeture si l'événement est fermé IconButton( icon: const Icon(Icons.close, color: Colors.white), onPressed: () { // Log du déclenchement du bouton de fermeture de l'événement print('Tentative de fermeture de l\'événement $eventId'); onCloseEvent(); }, ), ], ); } /// Afficher la catégorie de l'événement au-dessus du titre. /// Cette méthode affiche la catégorie en italique pour distinguer le type d'événement. Widget _buildEventCategory() { // Log du rendu de la catégorie de l'événement print('Affichage de la catégorie pour l\'événement $eventId: $eventCategory'); return Text( eventCategory, style: const TextStyle( color: Colors.blueAccent, fontSize: 14, fontStyle: FontStyle.italic, // Style en italique fontWeight: FontWeight.w400, // Titre fin ), ); } /// Afficher les détails de l'événement. /// Cette méthode affiche le titre et la description de l'événement. Widget _buildEventDetails() { // Log du rendu des détails de l'événement print('Affichage des détails pour l\'événement $eventId'); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( eventTitle, style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 5), Text( eventDescription, style: const TextStyle(color: Colors.white70, fontSize: 14), ), ], ); } /// Afficher l'image de l'événement. /// Cette méthode affiche l'image associée à l'événement. Widget _buildEventImage() { // Log du rendu de l'image de l'événement print('Affichage de l\'image pour l\'événement $eventId'); return ClipRRect( borderRadius: BorderRadius.circular(10.0), child: Image.network( eventImageUrl, height: 180, width: double.infinity, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { // Log de l'erreur lors du chargement de l'image print('Erreur de chargement de l\'image pour l\'événement $eventId: $error'); return Image.asset( 'lib/assets/images/placeholder.png', height: 180, width: double.infinity, fit: BoxFit.cover, ); }, ), ); } /// Afficher les icônes d'interaction (réagir, commenter, partager). /// Cette méthode affiche les boutons pour réagir, commenter, et partager l'événement. Widget _buildInteractionRow() { // Log du rendu de la ligne d'interaction de l'événement print('Affichage des interactions pour l\'événement $eventId'); return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), // Réduire le padding vertical child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, // Utiliser spaceAround pour réduire l'espace children: [ Expanded( child: _buildIconButton( icon: Icons.thumb_up_alt_outlined, label: 'Réagir', count: reactionsCount, onPressed: () { // Log de l'action "Réagir" print('Réaction à l\'événement $eventId'); onReact(); }, ), ), Expanded( child: _buildIconButton( icon: Icons.comment_outlined, label: 'Commenter', count: commentsCount, onPressed: () { // Log de l'action "Commenter" print('Commentaire sur l\'événement $eventId'); onComment(); }, ), ), Expanded( child: _buildIconButton( icon: Icons.share_outlined, label: 'Partager', count: sharesCount, onPressed: () { // Log de l'action "Partager" print('Partage de l\'événement $eventId'); onShare(); }, ), ), ], ), ); } /// Bouton d'interaction personnalisé. /// Cette méthode construit un bouton avec une icône et un label pour l'interaction. Widget _buildIconButton({ required IconData icon, required String label, required int count, required VoidCallback onPressed, }) { // Log de la construction du bouton d'interaction print('Construction du bouton $label pour l\'événement $eventId'); return TextButton.icon( onPressed: onPressed, icon: Icon(icon, color: const Color(0xFF1DBF73), size: 20), label: Text( '$label ($count)', style: const TextStyle(color: Colors.white70, fontSize: 12), overflow: TextOverflow.ellipsis, ), ); } /// Bouton pour participer à l'événement. /// Cette méthode construit un bouton qui permet de participer à l'événement. /// Si l'événement est fermé, le bouton est caché. Widget _buildParticipateButton() { // Log de la construction du bouton "Participer" print('Construction du bouton "Participer" pour l\'événement $eventId avec statut $eventStatus'); // Si l'événement est fermé, ne rien retourner (pas de bouton) if (eventStatus == 'CLOSED') { print('L\'événement $eventId est fermé, le bouton "Participer" est caché.'); return SizedBox.shrink(); // Retourne un widget vide pour ne pas occuper d'espace } // Sinon, retourner le bouton "Participer" return ElevatedButton( onPressed: onParticipate, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF1DBF73), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), padding: const EdgeInsets.symmetric(vertical: 12.0), minimumSize: const Size(double.infinity, 40), ), child: const Text( 'Participer', style: TextStyle(color: Colors.white), ), ); } /// Construire un badge pour afficher le statut de l'événement. /// Cette méthode affiche un badge avec le statut de l'événement ("OPEN" ou "CLOSED"). Widget _buildStatusBadge() { // Log de la construction du badge de statut print('Construction du badge de statut pour l\'événement $eventId: $eventStatus'); Color badgeColor; switch (eventStatus) { case 'CLOSED': badgeColor = Colors.redAccent; break; case 'OPEN': default: badgeColor = Colors.greenAccent; break; } return Container( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), decoration: BoxDecoration( color: badgeColor.withOpacity(0.7), borderRadius: BorderRadius.circular(8.0), ), child: Text( eventStatus.toUpperCase(), style: const TextStyle( color: Colors.white, fontSize: 10, // Réduction de la taille du texte fontWeight: FontWeight.bold, ), ), ); } }