feat(admin): onglet À valider, dossier unifié et modales de validation

- Onglet « À valider » (AM + familles), pending-families et détail dossier par numéro.
- Wizards validation AM et famille, modale commune, chargement via GET /dossiers/:num.
- UI : cartes enfants, photo AM (cadre uniforme, ratio), NIR affiché formaté (espaces autour du tiret).
- Backend : DTO / routes parents pending ; scripts de test et mise à jour issue Gitea.

Tickets #107, #119.

Made-with: Cursor
This commit is contained in:
2026-03-26 00:15:18 +01:00
parent d832559027
commit 2e02f60601
36 changed files with 3303 additions and 173 deletions
@@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
/// Sous-barre : Gestionnaires | Parents | Assistantes maternelles | [Administrateurs].
/// [subTabCount] = 3 pour masquer l'onglet Administrateurs (dashboard gestionnaire).
/// Sous-barre : [À valider] | Gestionnaires | Parents | Assistantes maternelles | [Administrateurs].
/// [tabLabels] : liste des libellés d'onglets (ex. avec « À valider » en premier si dossiers en attente).
/// [subTabCount] = 3 pour masquer Administrateurs (dashboard gestionnaire).
class DashboardUserManagementSubBar extends StatelessWidget {
final int selectedSubIndex;
final ValueChanged<int> onSubTabChange;
@@ -11,8 +12,10 @@ class DashboardUserManagementSubBar extends StatelessWidget {
final VoidCallback? onAddPressed;
final String addLabel;
final int subTabCount;
/// Si non null, utilisé à la place des labels par défaut (ex. ['À valider', 'Parents', ...]).
final List<String>? tabLabels;
static const List<String> _tabLabels = [
static const List<String> _defaultTabLabels = [
'Gestionnaires',
'Parents',
'Assistantes maternelles',
@@ -29,10 +32,14 @@ class DashboardUserManagementSubBar extends StatelessWidget {
this.onAddPressed,
this.addLabel = '+ Ajouter',
this.subTabCount = 4,
this.tabLabels,
}) : super(key: key);
List<String> get _labels => tabLabels ?? _defaultTabLabels.sublist(0, subTabCount.clamp(1, _defaultTabLabels.length));
@override
Widget build(BuildContext context) {
final labels = _labels;
return Container(
height: 56,
decoration: BoxDecoration(
@@ -42,9 +49,9 @@ class DashboardUserManagementSubBar extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 6),
child: Row(
children: [
for (int i = 0; i < subTabCount; i++) ...[
for (int i = 0; i < labels.length; i++) ...[
if (i > 0) const SizedBox(width: 12),
_buildSubNavItem(context, _tabLabels[i], i),
_buildSubNavItem(context, labels[i], i),
],
const SizedBox(width: 36),
_pillField(
@@ -68,7 +75,7 @@ class DashboardUserManagementSubBar extends StatelessWidget {
_pillField(width: 150, child: filterControl!),
],
const Spacer(),
_buildAddButton(),
if (onAddPressed != null) _buildAddButton(),
],
),
);