diff --git a/frontend/lib/models/reprise_dossier.dart b/frontend/lib/models/reprise_dossier.dart index 0275354..3d416f0 100644 --- a/frontend/lib/models/reprise_dossier.dart +++ b/frontend/lib/models/reprise_dossier.dart @@ -1,4 +1,5 @@ import 'package:p_tits_pas/models/dossier_unifie.dart'; +import 'package:p_tits_pas/utils/reprise_mapper.dart'; /// Réponse GET /auth/reprise-dossier. Tickets #111, #112. class RepriseDossier { @@ -20,7 +21,7 @@ class RepriseDossier { final List enfants; final String? texteMotivation; - final bool? consentementPhoto; + final bool consentementPhoto; final String? dateNaissance; final String? lieuNaissanceVille; final String? lieuNaissancePays; @@ -48,7 +49,7 @@ class RepriseDossier { this.parents = const [], this.enfants = const [], this.texteMotivation, - this.consentementPhoto, + this.consentementPhoto = false, this.dateNaissance, this.lieuNaissanceVille, this.lieuNaissancePays, @@ -80,9 +81,6 @@ class RepriseDossier { .toList() : []; - final nbMax = json['nb_max_enfants']; - final places = json['place_disponible']; - return RepriseDossier( id: json['id']?.toString() ?? '', email: json['email']?.toString() ?? '', @@ -101,17 +99,22 @@ class RepriseDossier { enfants: enfantsList, texteMotivation: (json['texte_motivation'] ?? json['presentation_dossier']) ?.toString(), - consentementPhoto: json['consentement_photo'] == true, - dateNaissance: json['date_naissance']?.toString(), + consentementPhoto: RepriseMapper.optionalBool(json['consentement_photo']) || + RepriseMapper.optionalBool(json['consent_photo']), + dateNaissance: RepriseMapper.optionalDateString(json['date_naissance']), lieuNaissanceVille: json['lieu_naissance_ville']?.toString(), lieuNaissancePays: json['lieu_naissance_pays']?.toString(), - numeroAgrement: json['numero_agrement']?.toString(), + numeroAgrement: (json['numero_agrement'] ?? json['numero_agrement_am']) + ?.toString(), nir: json['nir']?.toString(), - dateAgrement: json['date_agrement']?.toString(), - nbMaxEnfants: nbMax is int ? nbMax : (nbMax is num ? nbMax.toInt() : null), - placeDisponible: - places is int ? places : (places is num ? places.toInt() : null), - biographie: json['biographie']?.toString(), + dateAgrement: RepriseMapper.optionalDateString(json['date_agrement']), + nbMaxEnfants: RepriseMapper.optionalInt( + json['nb_max_enfants'] ?? json['capacite_accueil'], + ), + placeDisponible: RepriseMapper.optionalInt( + json['place_disponible'] ?? json['places_disponibles'], + ), + biographie: (json['biographie'] ?? json['presentation'])?.toString(), ); } } diff --git a/frontend/lib/screens/auth/am_register_step2_screen.dart b/frontend/lib/screens/auth/am_register_step2_screen.dart index 2f98b0e..8a7e3e4 100644 --- a/frontend/lib/screens/auth/am_register_step2_screen.dart +++ b/frontend/lib/screens/auth/am_register_step2_screen.dart @@ -29,6 +29,12 @@ class AmRegisterStep2Screen extends StatelessWidget { ); return ProfessionalInfoFormScreen( + key: ValueKey( + 'am-pro-${registrationData.dateOfBirth?.millisecondsSinceEpoch}' + '-${registrationData.agreementDate?.millisecondsSinceEpoch}' + '-${registrationData.placesAvailable}' + '-${registrationData.nir}', + ), stepText: 'Étape 2/4', title: 'Vos informations professionnelles', cardColor: CardColorHorizontal.green, diff --git a/frontend/lib/screens/auth/login_screen.dart b/frontend/lib/screens/auth/login_screen.dart index ab1c2e0..6f1efd0 100644 --- a/frontend/lib/screens/auth/login_screen.dart +++ b/frontend/lib/screens/auth/login_screen.dart @@ -377,8 +377,6 @@ class _LoginPageState extends State { ), ), const SizedBox(height: 10), - Center(child: _buildRepriseDossierLink()), - const SizedBox(height: 10), // Lien mot de passe oublié Center( child: TextButton( @@ -412,6 +410,7 @@ class _LoginPageState extends State { ), ), ), + Center(child: _buildRepriseDossierLink()), ], ), ), @@ -645,7 +644,6 @@ class _LoginPageState extends State { onPressed: _handleLogin, ), const SizedBox(height: 12), - _buildRepriseDossierLink(), TextButton( onPressed: () => context.go('/forgot-password'), child: Text( @@ -669,6 +667,7 @@ class _LoginPageState extends State { ), ), ), + _buildRepriseDossierLink(), ], ), ), diff --git a/frontend/lib/services/reprise_session.dart b/frontend/lib/services/reprise_session.dart index 8309371..6f9fc8a 100644 --- a/frontend/lib/services/reprise_session.dart +++ b/frontend/lib/services/reprise_session.dart @@ -53,26 +53,6 @@ class RepriseSession { } static void applyToAm(AmRegistrationData data, RepriseDossier dossier) { - final displayPhoto = _photoUrl; - data.resetForReprise( - firstName: dossier.prenom ?? '', - lastName: dossier.nom ?? '', - phone: dossier.telephone ?? '', - email: dossier.email, - streetAddress: dossier.adresse ?? '', - postalCode: dossier.codePostal ?? '', - city: dossier.ville ?? '', - existingPhotoUrl: displayPhoto, - consentementPhoto: dossier.consentementPhoto ?? false, - dateOfBirth: RepriseMapper.parseIsoDate(dossier.dateNaissance), - birthCity: dossier.lieuNaissanceVille ?? '', - birthCountry: dossier.lieuNaissancePays ?? '', - nir: dossier.nir ?? '', - agrementNumber: dossier.numeroAgrement ?? '', - agreementDate: RepriseMapper.parseIsoDate(dossier.dateAgrement), - capacity: dossier.nbMaxEnfants, - placesAvailable: dossier.placeDisponible, - presentationText: dossier.biographie ?? '', - ); + RepriseMapper.applyAmDossier(data, dossier); } } diff --git a/frontend/lib/utils/reprise_mapper.dart b/frontend/lib/utils/reprise_mapper.dart index 6720f9f..6691b7d 100644 --- a/frontend/lib/utils/reprise_mapper.dart +++ b/frontend/lib/utils/reprise_mapper.dart @@ -1,3 +1,4 @@ +import 'package:p_tits_pas/models/am_registration_data.dart'; import 'package:p_tits_pas/models/card_assets.dart'; import 'package:p_tits_pas/models/dossier_unifie.dart'; import 'package:p_tits_pas/models/reprise_dossier.dart'; @@ -106,13 +107,79 @@ class RepriseMapper { static DateTime? parseIsoDate(String? raw) { if (raw == null || raw.trim().isEmpty) return null; + final s = raw.trim(); try { - return DateTime.parse(raw.trim()); + return DateTime.parse(s); } catch (_) { + final parts = s.split('/'); + if (parts.length == 3) { + final day = int.tryParse(parts[0]); + final month = int.tryParse(parts[1]); + final year = int.tryParse(parts[2]); + if (day != null && month != null && year != null) { + return DateTime(year, month, day); + } + } return null; } } + static String? optionalDateString(dynamic value) { + if (value == null) return null; + if (value is String) { + final s = value.trim(); + return s.isEmpty ? null : s; + } + if (value is DateTime) return value.toIso8601String(); + return null; + } + + static int? optionalInt(dynamic value) { + if (value == null) return null; + if (value is int) return value; + if (value is num) return value.toInt(); + if (value is String) { + final s = value.trim(); + if (s.isEmpty) return null; + return int.tryParse(s); + } + return null; + } + + static bool optionalBool(dynamic value) { + if (value == true) return true; + if (value is String && value.toLowerCase() == 'true') return true; + return false; + } + + static void applyAmDossier(AmRegistrationData data, RepriseDossier dossier) { + final rawPhoto = dossier.photoUrl?.trim(); + final hasPhoto = rawPhoto != null && rawPhoto.isNotEmpty; + final displayPhoto = + hasPhoto ? ApiConfig.absoluteMediaUrl(rawPhoto) : null; + + data.resetForReprise( + firstName: dossier.prenom ?? '', + lastName: dossier.nom ?? '', + phone: dossier.telephone ?? '', + email: dossier.email, + streetAddress: dossier.adresse ?? '', + postalCode: dossier.codePostal ?? '', + city: dossier.ville ?? '', + existingPhotoUrl: displayPhoto, + consentementPhoto: dossier.consentementPhoto || hasPhoto, + dateOfBirth: parseIsoDate(dossier.dateNaissance), + birthCity: dossier.lieuNaissanceVille ?? '', + birthCountry: dossier.lieuNaissancePays ?? '', + nir: dossier.nir ?? '', + agrementNumber: dossier.numeroAgrement ?? '', + agreementDate: parseIsoDate(dossier.dateAgrement), + capacity: dossier.nbMaxEnfants, + placesAvailable: dossier.placeDisponible, + presentationText: dossier.biographie ?? '', + ); + } + static String isoToDdMmYyyy(String? iso) { final dt = parseIsoDate(iso); if (dt == null) return '';