petitspas/frontend/lib/widgets/admin/parent_managmant_widget.dart
Julien Martin b2d6414fab refactor(#93): homogénéiser la présentation des onglets admin
Uniformise les 4 onglets de gestion admin avec des composants UI partagés (header, états de liste, carte utilisateur) pour garantir une expérience cohérente sans changement backend.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-23 17:31:50 +01:00

180 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:p_tits_pas/models/parent_model.dart';
import 'package:p_tits_pas/services/user_service.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_list_header.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_list_state.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_user_card.dart';
class ParentManagementWidget extends StatefulWidget {
const ParentManagementWidget({super.key});
@override
State<ParentManagementWidget> createState() => _ParentManagementWidgetState();
}
class _ParentManagementWidgetState extends State<ParentManagementWidget> {
bool _isLoading = false;
String? _error;
List<ParentModel> _parents = [];
List<ParentModel> _filteredParents = [];
final TextEditingController _searchController = TextEditingController();
String? _selectedStatus;
@override
void initState() {
super.initState();
_loadParents();
_searchController.addListener(_filter);
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
Future<void> _loadParents() async {
setState(() {
_isLoading = true;
_error = null;
});
try {
final list = await UserService.getParents();
if (!mounted) return;
setState(() {
_parents = list;
_filter(); // Apply initial filter (if any)
_isLoading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e.toString();
_isLoading = false;
});
}
}
void _filter() {
final query = _searchController.text.toLowerCase();
setState(() {
_filteredParents = _parents.where((p) {
final matchesName = p.user.fullName.toLowerCase().contains(query) ||
p.user.email.toLowerCase().contains(query);
final matchesStatus =
_selectedStatus == null || p.user.statut == _selectedStatus;
return matchesName && matchesStatus;
}).toList();
});
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AdminListHeader(
searchController: _searchController,
searchHint: 'Rechercher un parent...',
filters: _buildFilters(),
),
const SizedBox(height: 16),
AdminListState(
isLoading: _isLoading,
error: _error,
isEmpty: _filteredParents.isEmpty,
emptyMessage: 'Aucun parent trouvé.',
list: ListView.builder(
itemCount: _filteredParents.length,
itemBuilder: (context, index) {
final parent = _filteredParents[index];
return AdminUserCard(
title: parent.user.fullName,
avatarUrl: parent.user.photoUrl,
subtitleLines: [
parent.user.email,
'Statut : ${_displayStatus(parent.user.statut)}',
'Enfants : ${parent.childrenCount}',
],
actions: [
IconButton(
icon: const Icon(Icons.visibility),
tooltip: 'Voir dossier',
onPressed: () {
// TODO: Voir le statut du dossier
},
),
IconButton(
icon: const Icon(Icons.edit),
tooltip: 'Modifier',
onPressed: () {
// TODO: Modifier parent
},
),
IconButton(
icon: const Icon(Icons.delete),
tooltip: 'Supprimer',
onPressed: () {
// TODO: Supprimer compte
},
),
],
);
},
),
),
],
),
);
}
Widget _buildFilters() {
return SizedBox(
width: 240,
child: DropdownButtonFormField<String?>(
decoration: const InputDecoration(
labelText: 'Statut',
border: OutlineInputBorder(),
isDense: true,
),
value: _selectedStatus,
items: const [
DropdownMenuItem<String?>(value: null, child: Text('Tous')),
DropdownMenuItem<String?>(value: 'actif', child: Text('Actif')),
DropdownMenuItem<String?>(
value: 'en_attente',
child: Text('En attente'),
),
DropdownMenuItem<String?>(
value: 'suspendu',
child: Text('Suspendu'),
),
],
onChanged: (value) {
setState(() {
_selectedStatus = value;
});
_filter();
},
),
);
}
String _displayStatus(String? status) {
switch (status) {
case 'actif':
return 'Actif';
case 'en_attente':
return 'En attente';
case 'suspendu':
return 'Suspendu';
default:
return 'Inconnu';
}
}
}