import 'package:flutter/material.dart'; import '../../models/activity.dart'; /// Widget représentant une carte d'activité avec système de vote class ActivityCard extends StatelessWidget { final Activity activity; final String currentUserId; final Function(int) onVote; final VoidCallback? onAddToTrip; const ActivityCard({ super.key, required this.activity, required this.currentUserId, required this.onVote, this.onAddToTrip, }); @override Widget build(BuildContext context) { final userVote = activity.getUserVote(currentUserId); final totalVotes = activity.positiveVotes + activity.negativeVotes; final positivePercentage = totalVotes > 0 ? (activity.positiveVotes / totalVotes) : 0.0; return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image de l'activité if (activity.imageUrl != null) ...[ ClipRRect( borderRadius: const BorderRadius.vertical(top: Radius.circular(12)), child: Stack( children: [ Image.network( activity.imageUrl!, height: 160, width: double.infinity, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( height: 160, width: double.infinity, decoration: const BoxDecoration( color: Color(0xFFF5F5F5), borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), child: const Icon( Icons.image_not_supported, size: 48, color: Color(0xFF9E9E9E), ), ); }, ), // Badge catégorie (simplifié) if (activity.category.isNotEmpty) Positioned( top: 12, right: 12, child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.7), borderRadius: BorderRadius.circular(8), ), child: Text( activity.category, style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500, ), ), ), ), ], ), ), ] else ...[ // Placeholder si pas d'image Container( height: 160, width: double.infinity, decoration: const BoxDecoration( color: Color(0xFFF5F5F5), borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), child: const Icon( Icons.image_not_supported, size: 48, color: Color(0xFF9E9E9E), ), ), ], // Contenu de la carte Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Titre et rating Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Text( activity.name, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A), ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), if (activity.rating != null) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: const Color(0xFFFFF3CD), borderRadius: BorderRadius.circular(4), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.star, size: 12, color: Color(0xFFFFB400)), const SizedBox(width: 2), Text( activity.rating!.toStringAsFixed(1), style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xFFB8860B), ), ), ], ), ), ], ], ), const SizedBox(height: 8), // Description (simplifiée) Text( activity.description, style: const TextStyle( fontSize: 14, color: Color(0xFF6B6B6B), height: 1.4, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 12), // Adresse (si disponible) if (activity.address != null) ...[ Row( children: [ const Icon( Icons.location_on, size: 14, color: Color(0xFF9E9E9E), ), const SizedBox(width: 4), Expanded( child: Text( activity.address!, style: const TextStyle( fontSize: 12, color: Color(0xFF9E9E9E), ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 12), ], // Section vote avec barre de progression if (activity.id.isNotEmpty) ...[ // Barre de progression des votes Container( height: 6, decoration: BoxDecoration( color: const Color(0xFFE0E0E0), borderRadius: BorderRadius.circular(3), ), child: totalVotes > 0 ? Row( children: [ if (activity.positiveVotes > 0) Expanded( flex: activity.positiveVotes, child: Container( decoration: BoxDecoration( color: const Color(0xFF4CAF50), borderRadius: BorderRadius.only( topLeft: const Radius.circular(3), bottomLeft: const Radius.circular(3), topRight: activity.negativeVotes == 0 ? const Radius.circular(3) : Radius.zero, bottomRight: activity.negativeVotes == 0 ? const Radius.circular(3) : Radius.zero, ), ), ), ), if (activity.negativeVotes > 0) Expanded( flex: activity.negativeVotes, child: Container( decoration: BoxDecoration( color: const Color(0xFFF44336), borderRadius: BorderRadius.only( topLeft: activity.positiveVotes == 0 ? const Radius.circular(3) : Radius.zero, bottomLeft: activity.positiveVotes == 0 ? const Radius.circular(3) : Radius.zero, topRight: const Radius.circular(3), bottomRight: const Radius.circular(3), ), ), ), ), ], ) : null, ), const SizedBox(height: 8), // Stats et boutons de vote Row( children: [ // Stats des votes Text( totalVotes > 0 ? '${(positivePercentage * 100).round()}% positif • $totalVotes vote${totalVotes > 1 ? 's' : ''}' : 'Aucun vote', style: const TextStyle( fontSize: 12, color: Color(0xFF9E9E9E), ), ), const Spacer(), // Boutons de vote compacts Row( children: [ _buildCompactVoteButton( icon: Icons.thumb_up, isActive: userVote == 1, onTap: () => onVote(userVote == 1 ? 0 : 1), activeColor: const Color(0xFF4CAF50), ), const SizedBox(width: 8), _buildCompactVoteButton( icon: Icons.thumb_down, isActive: userVote == -1, onTap: () => onVote(userVote == -1 ? 0 : -1), activeColor: const Color(0xFFF44336), ), ], ), ], ), ] else ...[ // Pour les activités non sauvegardées Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(12), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.info_outline, size: 14, color: Color(0xFF9E9E9E), ), SizedBox(width: 4), Text( 'Ajoutez pour voter', style: TextStyle( fontSize: 12, color: Color(0xFF9E9E9E), ), ), ], ), ), const Spacer(), // Bouton d'ajout if (onAddToTrip != null) ElevatedButton.icon( onPressed: onAddToTrip, icon: const Icon(Icons.add, size: 16), label: const Text('Ajouter'), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF007AFF), foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), textStyle: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), ], ], ), ), ], ), ); } Widget _buildCompactVoteButton({ required IconData icon, required bool isActive, required VoidCallback onTap, required Color activeColor, }) { return GestureDetector( onTap: onTap, child: Container( width: 32, height: 32, decoration: BoxDecoration( color: isActive ? activeColor : const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(16), ), child: Icon( icon, size: 16, color: isActive ? Colors.white : const Color(0xFF9E9E9E), ), ), ); } }