import 'package:p_tits_pas/models/user.dart'; /// Réponse unifiée GET /dossiers/:numeroDossier. Ticket #119, #107. class DossierUnifie { final String type; // 'am' | 'family' final dynamic dossier; // DossierAM | DossierFamille DossierUnifie({required this.type, required this.dossier}); bool get isAm => type == 'am'; bool get isFamily => type == 'family'; DossierAM get asAm => dossier as DossierAM; DossierFamille get asFamily => dossier as DossierFamille; factory DossierUnifie.fromJson(Map json) { final t = json['type']; final raw = t is String ? t : 'family'; final typeStr = raw.toLowerCase(); final d = json['dossier']; if (d == null || d is! Map) { throw FormatException('dossier manquant ou invalide'); } final dossierMap = Map.from(d as Map); // Seul `am` (casse tolérée) charge le dossier AM ; le reste = famille (API : type "family"). final isAm = typeStr == 'am'; final dossier = isAm ? DossierAM.fromJson(dossierMap) : DossierFamille.fromJson(dossierMap); return DossierUnifie(type: isAm ? 'am' : 'family', dossier: dossier); } } /// Dossier AM (type: 'am'). Champs alignés API. class DossierAM { final String? numeroDossier; final AppUser user; final String? numeroAgrement; final String? nir; final String? presentation; final String? dateAgrement; final int? nbMaxEnfants; final int? placesDisponibles; final String? villeResidence; DossierAM({ this.numeroDossier, required this.user, this.numeroAgrement, this.nir, this.presentation, this.dateAgrement, this.nbMaxEnfants, this.placesDisponibles, this.villeResidence, }); factory DossierAM.fromJson(Map json) { final userJson = json['user']; final userMap = userJson is Map ? userJson : {}; final nbMax = json['nb_max_enfants']; final places = json['place_disponible']; return DossierAM( numeroDossier: json['numero_dossier']?.toString(), user: AppUser.fromJson(Map.from(userMap)), numeroAgrement: json['numero_agrement']?.toString(), nir: json['nir']?.toString(), presentation: (json['biographie'] ?? json['presentation'])?.toString(), dateAgrement: json['date_agrement']?.toString(), nbMaxEnfants: nbMax is int ? nbMax : (nbMax is num ? nbMax.toInt() : null), placesDisponibles: places is int ? places : (places is num ? places.toInt() : null), villeResidence: json['ville_residence']?.toString(), ); } } /// Dossier famille (type: 'family'). Champs alignés API. class DossierFamille { final String? numeroDossier; final List parents; final List enfants; final String? presentation; DossierFamille({ this.numeroDossier, required this.parents, required this.enfants, this.presentation, }); factory DossierFamille.fromJson(Map json) { final parentsRaw = json['parents']; final parentsList = parentsRaw is List ? (parentsRaw) .where((e) => e is Map) .map((e) => ParentDossier.fromJson(Map.from(e as Map))) .toList() : []; final enfantsRaw = json['enfants']; final enfantsList = enfantsRaw is List ? (enfantsRaw) .where((e) => e is Map) .map((e) => EnfantDossier.fromJson(Map.from(e as Map))) .toList() : []; return DossierFamille( numeroDossier: json['numero_dossier']?.toString(), parents: parentsList, enfants: enfantsList, presentation: (json['texte_motivation'] ?? json['presentation'])?.toString(), ); } bool get isEnAttente => parents.any((p) => p.statut == 'en_attente'); } /// Parent dans un dossier famille (champs user exposés). class ParentDossier { final String id; final String email; final String? prenom; final String? nom; final String? telephone; final String? adresse; final String? ville; final String? codePostal; final String? dateNaissance; final String? genre; final String? situationFamiliale; final String? creeLe; final String? statut; ParentDossier({ required this.id, required this.email, this.prenom, this.nom, this.telephone, this.adresse, this.ville, this.codePostal, this.dateNaissance, this.genre, this.situationFamiliale, this.creeLe, this.statut, }); String get fullName => '${prenom ?? ''} ${nom ?? ''}'.trim(); factory ParentDossier.fromJson(Map json) { return ParentDossier( id: json['id']?.toString() ?? '', email: json['email']?.toString() ?? '', prenom: json['prenom']?.toString(), nom: json['nom']?.toString(), telephone: json['telephone']?.toString(), adresse: json['adresse']?.toString(), ville: json['ville']?.toString(), codePostal: json['code_postal']?.toString(), dateNaissance: json['date_naissance']?.toString(), genre: json['genre']?.toString(), situationFamiliale: json['situation_familiale']?.toString(), creeLe: json['cree_le']?.toString(), statut: json['statut']?.toString(), ); } } /// Enfant dans un dossier famille. class EnfantDossier { final String id; final String? firstName; final String? lastName; final String? birthDate; final String? gender; final String? status; final String? dueDate; final String? photoUrl; final bool consentPhoto; EnfantDossier({ required this.id, this.firstName, this.lastName, this.birthDate, this.gender, this.status, this.dueDate, this.photoUrl, this.consentPhoto = false, }); String get fullName => '${firstName ?? ''} ${lastName ?? ''}'.trim(); factory EnfantDossier.fromJson(Map json) { return EnfantDossier( id: json['id']?.toString() ?? '', firstName: (json['first_name'] ?? json['prenom'])?.toString(), lastName: (json['last_name'] ?? json['nom'])?.toString(), birthDate: json['birth_date']?.toString(), gender: (json['gender'] ?? json['genre'])?.toString(), status: json['status']?.toString(), dueDate: json['due_date']?.toString(), photoUrl: json['photo_url']?.toString(), consentPhoto: json['consent_photo'] == true, ); } }