Files
petitspas/frontend/lib/widgets/dashboard/parent_managmant_widget.dart
T
jmartin 5b83102a59 feat(#152/#155): cleanup est_multiple + dashboard sans préfixe Admin (squash develop).
Suppression complète grossesse multiple / est_multiple (BDD, API, front).
Rename option C : widgets partagés et panels staff sous widgets/dashboard/,
AdminManagementWidget seul restant dans widgets/admin/.
2026-09-14 12:52:22 +02:00

199 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:p_tits_pas/models/dossier_list_item.dart';
import 'package:p_tits_pas/models/parent_model.dart';
import 'package:p_tits_pas/services/auth_service.dart';
import 'package:p_tits_pas/services/user_service.dart';
import 'package:p_tits_pas/utils/staff_deletion_rights.dart';
import 'package:p_tits_pas/widgets/dashboard/parent_edit_modal.dart';
import 'package:p_tits_pas/widgets/dashboard/user_card.dart';
import 'package:p_tits_pas/widgets/dashboard/common/suppression_confirm_dialog.dart';
import 'package:p_tits_pas/widgets/dashboard/common/user_list.dart';
class ParentManagementWidget extends StatefulWidget {
final String searchQuery;
final String? statusFilter;
const ParentManagementWidget({
super.key,
required this.searchQuery,
this.statusFilter,
});
@override
State<ParentManagementWidget> createState() => _ParentManagementWidgetState();
}
class _ParentManagementWidgetState extends State<ParentManagementWidget> {
bool _isLoading = false;
String? _error;
List<ParentModel> _parents = [];
bool _canDelete = false;
@override
void initState() {
super.initState();
_loadRights();
_loadParents();
}
@override
void dispose() => super.dispose();
Future<void> _loadRights() async {
final user = await AuthService.getCurrentUser();
if (!mounted) return;
setState(() => _canDelete = canDeleteMetier(user?.role));
}
Future<void> _loadParents() async {
setState(() {
_isLoading = true;
_error = null;
});
try {
final list = await UserService.getParents();
if (!mounted) return;
setState(() {
_parents = list;
_isLoading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e.toString();
_isLoading = false;
});
}
}
bool _isLastParent(ParentModel parent) {
final co = parent.coParent?.id.trim();
if (co != null && co.isNotEmpty) return false;
final num = (parent.user.numeroDossier ?? '').trim();
if (num.isEmpty) return true;
return !_parents.any((other) {
if (other.user.id == parent.user.id) return false;
return (other.user.numeroDossier ?? '').trim() == num;
});
}
Future<void> _confirmDelete(ParentModel parent) async {
final num = (parent.user.numeroDossier ?? '').trim();
final name = formatDossierPersonLabel(
nom: parent.user.nom,
prenom: parent.user.prenom,
email: parent.user.email,
);
final last = _isLastParent(parent);
final enfants = ParentModel.foyerChildrenCount(parent, _parents);
final footnotes = last
? <String>[
if (num.isNotEmpty) 'Dernier parent du dossier $num.',
if (num.isEmpty) 'Dernier parent du dossier.',
'Les $enfants enfant(s) rattaché(s) seront aussi supprimés.',
]
: <String>[
if (num.isNotEmpty)
'Ce parent sera retiré du dossier $num.',
'Les enfants restent avec le co-parent.',
];
final confirmed = await showSuppressionConfirmDialog(
context,
title: 'Supprimer le parent',
subtitle: num.isEmpty ? null : 'Dossier $num',
people: [SuppressionPersonLine.parent(name)],
footnotes: footnotes,
);
if (!confirmed || !mounted) return;
try {
final result = await UserService.deleteUser(parent.user.id);
if (!mounted) return;
final msg = (result['message'] ?? 'Parent supprimé.').toString();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
await _loadParents();
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
e is Exception
? e.toString().replaceFirst('Exception: ', '')
: 'Erreur suppression',
),
),
);
}
}
@override
Widget build(BuildContext context) {
final query = widget.searchQuery.toLowerCase();
final filteredParents = _parents.where((p) {
final matchesName = p.user.fullName.toLowerCase().contains(query) ||
p.user.email.toLowerCase().contains(query);
final matchesStatus =
widget.statusFilter == null || p.user.statut == widget.statusFilter;
return matchesName && matchesStatus;
}).toList();
return UserList(
isLoading: _isLoading,
error: _error,
isEmpty: filteredParents.isEmpty,
emptyMessage: 'Aucun parent trouvé.',
itemCount: filteredParents.length,
itemBuilder: (context, index) {
final parent = filteredParents[index];
return UserCard(
title: parent.user.fullName,
fallbackIcon: Icons.supervisor_account_outlined,
avatarUrl: parent.user.photoUrl,
onCardTap: () => _openParentDetails(parent),
subtitleLines: [
parent.user.email,
'Statut : ${_displayStatus(parent.user.statut)} | Enfants : ${ParentModel.foyerChildrenCount(parent, _parents)}',
],
actions: [
IconButton(
icon: const Icon(Icons.edit),
tooltip: 'Modifier',
onPressed: () {
_openParentDetails(parent);
},
),
if (_canDelete)
suppressionIconButton(onPressed: () => _confirmDelete(parent)),
],
);
},
);
}
String _displayStatus(String? status) {
switch (status) {
case 'actif':
return 'Actif';
case 'en_attente':
return 'En attente';
case 'suspendu':
return 'Suspendu';
case 'refuse':
return 'Refusé';
default:
return 'Inconnu';
}
}
void _openParentDetails(ParentModel parent) {
showDialog<void>(
context: context,
builder: (context) => ParentEditModal(
parent: parent,
onSaved: _loadParents,
),
);
}
}