import 'package:flutter/material.dart'; import '../../../../shared/models/membre_search_criteria.dart'; /// Formulaire de recherche de membres /// Widget réutilisable pour la saisie des critères de recherche class MembreSearchForm extends StatefulWidget { final MembreSearchCriteria initialCriteria; final Function(MembreSearchCriteria) onCriteriaChanged; final VoidCallback? onSearch; final VoidCallback? onClear; final bool isCompact; const MembreSearchForm({ super.key, this.initialCriteria = MembreSearchCriteria.empty, required this.onCriteriaChanged, this.onSearch, this.onClear, this.isCompact = false, }); @override State createState() => _MembreSearchFormState(); } class _MembreSearchFormState extends State { late TextEditingController _queryController; late TextEditingController _nomController; late TextEditingController _prenomController; late TextEditingController _emailController; late TextEditingController _telephoneController; String? _selectedStatut; List _selectedRoles = []; RangeValues _ageRange = const RangeValues(18, 65); bool _includeInactifs = false; bool _membreBureau = false; bool _responsable = false; @override void initState() { super.initState(); _initializeControllers(); _loadInitialCriteria(); } @override void dispose() { _queryController.dispose(); _nomController.dispose(); _prenomController.dispose(); _emailController.dispose(); _telephoneController.dispose(); super.dispose(); } void _initializeControllers() { _queryController = TextEditingController(); _nomController = TextEditingController(); _prenomController = TextEditingController(); _emailController = TextEditingController(); _telephoneController = TextEditingController(); // Écouter les changements pour mettre à jour les critères _queryController.addListener(_updateCriteria); _nomController.addListener(_updateCriteria); _prenomController.addListener(_updateCriteria); _emailController.addListener(_updateCriteria); _telephoneController.addListener(_updateCriteria); } void _loadInitialCriteria() { final criteria = widget.initialCriteria; _queryController.text = criteria.query ?? ''; _nomController.text = criteria.nom ?? ''; _prenomController.text = criteria.prenom ?? ''; _emailController.text = criteria.email ?? ''; _telephoneController.text = criteria.telephone ?? ''; _selectedStatut = criteria.statut; _selectedRoles = criteria.roles ?? []; _ageRange = RangeValues( criteria.ageMin?.toDouble() ?? 18, criteria.ageMax?.toDouble() ?? 65, ); _includeInactifs = criteria.includeInactifs; _membreBureau = criteria.membreBureau ?? false; _responsable = criteria.responsable ?? false; } @override Widget build(BuildContext context) { if (widget.isCompact) { return _buildCompactForm(); } return _buildFullForm(); } /// Formulaire compact pour recherche rapide Widget _buildCompactForm() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _queryController, decoration: InputDecoration( labelText: 'Rechercher un membre', hintText: 'Nom, prénom ou email...', prefixIcon: const Icon(Icons.search), suffixIcon: _queryController.text.isNotEmpty ? IconButton( icon: const Icon(Icons.clear), onPressed: () { _queryController.clear(); _updateCriteria(); }, ) : null, border: const OutlineInputBorder(), ), onSubmitted: (_) => widget.onSearch?.call(), ), const SizedBox(height: 12), Row( children: [ Expanded( child: DropdownButtonFormField( value: _selectedStatut, decoration: const InputDecoration( labelText: 'Statut', border: OutlineInputBorder(), isDense: true, ), items: const [ DropdownMenuItem(value: null, child: Text('Tous')), DropdownMenuItem(value: 'ACTIF', child: Text('Actif')), DropdownMenuItem(value: 'INACTIF', child: Text('Inactif')), ], onChanged: (value) { setState(() => _selectedStatut = value); _updateCriteria(); }, ), ), const SizedBox(width: 12), if (widget.onSearch != null) ElevatedButton.icon( onPressed: widget.onSearch, icon: const Icon(Icons.search), label: const Text('Rechercher'), ), ], ), ], ), ), ); } /// Formulaire complet avec tous les critères Widget _buildFullForm() { return Column( children: [ // Recherche générale _buildGeneralSearchSection(), const SizedBox(height: 16), // Critères détaillés _buildDetailedCriteriaSection(), const SizedBox(height: 16), // Filtres avancés _buildAdvancedFiltersSection(), const SizedBox(height: 16), // Boutons d'action _buildActionButtons(), ], ); } /// Section de recherche générale Widget _buildGeneralSearchSection() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Recherche Générale', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), TextField( controller: _queryController, decoration: const InputDecoration( labelText: 'Terme de recherche', hintText: 'Nom, prénom, email...', prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ), ], ), ), ); } /// Section des critères détaillés Widget _buildDetailedCriteriaSection() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Critères Détaillés', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: TextField( controller: _nomController, decoration: const InputDecoration( labelText: 'Nom', border: OutlineInputBorder(), ), ), ), const SizedBox(width: 12), Expanded( child: TextField( controller: _prenomController, decoration: const InputDecoration( labelText: 'Prénom', border: OutlineInputBorder(), ), ), ), ], ), const SizedBox(height: 16), TextField( controller: _emailController, decoration: const InputDecoration( labelText: 'Email', border: OutlineInputBorder(), ), ), const SizedBox(height: 16), Row( children: [ Expanded( child: TextField( controller: _telephoneController, decoration: const InputDecoration( labelText: 'Téléphone', border: OutlineInputBorder(), ), ), ), const SizedBox(width: 12), Expanded( child: DropdownButtonFormField( value: _selectedStatut, decoration: const InputDecoration( labelText: 'Statut', border: OutlineInputBorder(), ), items: const [ DropdownMenuItem(value: null, child: Text('Tous')), DropdownMenuItem(value: 'ACTIF', child: Text('Actif')), DropdownMenuItem(value: 'INACTIF', child: Text('Inactif')), DropdownMenuItem(value: 'SUSPENDU', child: Text('Suspendu')), DropdownMenuItem(value: 'RADIE', child: Text('Radié')), ], onChanged: (value) { setState(() => _selectedStatut = value); _updateCriteria(); }, ), ), ], ), ], ), ), ); } /// Section des filtres avancés Widget _buildAdvancedFiltersSection() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Filtres Avancés', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), // Tranche d'âge Text('Tranche d\'âge: ${_ageRange.start.round()}-${_ageRange.end.round()} ans'), RangeSlider( values: _ageRange, min: 18, max: 80, divisions: 62, labels: RangeLabels( '${_ageRange.start.round()}', '${_ageRange.end.round()}', ), onChanged: (values) { setState(() => _ageRange = values); _updateCriteria(); }, ), const SizedBox(height: 16), // Options booléennes CheckboxListTile( title: const Text('Inclure les membres inactifs'), value: _includeInactifs, onChanged: (value) { setState(() => _includeInactifs = value ?? false); _updateCriteria(); }, ), CheckboxListTile( title: const Text('Membres du bureau uniquement'), value: _membreBureau, onChanged: (value) { setState(() => _membreBureau = value ?? false); _updateCriteria(); }, ), CheckboxListTile( title: const Text('Responsables uniquement'), value: _responsable, onChanged: (value) { setState(() => _responsable = value ?? false); _updateCriteria(); }, ), ], ), ), ); } /// Boutons d'action Widget _buildActionButtons() { return Row( children: [ if (widget.onClear != null) Expanded( child: OutlinedButton.icon( onPressed: () { _clearForm(); widget.onClear?.call(); }, icon: const Icon(Icons.clear), label: const Text('Effacer'), ), ), if (widget.onClear != null && widget.onSearch != null) const SizedBox(width: 16), if (widget.onSearch != null) Expanded( flex: widget.onClear != null ? 2 : 1, child: ElevatedButton.icon( onPressed: widget.onSearch, icon: const Icon(Icons.search), label: const Text('Rechercher'), ), ), ], ); } /// Met à jour les critères de recherche void _updateCriteria() { final criteria = MembreSearchCriteria( query: _queryController.text.trim().isEmpty ? null : _queryController.text.trim(), nom: _nomController.text.trim().isEmpty ? null : _nomController.text.trim(), prenom: _prenomController.text.trim().isEmpty ? null : _prenomController.text.trim(), email: _emailController.text.trim().isEmpty ? null : _emailController.text.trim(), telephone: _telephoneController.text.trim().isEmpty ? null : _telephoneController.text.trim(), statut: _selectedStatut, roles: _selectedRoles.isEmpty ? null : _selectedRoles, ageMin: _ageRange.start.round(), ageMax: _ageRange.end.round(), membreBureau: _membreBureau ? true : null, responsable: _responsable ? true : null, includeInactifs: _includeInactifs, ); widget.onCriteriaChanged(criteria); } /// Efface le formulaire void _clearForm() { setState(() { _queryController.clear(); _nomController.clear(); _prenomController.clear(); _emailController.clear(); _telephoneController.clear(); _selectedStatut = null; _selectedRoles.clear(); _ageRange = const RangeValues(18, 65); _includeInactifs = false; _membreBureau = false; _responsable = false; }); _updateCriteria(); } }