feat(admin): validation AM/famille, À valider au survol, nettoyage logs

- À valider : ligne avec survol type AdminUserCard, icône Ouvrir centrée et plus grande (iconSize 34).
- Wizard AM : titres Identité et coordonnées / Dossier professionnel / Présentation ; photo à gauche, grille droite [2,2,2,2] (NIR, naissance, agrément, capacité) ; AppUser champs naissance ; dates dd/MM/yyyy via formatIsoDateFr ; ValidationDetailSection titre optionnel.
- Wizard famille : titre étape 4 « Présentation ».
- Suppression des debugPrint liés médias / images / dossier (api_config, auth_network_image, dossier_unifie, user_service, validation_family).

Made-with: Cursor
This commit is contained in:
2026-04-13 17:22:08 +02:00
parent f442c85cb6
commit 0befd4eb2a
10 changed files with 212 additions and 199 deletions
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:p_tits_pas/models/dossier_unifie.dart';
import 'package:p_tits_pas/utils/date_display_utils.dart';
import 'package:p_tits_pas/utils/phone_utils.dart';
import 'package:p_tits_pas/utils/nir_utils.dart';
import 'package:p_tits_pas/models/user.dart';
@@ -74,29 +75,40 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
AdminDetailField(label: 'Ville', value: _v(u.ville)),
];
/// Informations professionnelles : N° Agrément|Date agrément, NIR, Capacité|Places, Ville.
List<AdminDetailField> _proFields(DossierAM d) => [
AdminDetailField(label: 'N° Agrément', value: _v(d.numeroAgrement)),
AdminDetailField(
label: 'Date dagrément',
value: d.dateAgrement != null && d.dateAgrement!.trim().isNotEmpty
? d.dateAgrement!.trim()
: '',
),
AdminDetailField(label: 'NIR', value: _formatNirForDisplay(d.nir)),
AdminDetailField(
label: 'Capacité max (enfants)',
value: d.nbMaxEnfants != null ? d.nbMaxEnfants.toString() : '',
),
AdminDetailField(
label: 'Places disponibles',
value: d.placesDisponibles != null
? d.placesDisponibles.toString()
: '',
),
AdminDetailField(
label: 'Ville de résidence', value: _v(d.villeResidence)),
];
/// Panneau photo + grille droite : NIR|naissance, ville|pays, agrément|date, capa|places.
List<AdminDetailField> _photoProFields(DossierAM d) {
final u = d.user;
return [
AdminDetailField(label: 'NIR', value: _formatNirForDisplay(d.nir)),
AdminDetailField(
label: 'Date de naissance',
value: formatIsoDateFr(u.dateNaissance),
),
AdminDetailField(
label: 'Ville de naissance',
value: _v(u.lieuNaissanceVille),
),
AdminDetailField(
label: 'Pays de naissance',
value: _v(u.lieuNaissancePays),
),
AdminDetailField(label: 'N° Agrément', value: _v(d.numeroAgrement)),
AdminDetailField(
label: 'Date dagrément',
value: formatIsoDateFr(d.dateAgrement),
),
AdminDetailField(
label: 'Capacité max (enfants)',
value: d.nbMaxEnfants != null ? d.nbMaxEnfants.toString() : '',
),
AdminDetailField(
label: 'Places disponibles',
value: d.placesDisponibles != null
? d.placesDisponibles.toString()
: '',
),
];
}
static const List<int> _personalRowLayout = [2, 2, 1, 2];
static const Map<int, List<int>> _personalRowFlex = {
@@ -119,15 +131,6 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Photo de profil',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
const SizedBox(height: 12),
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 8),
@@ -264,7 +267,7 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: constraints.maxWidth),
child: ValidationDetailSection(
title: 'Informations personnelles',
title: 'Identité et coordonnées',
fields: _personalFields(u),
rowLayout: _personalRowLayout,
rowFlex: _personalRowFlex,
@@ -280,8 +283,7 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
builder: (context, c) {
final maxRowW = c.maxWidth;
final maxRowH = c.maxHeight;
// Titre « Photo de profil » + espacement (~52 px) : hauteur dispo pour le cadre photo.
const photoHeaderH = 52.0;
const photoHeaderH = 0.0;
final bodyH = (maxRowH - photoHeaderH).clamp(0.0, double.infinity);
final idealPhotoW =
bodyH * _idPhotoAspectRatio + 16; // marge approx. cadre clair
@@ -307,14 +309,9 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
constraints: BoxConstraints(
minWidth: constraints.maxWidth),
child: ValidationDetailSection(
title: 'Informations professionnelles',
fields: _proFields(d),
rowLayout: const [
2,
1,
2,
1
], // N° Agrément|Date agrément, NIR, Capacité|Places, Ville
title: 'Dossier professionnel',
fields: _photoProFields(d),
rowLayout: const [2, 2, 2, 2],
),
),
);
@@ -333,12 +330,13 @@ class _ValidationAmWizardState extends State<ValidationAmWizard> {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
const Text(
'Présentation',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black87),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
const SizedBox(height: 12),
Expanded(