feat(#131): fiches parent/AM éditable, placement AM↔enfant, statuts garde/sans_garde

Squash merge develop → master.

- Fiche parent éditable (co-parent, PATCH fiche, GET /parents)
- Fiche AM 3 onglets (PATCH fiche, rattacher/détacher enfants)
- Table enfants_assistantes_maternelles + enum garde/sans_garde
- Migration SQL + BDD.sql canonique
- Correctifs recette : @Get() parents, DTO fiche AM, fix NIR

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-11 22:49:57 +02:00
co-authored by Cursor
parent b99745e0fe
commit 003fe6b762
69 changed files with 6290 additions and 417 deletions
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:p_tits_pas/models/assistante_maternelle_model.dart';
import 'package:p_tits_pas/utils/phone_utils.dart';
import 'package:p_tits_pas/utils/am_vigilance.dart';
import 'package:p_tits_pas/services/user_service.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_detail_modal.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_am_edit_modal.dart';
import 'package:p_tits_pas/widgets/admin/common/admin_user_card.dart';
import 'package:p_tits_pas/widgets/admin/common/user_list.dart';
@@ -77,10 +77,12 @@ class _AssistanteMaternelleManagementWidgetState
itemCount: filteredAssistantes.length,
itemBuilder: (context, index) {
final assistante = filteredAssistantes[index];
final vigilance = amPlacesVigilanceMessage(assistante);
return AdminUserCard(
title: assistante.user.fullName,
avatarUrl: assistante.user.photoUrl,
fallbackIcon: Icons.face,
vigilanceTooltip: vigilance,
subtitleLines: [
assistante.user.email,
'Zone : ${assistante.residenceCity ?? 'N/A'} | Capacité : ${assistante.maxChildren ?? 0}',
@@ -102,55 +104,10 @@ class _AssistanteMaternelleManagementWidgetState
void _openAssistanteDetails(AssistanteMaternelleModel assistante) {
showDialog<void>(
context: context,
builder: (context) => AdminDetailModal(
title: assistante.user.fullName.isEmpty
? 'Assistante maternelle'
: assistante.user.fullName,
subtitle: assistante.user.email,
fields: [
AdminDetailField(label: 'ID', value: _v(assistante.user.id)),
AdminDetailField(
label: 'Numero agrement',
value: _v(assistante.approvalNumber),
),
AdminDetailField(
label: 'Ville residence',
value: _v(assistante.residenceCity),
),
AdminDetailField(
label: 'Capacite max',
value: assistante.maxChildren?.toString() ?? '-',
),
AdminDetailField(
label: 'Places disponibles',
value: assistante.placesAvailable?.toString() ?? '-',
),
AdminDetailField(
label: 'Telephone',
value: _v(assistante.user.telephone) != '' ? formatPhoneForDisplay(_v(assistante.user.telephone)) : '',
),
AdminDetailField(label: 'Adresse', value: _v(assistante.user.adresse)),
AdminDetailField(label: 'Ville', value: _v(assistante.user.ville)),
AdminDetailField(
label: 'Code postal',
value: _v(assistante.user.codePostal),
),
],
onEdit: () {
Navigator.of(context).pop();
ScaffoldMessenger.of(this.context).showSnackBar(
const SnackBar(content: Text('Action Modifier a implementer')),
);
},
onDelete: () {
Navigator.of(context).pop();
ScaffoldMessenger.of(this.context).showSnackBar(
const SnackBar(content: Text('Action Supprimer a implementer')),
);
},
builder: (context) => AdminAmEditModal(
assistante: assistante,
onSaved: _loadAssistantes,
),
);
}
String _v(String? value) => (value == null || value.isEmpty) ? '-' : value;
}