fix(#138): cadre vide en sans garde et passage auto en garde à l'attach AM.

En statut sans_garde, la zone placement affiche toujours le cadre vide ;
sélectionner une AM passe le statut à en garde, et passer à sans_garde
détache l'AM rattachée.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
MARTIN Julien 2026-07-17 12:24:20 +02:00
parent 7951c38d4d
commit cf6acbae7c

View File

@ -57,6 +57,7 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
bool get _isUnborn => _status == 'a_naitre';
bool get _isScolarise => _status == 'scolarise';
bool get _isSansGarde => _status == 'sans_garde';
bool get _showsAmPlacement => !_isScolarise;
List<String> get _availableGenders =>
@ -294,7 +295,7 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
return;
}
if (_linkedAm != null) {
if (_linkedAm != null && !_isSansGarde) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
@ -332,11 +333,25 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
setState(() => _placementBusy = true);
try {
// Sans garde : éventuel lien résiduel à clôturer avant rattachement.
final previousAm = _linkedAm;
if (previousAm != null) {
await UserService.detachEnfantFromAm(
amUserId: previousAm.user.id,
enfantId: widget.enfant.id,
);
}
await UserService.attachEnfantToAm(
amUserId: selected.user.id,
enfantId: widget.enfant.id,
);
if (!mounted) return;
setState(() {
// Le back passe déjà sans_garde garde à l'attach ; on aligne l'UI.
if (_status == 'sans_garde') {
_status = 'garde';
}
});
await _loadLinkedAm();
widget.onSaved?.call();
if (!mounted) return;
@ -386,7 +401,13 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
enfantId: widget.enfant.id,
);
if (!mounted) return;
await _loadLinkedAm();
setState(() {
// Le back repasse en sans_garde sauf a_naitre / scolarise.
if (_status != 'a_naitre' && _status != 'scolarise') {
_status = 'sans_garde';
}
_linkedAm = null;
});
widget.onSaved?.call();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
@ -402,6 +423,30 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
}
}
/// Passe en « Sans garde » : cadre vide + détachement AM si besoin.
Future<void> _applySansGardeStatus() async {
final am = _linkedAm;
if (am == null) return;
setState(() => _placementBusy = true);
try {
await UserService.detachEnfantFromAm(
amUserId: am.user.id,
enfantId: widget.enfant.id,
);
if (!mounted) return;
setState(() => _linkedAm = null);
widget.onSaved?.call();
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toString().replaceFirst('Exception: ', ''))),
);
} finally {
if (mounted) setState(() => _placementBusy = false);
}
}
InputDecoration _inputDecoration({String? hint}) {
return ValidationFieldDecoration.input(hint: hint).copyWith(
isDense: false,
@ -479,11 +524,16 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
),
)
.toList(),
onChanged: (v) => setState(() {
onChanged: (v) {
setState(() {
_status = v;
_coerceGenderForStatus();
_dirty = true;
}),
});
if (v == 'sans_garde') {
_applySansGardeStatus();
}
},
),
),
ValidationLabeledField(
@ -731,6 +781,8 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
);
}
// Sans garde : toujours le cadre vide (comme après détachement AM).
if (_isSansGarde) return _emptyAmSlot();
if (_linkedAm != null) return _linkedAmCard();
return _emptyAmSlot();
}