fix(#131): activer Sauvegarder sur statut, enfants et champs AM.
Compare l'état de la fiche à un snapshot initial (liste enfants, statut, places, formulaire) et corrige la gélule statut pour les valeurs hors liste. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
66c7f22280
commit
d03a8e6c8b
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:p_tits_pas/models/assistante_maternelle_model.dart';
|
||||
@ -57,6 +58,25 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
bool _saving = false;
|
||||
bool _dirty = false;
|
||||
|
||||
late String _baseStatut;
|
||||
late bool _baseDisponible;
|
||||
late int? _basePlacesAvailable;
|
||||
late List<String> _baseChildIds;
|
||||
late String _baseNom;
|
||||
late String _basePrenom;
|
||||
late String _baseEmail;
|
||||
late String _baseTelephone;
|
||||
late String _baseAdresse;
|
||||
late String _baseVille;
|
||||
late String _baseCodePostal;
|
||||
late String _baseAgrement;
|
||||
late String _baseNir;
|
||||
late String? _baseDateNaissanceIso;
|
||||
late String _baseLieuNaissanceVille;
|
||||
late String _baseLieuNaissancePays;
|
||||
late String? _baseAgreementDateIso;
|
||||
late int? _baseCapacite;
|
||||
|
||||
static const double _modalWidth = 930;
|
||||
static const double _photoProGap = 24;
|
||||
static const double _proColumnMinWidth = 260;
|
||||
@ -147,16 +167,77 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
_nomCtrl.addListener(_onNameFieldChanged);
|
||||
_prenomCtrl.addListener(_onNameFieldChanged);
|
||||
_tabCtrl.addListener(_onTabChanged);
|
||||
_captureBaseline();
|
||||
_reloadChildren();
|
||||
}
|
||||
|
||||
void _captureBaseline() {
|
||||
_baseStatut = _statut;
|
||||
_baseDisponible = _disponible;
|
||||
_basePlacesAvailable = _placesAvailable;
|
||||
_baseChildIds = _children.map((c) => c.id).toList()..sort();
|
||||
_baseNom = _nomCtrl.text.trim();
|
||||
_basePrenom = _prenomCtrl.text.trim();
|
||||
_baseEmail = _emailCtrl.text.trim();
|
||||
_baseTelephone = normalizePhone(_telCtrl.text);
|
||||
_baseAdresse = _adresseCtrl.text.trim();
|
||||
_baseVille = _villeCtrl.text.trim();
|
||||
_baseCodePostal = _cpCtrl.text.trim();
|
||||
_baseAgrement = _agrementCtrl.text.trim();
|
||||
_baseNir = nirToRaw(_nirCtrl.text);
|
||||
_baseDateNaissanceIso = _frDateToIso(_dateNaissanceCtrl.text);
|
||||
_baseLieuNaissanceVille = _lieuNaissanceVilleCtrl.text.trim();
|
||||
_baseLieuNaissancePays = _lieuNaissancePaysCtrl.text.trim();
|
||||
_baseAgreementDateIso = _frDateToIso(_dateAgrementCtrl.text);
|
||||
_baseCapacite = _capaciteMax();
|
||||
}
|
||||
|
||||
bool _hasUnsavedChanges() {
|
||||
if (_statut != _baseStatut) return true;
|
||||
if (_disponible != _baseDisponible) return true;
|
||||
if (_placesAvailable != _basePlacesAvailable) return true;
|
||||
final childIds = _children.map((c) => c.id).toList()..sort();
|
||||
if (!listEquals(childIds, _baseChildIds)) return true;
|
||||
if (_nomCtrl.text.trim() != _baseNom) return true;
|
||||
if (_prenomCtrl.text.trim() != _basePrenom) return true;
|
||||
if (_emailCtrl.text.trim() != _baseEmail) return true;
|
||||
if (normalizePhone(_telCtrl.text) != _baseTelephone) return true;
|
||||
if (_adresseCtrl.text.trim() != _baseAdresse) return true;
|
||||
if (_villeCtrl.text.trim() != _baseVille) return true;
|
||||
if (_cpCtrl.text.trim() != _baseCodePostal) return true;
|
||||
if (_agrementCtrl.text.trim() != _baseAgrement) return true;
|
||||
if (nirToRaw(_nirCtrl.text) != _baseNir) return true;
|
||||
if (_frDateToIso(_dateNaissanceCtrl.text) != _baseDateNaissanceIso) {
|
||||
return true;
|
||||
}
|
||||
if (_lieuNaissanceVilleCtrl.text.trim() != _baseLieuNaissanceVille) {
|
||||
return true;
|
||||
}
|
||||
if (_lieuNaissancePaysCtrl.text.trim() != _baseLieuNaissancePays) {
|
||||
return true;
|
||||
}
|
||||
if (_frDateToIso(_dateAgrementCtrl.text) != _baseAgreementDateIso) {
|
||||
return true;
|
||||
}
|
||||
if (_capaciteMax() != _baseCapacite) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void _syncDirtyState() {
|
||||
final next = _hasUnsavedChanges();
|
||||
if (next != _dirty) setState(() => _dirty = next);
|
||||
}
|
||||
|
||||
void _onTabChanged() {
|
||||
if (!_tabCtrl.indexIsChanging) setState(() {});
|
||||
}
|
||||
|
||||
void _onNameFieldChanged() => setState(() {});
|
||||
|
||||
void _onCapacityChanged() => setState(() {});
|
||||
void _onCapacityChanged() {
|
||||
setState(() {});
|
||||
_syncDirtyState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -182,9 +263,7 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _markDirty() {
|
||||
if (!_dirty) setState(() => _dirty = true);
|
||||
}
|
||||
void _markDirty() => _syncDirtyState();
|
||||
|
||||
String _headerTitle() {
|
||||
final fn = _prenomCtrl.text.trim();
|
||||
@ -240,10 +319,8 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
void _applyPlacesCorrection() {
|
||||
final expected = _computedPlacesAvailable();
|
||||
if (expected == null) return;
|
||||
setState(() {
|
||||
_placesAvailable = expected;
|
||||
_dirty = true;
|
||||
});
|
||||
setState(() => _placesAvailable = expected);
|
||||
_syncDirtyState();
|
||||
}
|
||||
|
||||
String? _placesInconsistencyMessage() {
|
||||
@ -318,6 +395,7 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
_dirty = false;
|
||||
_saving = false;
|
||||
});
|
||||
_captureBaseline();
|
||||
widget.onSaved?.call();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Fiche assistante maternelle enregistrée')),
|
||||
@ -346,6 +424,7 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() => _children = kids);
|
||||
_syncDirtyState();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@ -574,10 +653,10 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
style: TextStyle(fontSize: 13),
|
||||
),
|
||||
value: _disponible,
|
||||
onChanged: (v) => setState(() {
|
||||
_disponible = v;
|
||||
_dirty = true;
|
||||
}),
|
||||
onChanged: (v) {
|
||||
setState(() => _disponible = v);
|
||||
_syncDirtyState();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -756,10 +835,10 @@ class _AdminAmEditModalState extends State<AdminAmEditModal>
|
||||
width: 160,
|
||||
child: AdminStatusCapsule(
|
||||
statut: _statut,
|
||||
onChanged: (v) => setState(() {
|
||||
_statut = v;
|
||||
_dirty = true;
|
||||
}),
|
||||
onChanged: (v) {
|
||||
setState(() => _statut = v);
|
||||
_syncDirtyState();
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
|
||||
@ -30,7 +30,10 @@ class AdminStatusCapsule extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final value = statuts.contains(statut) ? statut : statuts.first;
|
||||
final value = statut;
|
||||
final items = statuts.contains(statut)
|
||||
? statuts
|
||||
: <String>[statut, ...statuts];
|
||||
return Container(
|
||||
height: 34,
|
||||
decoration: BoxDecoration(
|
||||
@ -46,7 +49,7 @@ class AdminStatusCapsule extends StatelessWidget {
|
||||
isDense: true,
|
||||
style: const TextStyle(fontSize: 13, color: Colors.black87),
|
||||
icon: const Icon(Icons.arrow_drop_down, size: 20),
|
||||
items: statuts
|
||||
items: items
|
||||
.map(
|
||||
(s) => DropdownMenuItem(
|
||||
value: s,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user