feat(frontend): inscription — UI cartes enfant, formatage noms, focus Tab
- Formulaire infos perso : ordre de tabulation explicite, Checkbox Material pour le consentement photo, formatage nom/prénom/ville à la perte de focus et à la soumission (name_format_utils). - Carte enfant : cadre photo, croix, ombres, consentement ; formatage prénom/nom enfant ; normalisation avant passage étape 4. - Asset photo_frame.png ; HoverReliefWidget clipBehavior. - Ajustements payload / modèle / étapes inscription liés au parcours. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/// Formatage affichage prénom / nom (capitalisation par mot et segments après `-` ou `'`).
|
||||
|
||||
String formatPersonNameCase(String raw) {
|
||||
final trimmed = raw.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return trimmed;
|
||||
}
|
||||
final words = trimmed.split(RegExp(r'\s+'));
|
||||
return words.map(_capitalizeComposedWord).join(' ');
|
||||
}
|
||||
|
||||
String _capitalizeComposedWord(String word) {
|
||||
if (word.isEmpty) {
|
||||
return word;
|
||||
}
|
||||
final lower = word.toLowerCase();
|
||||
const separators = <String>{'-', "'", '’'};
|
||||
final buffer = StringBuffer();
|
||||
var capitalizeNext = true;
|
||||
|
||||
for (var i = 0; i < lower.length; i++) {
|
||||
final char = lower[i];
|
||||
if (capitalizeNext && RegExp(r'[a-zà-öø-ÿ]').hasMatch(char)) {
|
||||
buffer.write(char.toUpperCase());
|
||||
capitalizeNext = false;
|
||||
} else {
|
||||
buffer.write(char);
|
||||
capitalizeNext = separators.contains(char);
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
@@ -59,12 +59,17 @@ class ParentRegistrationPayload {
|
||||
for (var i = 0; i < d.children.length; i++) {
|
||||
final c = d.children[i];
|
||||
final label = 'Enfant ${i + 1}';
|
||||
// Pas de saisie genre sur la carte (widget revenu à b18d5c8) : valeur par défaut côté JSON.
|
||||
if (!c.photoConsent) {
|
||||
return '$label : le consentement photo est obligatoire.';
|
||||
}
|
||||
if (c.isUnbornChild) {
|
||||
final due = _ddMmYyyyToIso(c.dob);
|
||||
if (due == null) {
|
||||
return '$label : indiquez une date de naissance prévisionnelle.';
|
||||
}
|
||||
if (!apiGenres.contains(c.genre)) {
|
||||
return '$label : indiquez Fille, Garçon ou Inconnu.';
|
||||
}
|
||||
} else {
|
||||
if (c.firstName.trim().length < 2) {
|
||||
return '$label : le prénom doit contenir au moins 2 caractères.';
|
||||
@@ -73,6 +78,9 @@ class ParentRegistrationPayload {
|
||||
if (birth == null) {
|
||||
return '$label : indiquez une date de naissance valide.';
|
||||
}
|
||||
if (c.genre != 'H' && c.genre != 'F') {
|
||||
return '$label : indiquez Fille ou Garçon.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +142,7 @@ class ParentRegistrationPayload {
|
||||
static Map<String, dynamic> _childToJson(ChildData c, int index, String parentNom) {
|
||||
final map = <String, dynamic>{
|
||||
'genre': apiGenres.contains(c.genre) ? c.genre : 'Autre',
|
||||
'grossesse_multiple': c.multipleBirth,
|
||||
'grossesse_multiple': false,
|
||||
};
|
||||
|
||||
final prenom = c.firstName.trim();
|
||||
|
||||
Reference in New Issue
Block a user