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 1ebf683825
commit e65ae4cebe

View File

@ -57,6 +57,7 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
bool get _isUnborn => _status == 'a_naitre'; bool get _isUnborn => _status == 'a_naitre';
bool get _isScolarise => _status == 'scolarise'; bool get _isScolarise => _status == 'scolarise';
bool get _isSansGarde => _status == 'sans_garde';
bool get _showsAmPlacement => !_isScolarise; bool get _showsAmPlacement => !_isScolarise;
List<String> get _availableGenders => List<String> get _availableGenders =>
@ -294,7 +295,7 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
return; return;
} }
if (_linkedAm != null) { if (_linkedAm != null && !_isSansGarde) {
if (!mounted) return; if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
@ -332,11 +333,25 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
setState(() => _placementBusy = true); setState(() => _placementBusy = true);
try { 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( await UserService.attachEnfantToAm(
amUserId: selected.user.id, amUserId: selected.user.id,
enfantId: widget.enfant.id, enfantId: widget.enfant.id,
); );
if (!mounted) return; 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(); await _loadLinkedAm();
widget.onSaved?.call(); widget.onSaved?.call();
if (!mounted) return; if (!mounted) return;
@ -386,7 +401,13 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
enfantId: widget.enfant.id, enfantId: widget.enfant.id,
); );
if (!mounted) return; 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(); widget.onSaved?.call();
if (!mounted) return; if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar( 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}) { InputDecoration _inputDecoration({String? hint}) {
return ValidationFieldDecoration.input(hint: hint).copyWith( return ValidationFieldDecoration.input(hint: hint).copyWith(
isDense: false, isDense: false,
@ -479,11 +524,16 @@ class _AdminChildDetailModalState extends State<AdminChildDetailModal> {
), ),
) )
.toList(), .toList(),
onChanged: (v) => setState(() { onChanged: (v) {
_status = v; setState(() {
_coerceGenderForStatus(); _status = v;
_dirty = true; _coerceGenderForStatus();
}), _dirty = true;
});
if (v == 'sans_garde') {
_applySansGardeStatus();
}
},
), ),
), ),
ValidationLabeledField( 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(); if (_linkedAm != null) return _linkedAmCard();
return _emptyAmSlot(); return _emptyAmSlot();
} }