import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../shared/theme/app_theme.dart'; import '../../../../shared/widgets/custom_text_field.dart'; /// Widget de recherche avancée pour les membres class MembresAdvancedSearch extends StatefulWidget { const MembresAdvancedSearch({ super.key, required this.onSearch, this.initialFilters, }); final Function(Map) onSearch; final Map? initialFilters; @override State createState() => _MembresAdvancedSearchState(); } class _MembresAdvancedSearchState extends State { final _formKey = GlobalKey(); // Contrôleurs de texte final _nomController = TextEditingController(); final _prenomController = TextEditingController(); final _emailController = TextEditingController(); final _telephoneController = TextEditingController(); final _numeroMembreController = TextEditingController(); final _professionController = TextEditingController(); final _villeController = TextEditingController(); // Filtres de statut bool? _actifFilter; // Filtres de date DateTime? _dateAdhesionDebut; DateTime? _dateAdhesionFin; DateTime? _dateNaissanceDebut; DateTime? _dateNaissanceFin; // Filtres d'âge int? _ageMin; int? _ageMax; @override void initState() { super.initState(); _initializeFilters(); } void _initializeFilters() { if (widget.initialFilters != null) { final filters = widget.initialFilters!; _nomController.text = filters['nom'] ?? ''; _prenomController.text = filters['prenom'] ?? ''; _emailController.text = filters['email'] ?? ''; _telephoneController.text = filters['telephone'] ?? ''; _numeroMembreController.text = filters['numeroMembre'] ?? ''; _professionController.text = filters['profession'] ?? ''; _villeController.text = filters['ville'] ?? ''; _actifFilter = filters['actif']; _dateAdhesionDebut = filters['dateAdhesionDebut']; _dateAdhesionFin = filters['dateAdhesionFin']; _dateNaissanceDebut = filters['dateNaissanceDebut']; _dateNaissanceFin = filters['dateNaissanceFin']; _ageMin = filters['ageMin']; _ageMax = filters['ageMax']; } } @override void dispose() { _nomController.dispose(); _prenomController.dispose(); _emailController.dispose(); _telephoneController.dispose(); _numeroMembreController.dispose(); _professionController.dispose(); _villeController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // En-tête _buildHeader(), const SizedBox(height: 20), // Contenu scrollable Flexible( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Informations personnelles _buildSection( 'Informations personnelles', Icons.person, [ Row( children: [ Expanded( child: CustomTextField( controller: _nomController, label: 'Nom', prefixIcon: Icons.person_outline, ), ), const SizedBox(width: 12), Expanded( child: CustomTextField( controller: _prenomController, label: 'Prénom', prefixIcon: Icons.person_outline, ), ), ], ), const SizedBox(height: 12), CustomTextField( controller: _numeroMembreController, label: 'Numéro de membre', prefixIcon: Icons.badge, ), const SizedBox(height: 12), CustomTextField( controller: _professionController, label: 'Profession', prefixIcon: Icons.work, ), ], ), const SizedBox(height: 20), // Contact et localisation _buildSection( 'Contact et localisation', Icons.contact_phone, [ CustomTextField( controller: _emailController, label: 'Email', prefixIcon: Icons.email, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 12), CustomTextField( controller: _telephoneController, label: 'Téléphone', prefixIcon: Icons.phone, keyboardType: TextInputType.phone, ), const SizedBox(height: 12), CustomTextField( controller: _villeController, label: 'Ville', prefixIcon: Icons.location_city, ), ], ), const SizedBox(height: 20), // Statut et dates _buildSection( 'Statut et dates', Icons.calendar_today, [ _buildStatusFilter(), const SizedBox(height: 16), _buildDateRangeFilter( 'Période d\'adhésion', _dateAdhesionDebut, _dateAdhesionFin, (debut, fin) { setState(() { _dateAdhesionDebut = debut; _dateAdhesionFin = fin; }); }, ), const SizedBox(height: 16), _buildDateRangeFilter( 'Période de naissance', _dateNaissanceDebut, _dateNaissanceFin, (debut, fin) { setState(() { _dateNaissanceDebut = debut; _dateNaissanceFin = fin; }); }, ), const SizedBox(height: 16), _buildAgeRangeFilter(), ], ), ], ), ), ), const SizedBox(height: 20), // Boutons d'action _buildActionButtons(), ], ), ), ); } Widget _buildHeader() { return Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppTheme.primaryColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.search, color: AppTheme.primaryColor, size: 24, ), ), const SizedBox(width: 12), const Expanded( child: Text( 'Recherche avancée', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), ), IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.close), color: AppTheme.textSecondary, ), ], ); } Widget _buildSection(String title, IconData icon, List children) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( icon, color: AppTheme.primaryColor, size: 20, ), const SizedBox(width: 8), Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), ), ], ), const SizedBox(height: 12), ...children, ], ); } Widget _buildStatusFilter() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Statut du membre', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.textPrimary, ), ), const SizedBox(height: 8), Row( children: [ Expanded( child: RadioListTile( title: const Text('Tous', style: TextStyle(fontSize: 14)), value: null, groupValue: _actifFilter, onChanged: (value) { setState(() { _actifFilter = value; }); }, dense: true, contentPadding: EdgeInsets.zero, ), ), Expanded( child: RadioListTile( title: const Text('Actifs', style: TextStyle(fontSize: 14)), value: true, groupValue: _actifFilter, onChanged: (value) { setState(() { _actifFilter = value; }); }, dense: true, contentPadding: EdgeInsets.zero, ), ), Expanded( child: RadioListTile( title: const Text('Inactifs', style: TextStyle(fontSize: 14)), value: false, groupValue: _actifFilter, onChanged: (value) { setState(() { _actifFilter = value; }); }, dense: true, contentPadding: EdgeInsets.zero, ), ), ], ), ], ); } Widget _buildDateRangeFilter( String title, DateTime? dateDebut, DateTime? dateFin, Function(DateTime?, DateTime?) onChanged, ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.textPrimary, ), ), const SizedBox(height: 8), Row( children: [ Expanded( child: InkWell( onTap: () => _selectDate(context, dateDebut, (date) { onChanged(date, dateFin); }), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), decoration: BoxDecoration( border: Border.all(color: AppTheme.borderColor), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon( Icons.calendar_today, color: AppTheme.textSecondary, size: 16, ), const SizedBox(width: 8), Text( dateDebut != null ? DateFormat('dd/MM/yyyy').format(dateDebut) : 'Date début', style: TextStyle( fontSize: 14, color: dateDebut != null ? AppTheme.textPrimary : AppTheme.textSecondary, ), ), ], ), ), ), ), const SizedBox(width: 12), Expanded( child: InkWell( onTap: () => _selectDate(context, dateFin, (date) { onChanged(dateDebut, date); }), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), decoration: BoxDecoration( border: Border.all(color: AppTheme.borderColor), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon( Icons.calendar_today, color: AppTheme.textSecondary, size: 16, ), const SizedBox(width: 8), Text( dateFin != null ? DateFormat('dd/MM/yyyy').format(dateFin) : 'Date fin', style: TextStyle( fontSize: 14, color: dateFin != null ? AppTheme.textPrimary : AppTheme.textSecondary, ), ), ], ), ), ), ), ], ), ], ); } Widget _buildAgeRangeFilter() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Tranche d\'âge', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppTheme.textPrimary, ), ), const SizedBox(height: 8), Row( children: [ Expanded( child: TextFormField( initialValue: _ageMin?.toString(), decoration: InputDecoration( labelText: 'Âge minimum', border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), ), keyboardType: TextInputType.number, onChanged: (value) { _ageMin = int.tryParse(value); }, ), ), const SizedBox(width: 12), Expanded( child: TextFormField( initialValue: _ageMax?.toString(), decoration: InputDecoration( labelText: 'Âge maximum', border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), ), keyboardType: TextInputType.number, onChanged: (value) { _ageMax = int.tryParse(value); }, ), ), ], ), ], ); } Widget _buildActionButtons() { return Row( children: [ Expanded( child: OutlinedButton( onPressed: _clearFilters, style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), side: BorderSide(color: AppTheme.borderColor), ), child: const Text('Effacer'), ), ), const SizedBox(width: 12), Expanded( flex: 2, child: ElevatedButton( onPressed: _performSearch, style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primaryColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), ), child: const Text('Rechercher'), ), ), ], ); } Future _selectDate( BuildContext context, DateTime? initialDate, Function(DateTime?) onDateSelected, ) async { final date = await showDatePicker( context: context, initialDate: initialDate ?? DateTime.now(), firstDate: DateTime(1900), lastDate: DateTime.now(), ); if (date != null) { onDateSelected(date); } } void _clearFilters() { setState(() { _nomController.clear(); _prenomController.clear(); _emailController.clear(); _telephoneController.clear(); _numeroMembreController.clear(); _professionController.clear(); _villeController.clear(); _actifFilter = null; _dateAdhesionDebut = null; _dateAdhesionFin = null; _dateNaissanceDebut = null; _dateNaissanceFin = null; _ageMin = null; _ageMax = null; }); } void _performSearch() { final filters = {}; // Ajout des filtres texte if (_nomController.text.isNotEmpty) { filters['nom'] = _nomController.text; } if (_prenomController.text.isNotEmpty) { filters['prenom'] = _prenomController.text; } if (_emailController.text.isNotEmpty) { filters['email'] = _emailController.text; } if (_telephoneController.text.isNotEmpty) { filters['telephone'] = _telephoneController.text; } if (_numeroMembreController.text.isNotEmpty) { filters['numeroMembre'] = _numeroMembreController.text; } if (_professionController.text.isNotEmpty) { filters['profession'] = _professionController.text; } if (_villeController.text.isNotEmpty) { filters['ville'] = _villeController.text; } // Ajout des filtres de statut if (_actifFilter != null) { filters['actif'] = _actifFilter; } // Ajout des filtres de date if (_dateAdhesionDebut != null) { filters['dateAdhesionDebut'] = _dateAdhesionDebut; } if (_dateAdhesionFin != null) { filters['dateAdhesionFin'] = _dateAdhesionFin; } if (_dateNaissanceDebut != null) { filters['dateNaissanceDebut'] = _dateNaissanceDebut; } if (_dateNaissanceFin != null) { filters['dateNaissanceFin'] = _dateNaissanceFin; } // Ajout des filtres d'âge if (_ageMin != null) { filters['ageMin'] = _ageMin; } if (_ageMax != null) { filters['ageMax'] = _ageMax; } widget.onSearch(filters); Navigator.of(context).pop(); } }