import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../core/models/evenement_model.dart'; /// Page de détail d'un événement class EvenementDetailPage extends StatelessWidget { final EvenementModel evenement; const EvenementDetailPage({ super.key, required this.evenement, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final dateFormat = DateFormat('EEEE dd MMMM yyyy', 'fr_FR'); final timeFormat = DateFormat('HH:mm'); return Scaffold( body: CustomScrollView( slivers: [ // App Bar avec image de fond SliverAppBar( expandedHeight: 200, pinned: true, flexibleSpace: FlexibleSpaceBar( title: Text( evenement.titre, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, shadows: [ Shadow( offset: Offset(0, 1), blurRadius: 3, color: Colors.black54, ), ], ), ), background: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ theme.primaryColor, theme.primaryColor.withOpacity(0.8), ], ), ), child: Center( child: Text( evenement.typeEvenement.icone, style: const TextStyle(fontSize: 80), ), ), ), ), actions: [ IconButton( onPressed: () => _shareEvenement(context), icon: const Icon(Icons.share), ), PopupMenuButton( onSelected: (value) { switch (value) { case 'calendar': _addToCalendar(context); break; case 'favorite': _toggleFavorite(context); break; } }, itemBuilder: (context) => [ const PopupMenuItem( value: 'calendar', child: Row( children: [ Icon(Icons.calendar_today), SizedBox(width: 8), Text('Ajouter au calendrier'), ], ), ), const PopupMenuItem( value: 'favorite', child: Row( children: [ Icon(Icons.favorite_border), SizedBox(width: 8), Text('Ajouter aux favoris'), ], ), ), ], ), ], ), // Contenu principal SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Statut et type Row( children: [ _buildStatutChip(context), const SizedBox(width: 8), Chip( label: Text(evenement.typeEvenement.libelle), backgroundColor: theme.primaryColor.withOpacity(0.1), ), ], ), const SizedBox(height: 16), // Description if (evenement.description != null) ...[ Text( 'Description', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( evenement.description!, style: theme.textTheme.bodyMedium, ), const SizedBox(height: 24), ], // Informations pratiques _buildSectionTitle(context, 'Informations pratiques'), const SizedBox(height: 12), _buildInfoRow( context, Icons.schedule, 'Date et heure', '${dateFormat.format(evenement.dateDebut)}\n' '${timeFormat.format(evenement.dateDebut)}' '${evenement.dateFin != null ? ' - ${timeFormat.format(evenement.dateFin!)}' : ''}', ), if (evenement.lieu != null) _buildInfoRow( context, Icons.location_on, 'Lieu', evenement.lieu!, ), if (evenement.adresse != null) _buildInfoRow( context, Icons.map, 'Adresse', evenement.adresse!, ), if (evenement.duree != null) _buildInfoRow( context, Icons.timer, 'Durée', evenement.dureeFormatee, ), if (evenement.prix != null) _buildInfoRow( context, Icons.euro, 'Prix', evenement.prix! > 0 ? '${evenement.prix!.toStringAsFixed(0)} €' : 'Gratuit', ), if (evenement.capaciteMax != null) _buildInfoRow( context, Icons.people, 'Capacité', '${evenement.capaciteMax} personnes', ), const SizedBox(height: 24), // Inscription if (evenement.inscriptionRequise) ...[ _buildSectionTitle(context, 'Inscription'), const SizedBox(height: 12), if (evenement.inscriptionsOuvertes) ...[ Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.green.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.green.withOpacity(0.3)), ), child: Column( children: [ const Icon( Icons.check_circle, color: Colors.green, size: 32, ), const SizedBox(height: 8), const Text( 'Inscriptions ouvertes', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.green, ), ), if (evenement.dateLimiteInscription != null) ...[ const SizedBox(height: 4), Text( 'Jusqu\'au ${dateFormat.format(evenement.dateLimiteInscription!)}', style: TextStyle( color: Colors.green[700], fontSize: 12, ), ), ], ], ), ), ] else ...[ Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.red.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.red.withOpacity(0.3)), ), child: const Column( children: [ Icon( Icons.cancel, color: Colors.red, size: 32, ), SizedBox(height: 8), Text( 'Inscriptions fermées', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.red, ), ), ], ), ), ], const SizedBox(height: 24), ], // Instructions particulières if (evenement.instructionsParticulieres != null) ...[ _buildSectionTitle(context, 'Instructions particulières'), const SizedBox(height: 8), Text( evenement.instructionsParticulieres!, style: theme.textTheme.bodyMedium, ), const SizedBox(height: 24), ], // Matériel requis if (evenement.materielRequis != null) ...[ _buildSectionTitle(context, 'Matériel requis'), const SizedBox(height: 8), Text( evenement.materielRequis!, style: theme.textTheme.bodyMedium, ), const SizedBox(height: 24), ], // Contact organisateur if (evenement.contactOrganisateur != null) ...[ _buildSectionTitle(context, 'Contact organisateur'), const SizedBox(height: 8), Text( evenement.contactOrganisateur!, style: theme.textTheme.bodyMedium, ), const SizedBox(height: 24), ], // Espace pour le bouton flottant const SizedBox(height: 80), ], ), ), ), ], ), // Bouton d'action flottant floatingActionButton: evenement.inscriptionRequise && evenement.inscriptionsOuvertes ? FloatingActionButton.extended( onPressed: () => _inscrireAEvenement(context), icon: const Icon(Icons.how_to_reg), label: const Text('S\'inscrire'), ) : null, ); } Widget _buildStatutChip(BuildContext context) { final color = Color(int.parse( evenement.statut.couleur.substring(1), radix: 16, ) + 0xFF000000); return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(16), border: Border.all(color: color.withOpacity(0.3)), ), child: Text( evenement.statut.libelle, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: color, ), ), ); } Widget _buildSectionTitle(BuildContext context, String title) { return Text( title, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ); } Widget _buildInfoRow( BuildContext context, IconData icon, String label, String value, ) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon( icon, size: 20, color: Colors.grey[600], ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Colors.grey[600], fontWeight: FontWeight.w500, ), ), const SizedBox(height: 2), Text( value, style: Theme.of(context).textTheme.bodyMedium, ), ], ), ), ], ), ); } 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')), ); } void _toggleFavorite(BuildContext context) { // TODO: Implémenter les favoris ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Favoris - À implémenter')), ); } void _inscrireAEvenement(BuildContext context) { // TODO: Implémenter l'inscription ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Inscription - À implémenter')), ); } }