feat(inscription): email accusé réception, photos enfants, formulaires identité

- Backend: mail après inscription parent avec n° dossier, UPLOAD_PHOTOS_DIR, réponse API
- Frontend: imageBytes + payload photo, utils email/code postal/téléphone, champs dédiés
- Formulaires admin, login (focus), personal_info, child_card, custom_app_text_field

Made-with: Cursor
This commit is contained in:
2026-03-31 00:04:38 +02:00
parent 110240b682
commit bf05b1d7d7
20 changed files with 1148 additions and 273 deletions
+57
View File
@@ -0,0 +1,57 @@
import 'package:flutter/services.dart';
/// Longueur maximale dune adresse e-mail (RFC 5321).
const int kEmailMaxLength = 254;
/// Trim + minuscules (usage à la perte de focus et avant validation côté API).
String normalizeEmailText(String raw) {
return raw.trim().toLowerCase();
}
/// Motif volontairement simple pour lUI (pas une validation RFC complète).
/// Local + @ + domaine avec au moins un point ; pas despaces.
final RegExp kAppEmailPattern = RegExp(
r'^[a-zA-Z0-9._%+\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,63}$',
);
/// Indique si [trimmed] est un e-mail plausible (insensible à la casse).
bool isValidEmailFormat(String trimmed) {
final s = normalizeEmailText(trimmed);
if (s.isEmpty || s.length > kEmailMaxLength) {
return false;
}
return kAppEmailPattern.hasMatch(s);
}
/// Validation centralisée pour les champs e-mail.
///
/// Si [allowEmpty] est `true`, une chaîne vide (après trim) est acceptée.
String? validateEmail(String? raw, {bool allowEmpty = false}) {
final s = normalizeEmailText(raw ?? '');
if (s.isEmpty) {
return allowEmpty ? null : 'Ladresse e-mail est obligatoire.';
}
if (s.length > kEmailMaxLength) {
return 'Ladresse e-mail est trop longue ($kEmailMaxLength caractères maximum).';
}
if (!kAppEmailPattern.hasMatch(s)) {
return 'Le format de ladresse e-mail est incorrect.';
}
return null;
}
/// Limite la longueur saisie dans un champ e-mail ([kEmailMaxLength]).
class EmailMaxLengthFormatter extends TextInputFormatter {
const EmailMaxLengthFormatter();
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
if (newValue.text.length <= kEmailMaxLength) {
return newValue;
}
return oldValue;
}
}