/// Dialogue de création d'événement /// Formulaire complet pour créer un nouvel événement library create_event_dialog; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; import '../../bloc/evenements_bloc.dart'; import '../../bloc/evenements_event.dart'; import '../../data/models/evenement_model.dart'; /// Dialogue de création d'événement class CreateEventDialog extends StatefulWidget { const CreateEventDialog({super.key}); @override State createState() => _CreateEventDialogState(); } class _CreateEventDialogState extends State { final _formKey = GlobalKey(); // Contrôleurs de texte final _titreController = TextEditingController(); final _descriptionController = TextEditingController(); final _lieuController = TextEditingController(); final _adresseController = TextEditingController(); final _capaciteController = TextEditingController(); // Valeurs sélectionnées DateTime _dateDebut = DateTime.now().add(const Duration(days: 7)); DateTime? _dateFin; TypeEvenement _selectedType = TypeEvenement.autre; bool _inscriptionRequise = true; bool _visiblePublic = true; @override void dispose() { _titreController.dispose(); _descriptionController.dispose(); _lieuController.dispose(); _adresseController.dispose(); _capaciteController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Dialog( child: Container( width: MediaQuery.of(context).size.width * 0.9, constraints: const BoxConstraints(maxHeight: 600), child: Column( mainAxisSize: MainAxisSize.min, children: [ // En-tête Container( padding: const EdgeInsets.all(16), decoration: const BoxDecoration( color: Color(0xFF3B82F6), borderRadius: BorderRadius.only( topLeft: Radius.circular(4), topRight: Radius.circular(4), ), ), child: Row( children: [ const Icon(Icons.event, color: Colors.white), const SizedBox(width: 12), const Text( 'Créer un événement', style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), const Spacer(), IconButton( icon: const Icon(Icons.close, color: Colors.white), onPressed: () => Navigator.pop(context), ), ], ), ), // Formulaire Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Informations de base _buildSectionTitle('Informations de base'), const SizedBox(height: 12), TextFormField( controller: _titreController, decoration: const InputDecoration( labelText: 'Titre *', border: OutlineInputBorder(), prefixIcon: Icon(Icons.title), ), validator: (value) { if (value == null || value.isEmpty) { return 'Le titre est obligatoire'; } if (value.length < 3) { return 'Le titre doit contenir au moins 3 caractères'; } return null; }, ), const SizedBox(height: 12), TextFormField( controller: _descriptionController, decoration: const InputDecoration( labelText: 'Description', border: OutlineInputBorder(), prefixIcon: Icon(Icons.description), ), maxLines: 3, ), const SizedBox(height: 12), // Type d'événement DropdownButtonFormField( value: _selectedType, decoration: const InputDecoration( labelText: 'Type d\'événement *', border: OutlineInputBorder(), prefixIcon: Icon(Icons.category), ), items: TypeEvenement.values.map((type) { return DropdownMenuItem( value: type, child: Text(_getTypeLabel(type)), ); }).toList(), onChanged: (value) { setState(() { _selectedType = value!; }); }, ), const SizedBox(height: 16), // Dates _buildSectionTitle('Dates et horaires'), const SizedBox(height: 12), InkWell( onTap: () => _selectDateDebut(context), child: InputDecorator( decoration: const InputDecoration( labelText: 'Date de début *', border: OutlineInputBorder(), prefixIcon: Icon(Icons.calendar_today), ), child: Text( DateFormat('dd/MM/yyyy HH:mm').format(_dateDebut), ), ), ), const SizedBox(height: 12), InkWell( onTap: () => _selectDateFin(context), child: InputDecorator( decoration: const InputDecoration( labelText: 'Date de fin (optionnel)', border: OutlineInputBorder(), prefixIcon: Icon(Icons.event_available), ), child: Text( _dateFin != null ? DateFormat('dd/MM/yyyy HH:mm').format(_dateFin!) : 'Sélectionner une date', ), ), ), const SizedBox(height: 16), // Lieu _buildSectionTitle('Lieu'), const SizedBox(height: 12), TextFormField( controller: _lieuController, decoration: const InputDecoration( labelText: 'Lieu *', border: OutlineInputBorder(), prefixIcon: Icon(Icons.place), ), validator: (value) { if (value == null || value.isEmpty) { return 'Le lieu est obligatoire'; } return null; }, ), const SizedBox(height: 12), TextFormField( controller: _adresseController, decoration: const InputDecoration( labelText: 'Adresse complète', border: OutlineInputBorder(), prefixIcon: Icon(Icons.location_on), ), maxLines: 2, ), const SizedBox(height: 16), // Paramètres _buildSectionTitle('Paramètres'), const SizedBox(height: 12), TextFormField( controller: _capaciteController, decoration: const InputDecoration( labelText: 'Capacité maximale', border: OutlineInputBorder(), prefixIcon: Icon(Icons.people), hintText: 'Nombre de places disponibles', ), keyboardType: TextInputType.number, validator: (value) { if (value != null && value.isNotEmpty) { final capacite = int.tryParse(value); if (capacite == null || capacite <= 0) { return 'Capacité invalide'; } } return null; }, ), const SizedBox(height: 12), SwitchListTile( title: const Text('Inscription requise'), subtitle: const Text('Les participants doivent s\'inscrire'), value: _inscriptionRequise, onChanged: (value) { setState(() { _inscriptionRequise = value; }); }, ), SwitchListTile( title: const Text('Visible publiquement'), subtitle: const Text('L\'événement est visible par tous'), value: _visiblePublic, onChanged: (value) { setState(() { _visiblePublic = value; }); }, ), ], ), ), ), ), // Boutons d'action Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey[100], border: Border(top: BorderSide(color: Colors.grey[300]!)), ), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Annuler'), ), const SizedBox(width: 12), ElevatedButton( onPressed: _submitForm, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF3B82F6), foregroundColor: Colors.white, ), child: const Text('Créer l\'événement'), ), ], ), ), ], ), ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF3B82F6), ), ); } String _getTypeLabel(TypeEvenement type) { switch (type) { case TypeEvenement.assembleeGenerale: return 'Assemblée Générale'; case TypeEvenement.reunion: return 'Réunion'; case TypeEvenement.formation: return 'Formation'; case TypeEvenement.conference: return 'Conférence'; case TypeEvenement.atelier: return 'Atelier'; case TypeEvenement.seminaire: return 'Séminaire'; case TypeEvenement.evenementSocial: return 'Événement Social'; case TypeEvenement.manifestation: return 'Manifestation'; case TypeEvenement.celebration: return 'Célébration'; case TypeEvenement.autre: return 'Autre'; } } Future _selectDateDebut(BuildContext context) async { final DateTime? pickedDate = await showDatePicker( context: context, initialDate: _dateDebut, firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365 * 2)), ); if (pickedDate != null) { final TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(_dateDebut), ); if (pickedTime != null) { setState(() { _dateDebut = DateTime( pickedDate.year, pickedDate.month, pickedDate.day, pickedTime.hour, pickedTime.minute, ); }); } } } Future _selectDateFin(BuildContext context) async { final DateTime? pickedDate = await showDatePicker( context: context, initialDate: _dateFin ?? _dateDebut.add(const Duration(hours: 2)), firstDate: _dateDebut, lastDate: DateTime.now().add(const Duration(days: 365 * 2)), ); if (pickedDate != null) { final TimeOfDay? pickedTime = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(_dateFin ?? _dateDebut.add(const Duration(hours: 2))), ); if (pickedTime != null) { setState(() { _dateFin = DateTime( pickedDate.year, pickedDate.month, pickedDate.day, pickedTime.hour, pickedTime.minute, ); }); } } } void _submitForm() { if (_formKey.currentState!.validate()) { // Créer le modèle d'événement final evenement = EvenementModel( titre: _titreController.text, description: _descriptionController.text.isNotEmpty ? _descriptionController.text : null, dateDebut: _dateDebut, dateFin: _dateFin ?? _dateDebut.add(const Duration(hours: 2)), lieu: _lieuController.text, adresse: _adresseController.text.isNotEmpty ? _adresseController.text : null, type: _selectedType, maxParticipants: _capaciteController.text.isNotEmpty ? int.parse(_capaciteController.text) : null, inscriptionRequise: _inscriptionRequise, estPublic: _visiblePublic, statut: StatutEvenement.planifie, ); // Envoyer l'événement au BLoC context.read().add(CreateEvenement(evenement)); // Fermer le dialogue Navigator.pop(context); // Afficher un message de succès ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Événement créé avec succès'), backgroundColor: Colors.green, ), ); } } }