petitspas/frontend/lib/models/am_registration_data.dart
Julien Martin 58607cdbc9 feat(inscription AM #120): UI étape pro, photo unifiée, scripts et données test
- Panneau AM : validation NIR alignée API, date d’agrément requise côté app,
  capacité 1–10, n° agrément + date sur une ligne, ville/pays formatés au blur.
- Widget RegistrationPhotoSlot (cadre, croix) partagé avec les cartes enfant.
- AuthService : MIME PNG/JPEG pour la photo ; payload date_agrement.
- Scripts register-am-dubois / mansouri ; chemins tests/ressources/photos ;
  doc test-data + seed ; smoke curl inscription AM.

Made-with: Cursor
2026-04-13 13:19:32 +02:00

150 lines
5.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/foundation.dart';
class AmRegistrationData extends ChangeNotifier {
// Step 1: Identity Info
String firstName = '';
String lastName = '';
String streetAddress = ''; // Nouveau pour N° et Rue
String postalCode = ''; // Nouveau
String city = ''; // Nouveau
String phone = '';
String email = '';
String password = '';
// String? photoPath; // Déplacé ou géré à l'étape 2
// bool photoConsent = false; // Déplacé ou géré à l'étape 2
// Step 2: Professional Info
String? photoPath; // Chemin fichier local (hors web) si pas doctets en mémoire
Uint8List? photoBytes; // Galerie / web (ImagePicker)
String? photoFilename; // Nom pour lAPI (ex. image.jpg)
bool photoConsent = false; // Ajouté pour l'étape 2
DateTime? dateOfBirth;
String birthCity = ''; // Nouveau
String birthCountry = ''; // Nouveau
// String placeOfBirth = ''; // Remplacé par birthCity et birthCountry
String nir = ''; // Numéro de Sécurité Sociale
String agrementNumber = ''; // Numéro d'agrément
/// Date d'obtention de l'agrément — obligatoire (API `date_agrement`).
DateTime? agreementDate;
int? capacity; // Number of children the AM can look after
// Step 3: Presentation & CGU
String presentationText = '';
bool cguAccepted = false;
// --- Methods to update data and notify listeners ---
void updateIdentityInfo({
String? firstName,
String? lastName,
String? streetAddress, // Modifié
String? postalCode, // Nouveau
String? city, // Nouveau
String? phone,
String? email,
String? password,
}) {
this.firstName = firstName ?? this.firstName;
this.lastName = lastName ?? this.lastName;
this.streetAddress = streetAddress ?? this.streetAddress; // Modifié
this.postalCode = postalCode ?? this.postalCode; // Nouveau
this.city = city ?? this.city; // Nouveau
this.phone = phone ?? this.phone;
this.email = email ?? this.email;
this.password = password ?? this.password;
// if (photoPath != null || this.photoPath != null) { // Supprimé de l'étape 1
// this.photoPath = photoPath;
// }
// this.photoConsent = photoConsent ?? this.photoConsent; // Supprimé de l'étape 1
notifyListeners();
}
void updateProfessionalInfo({
String? photoPath,
Uint8List? photoBytes,
String? photoFilename,
bool? photoConsent,
DateTime? dateOfBirth,
String? birthCity, // Nouveau
String? birthCountry, // Nouveau
// String? placeOfBirth, // Remplacé
String? nir,
String? agrementNumber,
DateTime? agreementDate,
int? capacity,
}) {
this.photoPath = photoPath;
this.photoBytes = photoBytes;
this.photoFilename = photoFilename;
this.photoConsent = photoConsent ?? this.photoConsent;
this.dateOfBirth = dateOfBirth ?? this.dateOfBirth;
this.birthCity = birthCity ?? this.birthCity; // Nouveau
this.birthCountry = birthCountry ?? this.birthCountry; // Nouveau
// this.placeOfBirth = placeOfBirth ?? this.placeOfBirth; // Remplacé
this.nir = nir ?? this.nir;
this.agrementNumber = agrementNumber ?? this.agrementNumber;
this.agreementDate = agreementDate ?? this.agreementDate;
this.capacity = capacity ?? this.capacity;
notifyListeners();
}
void updatePresentationAndCgu({
String? presentationText,
bool? cguAccepted,
}) {
this.presentationText = presentationText ?? this.presentationText;
this.cguAccepted = cguAccepted ?? this.cguAccepted;
notifyListeners();
}
// --- Getters for validation or display ---
bool get isStep1Complete =>
firstName.isNotEmpty &&
lastName.isNotEmpty &&
streetAddress.isNotEmpty && // Modifié
postalCode.isNotEmpty && // Nouveau
city.isNotEmpty && // Nouveau
phone.isNotEmpty &&
email.isNotEmpty;
// password n'est pas requis à l'inscription (défini après validation par lien email)
/// Photo réelle (pas seulement un placeholder asset).
bool get _hasUserPhoto =>
(photoBytes != null && photoBytes!.isNotEmpty) ||
(photoPath != null &&
photoPath!.isNotEmpty &&
!photoPath!.startsWith('assets/'));
bool get isStep2Complete =>
(_hasUserPhoto ? photoConsent == true : true) &&
dateOfBirth != null &&
birthCity.isNotEmpty &&
birthCountry.isNotEmpty &&
nir.isNotEmpty && // Basic check, could add validation
agrementNumber.isNotEmpty &&
agreementDate != null &&
capacity != null &&
capacity! >= 1 &&
capacity! <= 10;
bool get isStep3Complete =>
// presentationText is optional as per CDC (message au gestionnaire)
cguAccepted;
bool get isRegistrationComplete =>
isStep1Complete && isStep2Complete && isStep3Complete;
@override
String toString() {
return 'AmRegistrationData('
'firstName: $firstName, lastName: $lastName, '
'streetAddress: $streetAddress, postalCode: $postalCode, city: $city, '
'phone: $phone, email: $email, '
// 'photoPath: $photoPath, photoConsent: $photoConsent, ' // Commenté car déplacé/modifié
'dateOfBirth: $dateOfBirth, birthCity: $birthCity, birthCountry: $birthCountry, '
'nir: $nir, agrementNumber: $agrementNumber, agreementDate: $agreementDate, capacity: $capacity, '
'photoPath (step2): $photoPath, photoConsent (step2): $photoConsent, '
'presentationText: $presentationText, cguAccepted: $cguAccepted)';
}
}