import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/user_provider.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(); DateTime? _startDate; DateTime? _endDate; bool _isLoading = false; // Liste des participants (emails) 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 Scaffold( appBar: AppBar( title: Text('Créer un voyage'), backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, actions: [ TextButton( onPressed: _isLoading ? null : _saveTrip, child: Text( 'Sauvegarder', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ), ], ), body: SingleChildScrollView( padding: EdgeInsets.all(16), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Titre du voyage _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), // Description 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), // Destination 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), // Dates _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), // Budget _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), // Participants _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), // Champ d'ajout de participant 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), // Liste des participants ajoutés 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), // Bouton de création SizedBox( width: double.infinity, height: 50, child: ElevatedButton( onPressed: _isLoading ? null : _saveTrip, 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, }) { return InkWell( onTap: onTap, child: Container( padding: EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: Colors.grey[400]!), borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), SizedBox(height: 8), Row( children: [ Icon(Icons.calendar_today, size: 16, color: Colors.grey[600]), SizedBox(width: 8), Text( date != null ? '${date.day}/${date.month}/${date.year}' : 'Sélectionner', style: TextStyle( fontSize: 16, color: date != null ? Colors.black : Colors.grey[500], ), ), ], ), ], ), ), ); } 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) { 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) { setState(() { _endDate = picked; }); } } void _addParticipant() { final email = _participantController.text.trim(); if (email.isEmpty) return; // Validation email simple final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); if (!emailRegex.hasMatch(email)) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text('Email invalide'))); return; } // Vérifier si l'email existe déjà if (_participants.contains(email)) { 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() async { if (!_formKey.currentState!.validate()) { return; } if (_startDate == null || _endDate == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Veuillez sélectionner les dates')), ); return; } setState(() { _isLoading = true; }); try { // TODO: Implémenter la sauvegarde du voyage await Future.delayed(Duration(seconds: 2)); // Simulation ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Voyage créé avec succès !'), backgroundColor: Colors.green, ), ); Navigator.pop(context); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur lors de la création: $e'), backgroundColor: Colors.red, ), ); } finally { setState(() { _isLoading = false; }); } } }