Files
afterwork/lib/presentation/screens/event/event_card.dart

290 lines
8.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:afterwork/data/datasources/event_remote_data_source.dart';
/// Widget pour afficher une carte d'événement.
class EventCard extends StatelessWidget {
final String eventId;
final EventRemoteDataSource eventRemoteDataSource;
final String userId;
final String userName;
final String userLastName;
final String profileImage;
final String name;
final String datePosted;
final String eventTitle;
final String eventDescription;
final String eventImageUrl;
final String eventStatus; // Ajout du statut de l'événement
final int reactionsCount;
final int commentsCount;
final int sharesCount;
final VoidCallback onReact;
final VoidCallback onComment;
final VoidCallback onShare;
final VoidCallback onParticipate;
final VoidCallback onMoreOptions;
final VoidCallback onCloseEvent;
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, // Initialisation du statut de l'événement
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,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AnimatedOpacity(
opacity: 1.0,
duration: const Duration(milliseconds: 300),
child: Dismissible(
key: ValueKey(eventId),
direction: DismissDirection.startToEnd,
onDismissed: (direction) => onCloseEvent(),
background: Container(
color: Colors.red,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 20.0),
child: const Icon(Icons.delete, 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),
_buildEventDetails(),
const SizedBox(height: 10),
_buildEventImage(),
const SizedBox(height: 10),
Divider(color: Colors.white.withOpacity(0.2)),
_buildInteractionRow(),
const SizedBox(height: 10),
_buildParticipateButton(),
],
),
),
),
],
),
),
);
}
/// Construire l'en-tête de la carte avec les informations de l'utilisateur.
Widget _buildHeader(BuildContext context) {
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: 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: onCloseEvent,
),
],
);
}
/// Afficher les détails de l'événement.
Widget _buildEventDetails() {
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.
Widget _buildEventImage() {
return ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.network(
eventImageUrl,
height: 180,
width: double.infinity,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
print('Erreur de chargement de l\'image: $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).
Widget _buildInteractionRow() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildIconButton(
icon: Icons.thumb_up_alt_outlined,
label: 'Réagir',
count: reactionsCount,
onPressed: onReact,
),
_buildIconButton(
icon: Icons.comment_outlined,
label: 'Commenter',
count: commentsCount,
onPressed: onComment,
),
_buildIconButton(
icon: Icons.share_outlined,
label: 'Partager',
count: sharesCount,
onPressed: onShare,
),
],
),
);
}
/// Bouton d'interaction personnalisé.
Widget _buildIconButton({
required IconData icon,
required String label,
required int count,
required VoidCallback onPressed,
}) {
return Expanded(
child: 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),
),
),
);
}
/// Bouton pour participer à l'événement.
Widget _buildParticipateButton() {
return ElevatedButton(
onPressed: eventStatus == 'CLOSED' ? null : onParticipate, // Désactiver si l'événement est fermé
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: Text(
eventStatus == 'CLOSED' ? 'Événement fermé' : 'Participer',
style: const TextStyle(color: Colors.white),
),
);
}
/// Construire un badge pour afficher le statut de l'événement.
Widget _buildStatusBadge() {
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,
),
),
);
}
}