import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:travel_mate/data/models/trip.dart'; import '../../blocs/user/user_bloc.dart'; import '../../blocs/user/user_state.dart' as user_state; import '../../blocs/trip/trip_bloc.dart'; import '../../blocs/trip/trip_event.dart'; import '../../blocs/group/group_bloc.dart'; import '../../blocs/group/group_event.dart'; import '../../data/models/group.dart'; import '../../services/user_service.dart'; class CreateTripContent extends StatefulWidget { const CreateTripContent({super.key}); @override State createState() => _CreateTripContentState(); } class _CreateTripContentState extends State { final _formKey = GlobalKey(); final _titleController = TextEditingController(); final _descriptionController = TextEditingController(); final _locationController = TextEditingController(); final _budgetController = TextEditingController(); final _userService = UserService(); DateTime? _startDate; DateTime? _endDate; bool _isLoading = false; final List _participants = []; final _participantController = TextEditingController(); @override void dispose() { _titleController.dispose(); _descriptionController.dispose(); _locationController.dispose(); _budgetController.dispose(); _participantController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, userState) { if (userState is! user_state.UserLoaded) { return Scaffold( appBar: AppBar(title: Text('Créer un voyage')), body: Center(child: Text('Veuillez vous connecter')), ); } return Scaffold( appBar: AppBar( title: Text('Créer un voyage'), backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, ), body: SingleChildScrollView( padding: EdgeInsets.all(16), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSectionTitle('Informations générales'), SizedBox(height: 16), TextFormField( controller: _titleController, validator: (value) { if (value == null || value.trim().isEmpty) { return 'Titre requis'; } return null; }, decoration: InputDecoration( labelText: 'Titre du voyage *', hintText: 'ex: Voyage à Paris', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixIcon: Icon(Icons.travel_explore), ), ), SizedBox(height: 16), TextFormField( controller: _descriptionController, maxLines: 3, decoration: InputDecoration( labelText: 'Description', hintText: 'Décrivez votre voyage...', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixIcon: Icon(Icons.description), ), ), SizedBox(height: 16), TextFormField( controller: _locationController, validator: (value) { if (value == null || value.trim().isEmpty) { return 'Destination requise'; } return null; }, decoration: InputDecoration( labelText: 'Destination *', hintText: 'ex: Paris, France', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixIcon: Icon(Icons.location_on), ), ), SizedBox(height: 24), _buildSectionTitle('Dates du voyage'), SizedBox(height: 16), Row( children: [ Expanded( child: _buildDateField( label: 'Date de début *', date: _startDate, onTap: () => _selectStartDate(context), ), ), SizedBox(width: 16), Expanded( child: _buildDateField( label: 'Date de fin *', date: _endDate, onTap: () => _selectEndDate(context), ), ), ], ), SizedBox(height: 24), _buildSectionTitle('Budget'), SizedBox(height: 16), TextFormField( controller: _budgetController, keyboardType: TextInputType.numberWithOptions(decimal: true), decoration: InputDecoration( labelText: 'Budget estimé', hintText: 'ex: 1200.50', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixIcon: Icon(Icons.euro), suffixText: '€', ), ), SizedBox(height: 24), _buildSectionTitle('Participants'), SizedBox(height: 8), Text( 'Ajoutez les emails des personnes que vous souhaitez inviter', style: TextStyle(color: Colors.grey[600], fontSize: 14), ), SizedBox(height: 16), Row( children: [ Expanded( child: TextFormField( controller: _participantController, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email du participant', hintText: 'ex: ami@email.com', border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), prefixIcon: Icon(Icons.person_add), ), ), ), SizedBox(width: 8), ElevatedButton( onPressed: _addParticipant, style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: EdgeInsets.all(16), ), child: Icon(Icons.add), ), ], ), SizedBox(height: 16), if (_participants.isNotEmpty) ...[ Text( 'Participants ajoutés (${_participants.length})', style: TextStyle(fontWeight: FontWeight.w500), ), SizedBox(height: 8), Container( width: double.infinity, padding: EdgeInsets.all(12), decoration: BoxDecoration( border: Border.all(color: Colors.grey[300]!), borderRadius: BorderRadius.circular(12), ), child: Wrap( spacing: 8, runSpacing: 8, children: _participants .map( (email) => Chip( label: Text(email, style: TextStyle(fontSize: 12)), deleteIcon: Icon(Icons.close, size: 18), onDeleted: () => _removeParticipant(email), backgroundColor: Theme.of( context, ).colorScheme.primary.withAlpha(25), ), ) .toList(), ), ), ], SizedBox(height: 32), SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _isLoading ? null : () => _saveTrip(userState.user), style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _isLoading ? CircularProgressIndicator(color: Colors.white) : Text( 'Créer le voyage', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), SizedBox(height: 20), ], ), ), ), ); }, ); } Widget _buildSectionTitle(String title) { return Text( title, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.grey[700], ), ); } Widget _buildDateField({ required String label, required DateTime? date, required VoidCallback onTap, }) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; final textColor = isDarkMode ? Colors.white : Colors.black; final labelColor = isDarkMode ? Colors.white70 : Colors.grey[600]; final iconColor = isDarkMode ? Colors.white70 : Colors.grey[600]; final placeholderColor = isDarkMode ? Colors.white38 : Colors.grey[500]; return InkWell( onTap: onTap, child: Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: isDarkMode ? Colors.white24 : Colors.grey[400]!), borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: TextStyle(fontSize: 12, color: labelColor)), SizedBox(height: 8), Row( children: [ Icon(Icons.calendar_today, size: 16, color: iconColor), SizedBox(width: 8), Text( date != null ? '${date.day}/${date.month}/${date.year}' : 'Sélectionner', style: TextStyle( fontSize: 16, color: date != null ? textColor : placeholderColor, ), ), ], ), ], ), ), ); } Future _selectStartDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, initialDate: _startDate ?? DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(Duration(days: 365 * 2)), ); if (picked != null) { setState(() { _startDate = picked; if (_endDate != null && _endDate!.isBefore(picked)) { _endDate = null; } }); } } Future _selectEndDate(BuildContext context) async { if (_startDate == null) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Veuillez d\'abord sélectionner la date de début')), ); } return; } final DateTime? picked = await showDatePicker( context: context, initialDate: _endDate ?? _startDate!.add(Duration(days: 1)), firstDate: _startDate!, lastDate: DateTime.now().add(Duration(days: 365 * 2)), ); if (picked != null && mounted) { setState(() { _endDate = picked; }); } } void _addParticipant() { final email = _participantController.text.trim(); if (email.isEmpty) return; final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); if (!emailRegex.hasMatch(email)) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Email invalide')) ); } return; } if (_participants.contains(email)) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Ce participant est déjà ajouté')) ); } return; } setState(() { _participants.add(email); _participantController.clear(); }); } void _removeParticipant(String email) { setState(() { _participants.remove(email); }); } Future _saveTrip(user_state.UserModel currentUser) async { if (!_formKey.currentState!.validate()) { return; } if (_startDate == null || _endDate == null) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Veuillez sélectionner les dates')), ); } return; } setState(() { _isLoading = true; }); try { // Convertir les emails en IDs List participantIds = await _changeUserEmailById(_participants); // Ajouter le créateur if (!participantIds.contains(currentUser.id)) { participantIds.insert(0, currentUser.id); } // Créer le voyage final trip = Trip( id: '', title: _titleController.text.trim(), description: _descriptionController.text.trim(), location: _locationController.text.trim(), startDate: _startDate!, endDate: _endDate!, budget: double.tryParse(_budgetController.text) ?? 0.0, createdBy: currentUser.id, participants: participantIds, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); // Créer le groupe final group = Group( id: '', name: _titleController.text.trim(), members: participantIds, ); // Utiliser les BLoCs pour créer context.read().add(TripCreateRequested(trip: trip)); context.read().add(GroupCreateRequested(group: group)); if (mounted) { Navigator.pop(context, true); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur: $e'), backgroundColor: Colors.red, ), ); } } finally { if (mounted) { setState(() { _isLoading = false; }); } } } Future> _changeUserEmailById(List participants) async { List ids = []; for (String email in participants) { try { final id = await _userService.getUserIdByEmail(email); if (id != null) { ids.add(id); } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Utilisateur non trouvé: $email'), backgroundColor: Colors.orange, ), ); } } } catch (e) { print('Erreur: $e'); } } return ids; } }