import 'package:flutter/material.dart'; import 'package:p_tits_pas/services/user_service.dart'; class ParentManagementWidget extends StatefulWidget { const ParentManagementWidget({super.key}); @override State createState() => _ParentManagementWidgetState(); } class _ParentManagementWidgetState extends State { final UserService _userService = UserService(); final TextEditingController _searchController = TextEditingController(); List> _allParents = []; List> _filteredParents = []; String? _selectedStatus; bool _isLoading = true; String? _error; @override void initState() { super.initState(); _loadParents(); } @override void dispose() { _searchController.dispose(); super.dispose(); } Future _loadParents() async { setState(() { _isLoading = true; _error = null; }); try { final parents = await _userService.getUsersByRole("parent"); setState(() { _allParents = parents; _filteredParents = parents; _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } void _applyFilters() { setState(() { _filteredParents = _allParents.where((parent) { final searchQuery = _searchController.text.toLowerCase(); final fullName = '${parent['prenom'] ?? ''} ${parent['nom'] ?? ''}'.toLowerCase(); final email = (parent['email'] ?? '').toLowerCase(); bool matchesSearch = searchQuery.isEmpty || fullName.contains(searchQuery) || email.contains(searchQuery); bool matchesStatus = _selectedStatus == null || _selectedStatus!.isEmpty || parent['statut']?.toString() == _selectedStatus; return matchesSearch && matchesStatus; }).toList(); }); } String _getStatusDisplay(Map parent) { final status = parent['statut']; if (status == null) return 'Non défini'; switch (status.toString().toLowerCase()) { case 'actif': return 'Actif'; case 'en_attente': return 'En attente'; case 'inactif': return 'Inactif'; case 'supprimé': return 'Supprimé'; default: return status.toString(); } } Color _getStatusColor(Map parent) { final status = parent['statut']?.toString().toLowerCase(); switch (status) { case 'actif': return Colors.green; case 'en_attente': return Colors.orange; case 'inactif': return Colors.grey; case 'supprimé': return Colors.red; default: return Colors.grey; } } Future _confirmDelete(Map parent) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Confirmer la suppression'), content: Text( 'Êtes-vous sûr de vouloir supprimer le compte de ${parent['firstName']} ${parent['lastName']} ?' ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Annuler'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), style: TextButton.styleFrom(foregroundColor: Colors.red), child: const Text('Supprimer'), ), ], ), ); if (confirmed == true) { await _deleteParent(parent); } } Future _deleteParent(Map parent) async { try { final success = await _userService.deleteUser(parent['id']); if (success) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${parent['firstName']} ${parent['lastName']} supprimé avec succès'), backgroundColor: Colors.green, ), ); _loadParents(); // Recharger la liste } else { throw Exception('Erreur lors de la suppression'); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Erreur: ${e.toString()}'), backgroundColor: Colors.red, ), ); } } void _viewParentDetails(Map parent) { showDialog( context: context, builder: (context) => AlertDialog( title: Text('${parent['firstName']} ${parent['lastName']}'), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Email: ${parent['email']}'), Text('Rôle: ${parent['role']}'), Text('Statut: ${_getStatusDisplay(parent)}'), Text('ID: ${parent['id']}'), if (parent['createdAt'] != null) Text('Créé le: ${DateTime.parse(parent['createdAt']).toLocal().toString().split(' ')[0]}'), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Fermer'), ), ], ), ); } Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Gestion des Parents (${_filteredParents.length})', style: Theme.of(context).textTheme.headlineSmall, ), IconButton( icon: const Icon(Icons.refresh), onPressed: _loadParents, tooltip: 'Actualiser', ), ], ), const SizedBox(height: 16), _buildSearchSection(), const SizedBox(height: 16), Expanded( child: _buildParentsList(), ), ], )); } Widget _buildSearchSection() { return Wrap( spacing: 16, runSpacing: 8, children: [ SizedBox( width: 250, child: TextField( controller: _searchController, decoration: const InputDecoration( labelText: "Rechercher un parent", hintText: "Nom ou email", border: OutlineInputBorder(), prefixIcon: Icon(Icons.search), ), onChanged: (value) => _applyFilters(), ), ), SizedBox( width: 200, child: DropdownButtonFormField( value: _selectedStatus, decoration: const InputDecoration( labelText: "Statut", border: OutlineInputBorder(), ), items: const [ DropdownMenuItem(value: null, child: Text("Tous")), DropdownMenuItem(value: "active", child: Text("Actif")), DropdownMenuItem(value: "pending", child: Text("En attente")), DropdownMenuItem(value: "inactive", child: Text("Inactif")), DropdownMenuItem(value: "deleted", child: Text("Supprimé")), ], onChanged: (value) { setState(() { _selectedStatus = value; }); _applyFilters(); }, ), ), ], ); } Widget _buildParentsList() { if (_isLoading) { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('Chargement des parents...'), ], ), ); } if (_error != null) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline, size: 48, color: Colors.red[300]), const SizedBox(height: 16), Text( 'Erreur de chargement', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( _error!, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium, ), const SizedBox(height: 16), ElevatedButton( onPressed: _loadParents, child: const Text('Réessayer'), ), ], ), ); } if (_filteredParents.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.people_outline, size: 48, color: Colors.grey[400]), const SizedBox(height: 16), Text( _allParents.isEmpty ? 'Aucun parent trouvé' : 'Aucun résultat', style: Theme.of(context).textTheme.titleLarge, ), if (_allParents.isNotEmpty) ...[ const SizedBox(height: 8), const Text('Essayez de modifier vos critères de recherche'), ], ], ), ); } return ListView.builder( itemCount: _filteredParents.length, itemBuilder: (context, index) { final parent = _filteredParents[index]; return Card( margin: const EdgeInsets.symmetric(vertical: 4), child: ListTile( leading: CircleAvatar( backgroundColor: _getStatusColor(parent).withOpacity(0.2), child: Text( '${parent['firstName']?[0] ?? ''}${parent['lastName']?[0] ?? ''}', style: TextStyle( color: _getStatusColor(parent), fontWeight: FontWeight.bold, ), ), ), title: Text('${parent['firstName'] ?? ''} ${parent['lastName'] ?? ''}'), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(parent['email'] ?? ''), const SizedBox(height: 4), Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: _getStatusColor(parent).withOpacity(0.2), borderRadius: BorderRadius.circular(12), border: Border.all(color: _getStatusColor(parent)), ), child: Text( _getStatusDisplay(parent), style: TextStyle( color: _getStatusColor(parent), fontSize: 12, fontWeight: FontWeight.w500, ), ), ), ], ), ], ), isThreeLine: true, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.visibility, color: Colors.blue), tooltip: "Voir détails", onPressed: () => _viewParentDetails(parent), ), IconButton( icon: const Icon(Icons.edit, color: Colors.orange), tooltip: "Modifier", onPressed: () { // TODO: Implémenter la modification ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Fonctionnalité de modification à implémenter'), ), ); }, ), IconButton( icon: const Icon(Icons.delete, color: Colors.red), tooltip: "Supprimer", onPressed: () => _confirmDelete(parent), ), ], ), ), ); }, ); } }