feat: Ajout filtres membre/secteur dans historique admin (#42)
- Ajout de 2 dropdowns de filtres dans history_page.dart (admin uniquement) - Filtre par membre (fkUser) : liste dynamique depuis passages - Filtre par secteur (fkSector) : liste dynamique depuis passages - Valeurs par défaut : "Tous" pour chaque filtre - Tri alphabétique des dropdowns - Mise à jour du planning : #42 validée (26/01) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
140
app/lib/presentation/pages/history_page.dart
Normal file → Executable file
140
app/lib/presentation/pages/history_page.dart
Normal file → Executable file
@@ -55,6 +55,8 @@ class _HistoryContentState extends State<HistoryContent> {
|
||||
String _selectedTypeFilter = 'Tous les types';
|
||||
String _searchQuery = '';
|
||||
int? selectedTypeId;
|
||||
int? _selectedMemberId; // null = "Tous" (admin uniquement)
|
||||
int? _selectedSectorId; // null = "Tous" (admin uniquement)
|
||||
|
||||
// Contrôleur de recherche
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
@@ -221,6 +223,20 @@ class _HistoryContentState extends State<HistoryContent> {
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par membre (admin uniquement)
|
||||
if (isAdmin && _selectedMemberId != null) {
|
||||
if (passage.fkUser != _selectedMemberId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par secteur (admin uniquement)
|
||||
if (isAdmin && _selectedSectorId != null) {
|
||||
if (passage.fkSector != _selectedSectorId) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par recherche textuelle
|
||||
if (_searchQuery.isNotEmpty) {
|
||||
final query = _searchQuery.toLowerCase();
|
||||
@@ -302,6 +318,7 @@ class _HistoryContentState extends State<HistoryContent> {
|
||||
children: [
|
||||
// Barre de recherche
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: TextFormField(
|
||||
controller: _searchController,
|
||||
decoration: const InputDecoration(
|
||||
@@ -319,6 +336,21 @@ class _HistoryContentState extends State<HistoryContent> {
|
||||
},
|
||||
),
|
||||
),
|
||||
// Filtres admin uniquement
|
||||
if (isAdmin) ...[
|
||||
const SizedBox(width: 8),
|
||||
// Filtre par membre
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: _buildMemberDropdown(),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// Filtre par secteur
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: _buildSectorDropdown(),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -563,4 +595,112 @@ class _HistoryContentState extends State<HistoryContent> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construit le dropdown de sélection de membre (admin uniquement)
|
||||
Widget _buildMemberDropdown() {
|
||||
// Récupérer les membres uniques depuis les passages de l'opération courante
|
||||
final memberIds = <int>{};
|
||||
final memberNames = <int, String>{};
|
||||
|
||||
for (final passage in _originalPassages) {
|
||||
if (!memberIds.contains(passage.fkUser)) {
|
||||
memberIds.add(passage.fkUser);
|
||||
// Utiliser le nom du passage (qui contient prenom + nom)
|
||||
memberNames[passage.fkUser] = passage.name.isNotEmpty ? passage.name : 'Membre #${passage.fkUser}';
|
||||
}
|
||||
}
|
||||
|
||||
// Trier par nom
|
||||
final sortedMembers = memberIds.toList()
|
||||
..sort((a, b) => (memberNames[a] ?? '').compareTo(memberNames[b] ?? ''));
|
||||
|
||||
return DropdownButtonFormField<int?>(
|
||||
value: _selectedMemberId,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
isDense: true,
|
||||
labelText: 'Membre',
|
||||
prefixIcon: Icon(Icons.person, size: 20),
|
||||
),
|
||||
items: [
|
||||
const DropdownMenuItem<int?>(
|
||||
value: null,
|
||||
child: Text('Tous'),
|
||||
),
|
||||
...sortedMembers.map((memberId) {
|
||||
return DropdownMenuItem<int?>(
|
||||
value: memberId,
|
||||
child: Text(
|
||||
memberNames[memberId] ?? 'Membre #$memberId',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
_selectedMemberId = newValue;
|
||||
});
|
||||
_applyFilters();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Construit le dropdown de sélection de secteur (admin uniquement)
|
||||
Widget _buildSectorDropdown() {
|
||||
// Récupérer les secteurs uniques depuis les passages de l'opération courante
|
||||
final sectorIds = <int>{};
|
||||
|
||||
for (final passage in _originalPassages) {
|
||||
if (passage.fkSector != null && !sectorIds.contains(passage.fkSector)) {
|
||||
sectorIds.add(passage.fkSector!);
|
||||
}
|
||||
}
|
||||
|
||||
// Récupérer les noms des secteurs depuis le repository
|
||||
final allSectors = sectorRepository.getAllSectors();
|
||||
final sectorNames = <int, String>{};
|
||||
for (final sector in allSectors) {
|
||||
if (sectorIds.contains(sector.id)) {
|
||||
sectorNames[sector.id] = sector.libelle;
|
||||
}
|
||||
}
|
||||
|
||||
// Trier par nom
|
||||
final sortedSectors = sectorIds.toList()
|
||||
..sort((a, b) => (sectorNames[a] ?? '').compareTo(sectorNames[b] ?? ''));
|
||||
|
||||
return DropdownButtonFormField<int?>(
|
||||
value: _selectedSectorId,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
isDense: true,
|
||||
labelText: 'Secteur',
|
||||
prefixIcon: Icon(Icons.location_on, size: 20),
|
||||
),
|
||||
items: [
|
||||
const DropdownMenuItem<int?>(
|
||||
value: null,
|
||||
child: Text('Tous'),
|
||||
),
|
||||
...sortedSectors.map((sectorId) {
|
||||
return DropdownMenuItem<int?>(
|
||||
value: sectorId,
|
||||
child: Text(
|
||||
sectorNames[sectorId] ?? 'Secteur #$sectorId',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
_selectedSectorId = newValue;
|
||||
});
|
||||
_applyFilters();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user