import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:travel_mate/components/home/create_trip_content.dart'; import '../../providers/user_provider.dart'; import '../../services/trip_service.dart'; import '../../models/trip.dart'; import '../home/show_trip_details_content.dart'; class HomeContent extends StatefulWidget { const HomeContent({super.key}); @override State createState() => _HomeContentState(); } class _HomeContentState extends State { final TripService _tripService = TripService(); @override Widget build(BuildContext context) { return Scaffold( body: Consumer( builder: (context, userProvider, child) { final user = userProvider.currentUser; if (user == null || user.id == null) { return Center( child: Text('Utilisateur non connecté'), ); } return StreamBuilder>( stream: _tripService.getTripsStreamByUser(user.id!, user.email), builder: (context, snapshot) { print('StreamBuilder - ConnectionState: ${snapshot.connectionState}'); print('StreamBuilder - HasError: ${snapshot.hasError}'); print('StreamBuilder - Data: ${snapshot.data?.length ?? 0} trips'); if (snapshot.connectionState == ConnectionState.waiting) { return _buildLoadingState(); } if (snapshot.hasError) { print('Erreur du stream: ${snapshot.error}'); return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error, size: 64, color: Colors.red), SizedBox(height: 16), Text('Erreur lors du chargement des voyages'), SizedBox(height: 8), Text('${snapshot.error}'), SizedBox(height: 8), ElevatedButton( onPressed: () { setState(() {}); // Forcer le rebuild }, child: Text('Réessayer'), ), ], ), ); } final trips = snapshot.data ?? []; print('Trips reçus du stream: ${trips.length}'); return RefreshIndicator( onRefresh: () async { setState(() {}); // Forcer le rebuild du stream }, child: SingleChildScrollView( physics: AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header de bienvenue Text( 'Bonjour ${user.prenom} !', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold), ), SizedBox(height: 8), Text( 'Vos voyages', style: TextStyle(fontSize: 16, color: Colors.grey[600]), ), SizedBox(height: 20), // Contenu principal trips.isEmpty ? _buildEmptyState() : _buildTripsList(trips), // Espacement en bas pour éviter que le FAB cache le contenu const SizedBox(height: 80), ], ), ), ); }, ); }, ), // FloatingActionButton floatingActionButton: FloatingActionButton( onPressed: () async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => CreateTripContent()), ); // Le stream se mettra à jour automatiquement if (result == true) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Voyage créé ! Il apparaîtra dans quelques secondes.'), backgroundColor: Colors.green, ), ); } }, backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, child: const Icon(Icons.add), ), floatingActionButtonLocation: FloatingActionButtonLocation.endFloat, ); } Widget _buildLoadingState() { return Center( child: Padding( padding: EdgeInsets.all(32), child: CircularProgressIndicator(), ), ); } Widget _buildEmptyState() { return Center( child: Padding( padding: EdgeInsets.all(32), child: Column( children: [ Icon( Icons.travel_explore, size: 64, color: Colors.grey[400], ), SizedBox(height: 16), Text( 'Aucun voyage pour le moment', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, color: Colors.grey[600], ), ), SizedBox(height: 8), Text( 'Créez votre premier voyage en appuyant sur le bouton +', textAlign: TextAlign.center, style: TextStyle( fontSize: 14, color: Colors.grey[500], ), ), ], ), ), ); } Widget _buildTripsList(List trips) { return Column( children: trips.map((trip) => _buildTravelCard(trip)).toList(), ); } Widget _buildTravelCard(Trip trip) { final colors = [Colors.blue, Colors.orange, Colors.green, Colors.purple, Colors.red]; final color = colors[trip.title.hashCode.abs() % colors.length]; // Détecter le thème actuel final isDarkMode = Theme.of(context).brightness == Brightness.dark; final textColor = isDarkMode ? Colors.white : Colors.black; final secondaryTextColor = isDarkMode ? Colors.white70 : Colors.grey[700]; final iconColor = isDarkMode ? Colors.white70 : Colors.grey[600]; return Card( elevation: 4, margin: const EdgeInsets.only(bottom: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: InkWell( onTap: () { Navigator.push( context, MaterialPageRoute(builder: (context) => ShowTripDetailsContent(trip: trip)), ); }, borderRadius: BorderRadius.circular(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image d'en-tête avec titre overlay Container( height: 150, decoration: BoxDecoration( borderRadius: const BorderRadius.vertical(top: Radius.circular(12)), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ color.withValues(alpha: 0.7), color.withValues(alpha: 0.9), ], ), ), child: Stack( children: [ Container( width: double.infinity, decoration: BoxDecoration( borderRadius: const BorderRadius.vertical( top: Radius.circular(12), ), color: color.withValues(alpha: 0.3), ), ), Positioned( bottom: 16, left: 16, right: 16, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( trip.title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 4), Row( children: [ const Icon( Icons.location_on, color: Colors.white, size: 16, ), const SizedBox(width: 4), Expanded( child: Text( trip.location, style: TextStyle( fontSize: 14, color: textColor, ), overflow: TextOverflow.ellipsis, ), ), ], ), ], ), ), ], ), ), // Contenu de la carte Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Description if (trip.description.isNotEmpty) ...[ Text( trip.description, style: TextStyle( fontSize: 14, color: secondaryTextColor, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), SizedBox(height: 12), ], // Dates Row( children: [ Icon( Icons.calendar_today, size: 16, color: iconColor, ), SizedBox(width: 8), Text( '${trip.startDate.day}/${trip.startDate.month}/${trip.startDate.year} - ${trip.endDate.day}/${trip.endDate.month}/${trip.endDate.year}', style: TextStyle( fontSize: 14, color: iconColor, fontWeight: FontWeight.w500, ), ), ], ), SizedBox(height: 12), // Participants Row( children: [ Icon(Icons.group, size: 16, color: iconColor), SizedBox(width: 8), Text( '${trip.participants.length} participant${trip.participants.length > 1 ? 's' : ''}', style: TextStyle( fontSize: 14, color: iconColor, fontWeight: FontWeight.w500, ), ), ], ), SizedBox(height: 12), // Budget et statut Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (trip.budget! > 0) Row( children: [ Icon(Icons.euro, size: 16, color: iconColor), SizedBox(width: 8), Text( 'Budget: ${trip.budget?.toStringAsFixed(2)}€', style: TextStyle( fontSize: 14, color: iconColor, fontWeight: FontWeight.w500, ), ), ], ), Container( padding: EdgeInsets.symmetric( horizontal: 8, vertical: 4, ), decoration: BoxDecoration( color: _getStatusColor(trip).withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Text( _getStatusText(trip), style: TextStyle( fontSize: 12, color: _getStatusColor(trip), fontWeight: FontWeight.w500, ), ), ), ], ), ], ), ), ], ), ), ); } Color _getStatusColor(Trip trip) { final now = DateTime.now(); if (trip.endDate.isBefore(now)) { return Colors.grey; } else if (trip.startDate.isBefore(now) && trip.endDate.isAfter(now)) { return Colors.green; } else { return Colors.blue; } } String _getStatusText(Trip trip) { final now = DateTime.now(); if (trip.endDate.isBefore(now)) { return 'Terminé'; } else if (trip.startDate.isBefore(now) && trip.endDate.isAfter(now)) { return 'En cours'; } else { return 'À venir'; } } }