172 lines
5.3 KiB
Dart
172 lines
5.3 KiB
Dart
import 'package:p_tits_pas/models/user.dart';
|
|
import 'package:p_tits_pas/utils/enfant_status_utils.dart';
|
|
|
|
/// Enfant tel que renvoyé par `GET /enfants` (dashboard admin).
|
|
class EnfantAdminModel {
|
|
final String id;
|
|
final String? firstName;
|
|
final String? lastName;
|
|
final String? gender;
|
|
final String? birthDate;
|
|
final String? dueDate;
|
|
final String status;
|
|
final String? photoUrl;
|
|
final bool consentPhoto;
|
|
final bool isMultiple;
|
|
final List<EnfantParentLink> parentLinks;
|
|
|
|
EnfantAdminModel({
|
|
required this.id,
|
|
this.firstName,
|
|
this.lastName,
|
|
this.gender,
|
|
this.birthDate,
|
|
this.dueDate,
|
|
required this.status,
|
|
this.photoUrl,
|
|
this.consentPhoto = false,
|
|
this.isMultiple = false,
|
|
this.parentLinks = const [],
|
|
});
|
|
|
|
String get fullName {
|
|
final fn = (firstName ?? '').trim();
|
|
final ln = (lastName ?? '').trim();
|
|
if (fn.isEmpty && ln.isEmpty) return 'Enfant';
|
|
if (ln.isEmpty) return fn;
|
|
return '$fn $ln';
|
|
}
|
|
|
|
/// Aucun lien parent valide (`enfants_parents` vide) — ticket #157.
|
|
bool get hasNoResponsable =>
|
|
!parentLinks.any((l) => l.parentId.trim().isNotEmpty);
|
|
|
|
EnfantAdminModel copyWith({
|
|
String? id,
|
|
String? firstName,
|
|
String? lastName,
|
|
String? gender,
|
|
String? birthDate,
|
|
String? dueDate,
|
|
String? status,
|
|
String? photoUrl,
|
|
bool? consentPhoto,
|
|
bool? isMultiple,
|
|
List<EnfantParentLink>? parentLinks,
|
|
}) {
|
|
return EnfantAdminModel(
|
|
id: id ?? this.id,
|
|
firstName: firstName ?? this.firstName,
|
|
lastName: lastName ?? this.lastName,
|
|
gender: gender ?? this.gender,
|
|
birthDate: birthDate ?? this.birthDate,
|
|
dueDate: dueDate ?? this.dueDate,
|
|
status: status ?? this.status,
|
|
photoUrl: photoUrl ?? this.photoUrl,
|
|
consentPhoto: consentPhoto ?? this.consentPhoto,
|
|
isMultiple: isMultiple ?? this.isMultiple,
|
|
parentLinks: parentLinks ?? this.parentLinks,
|
|
);
|
|
}
|
|
|
|
factory EnfantAdminModel.fromJson(Map<String, dynamic> json) {
|
|
final linksRaw = json['parentLinks'] as List?;
|
|
final links = <EnfantParentLink>[];
|
|
if (linksRaw != null) {
|
|
for (final item in linksRaw) {
|
|
if (item is Map<String, dynamic>) {
|
|
links.add(EnfantParentLink.fromJson(item));
|
|
}
|
|
}
|
|
}
|
|
|
|
final photoUrl = json['photo_url'] as String? ?? json['photoUrl'] as String?;
|
|
final consentPhoto = _parseBool(json['consent_photo']) ||
|
|
_parseBool(json['consentement_photo']) ||
|
|
_parseBool(json['consentPhoto']);
|
|
|
|
return EnfantAdminModel(
|
|
id: (json['id'] ?? '').toString(),
|
|
firstName: json['first_name'] as String? ?? json['prenom'] as String?,
|
|
lastName: json['last_name'] as String? ?? json['nom'] as String?,
|
|
gender: json['gender'] as String? ?? json['genre'] as String?,
|
|
birthDate: _dateString(json['birth_date'] ?? json['date_naissance']),
|
|
dueDate: _dateString(json['due_date'] ?? json['date_prevue_naissance']),
|
|
status: normalizeEnfantStatus(
|
|
(json['status'] ?? json['statut'])?.toString(),
|
|
),
|
|
photoUrl: photoUrl,
|
|
consentPhoto: consentPhoto,
|
|
isMultiple: _parseBool(json['is_multiple']) ||
|
|
_parseBool(json['est_multiple']),
|
|
parentLinks: links,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toUpdateJson() {
|
|
return {
|
|
if (firstName != null) 'first_name': firstName,
|
|
if (lastName != null) 'last_name': lastName,
|
|
if (gender != null && gender!.isNotEmpty) 'gender': gender,
|
|
'status': status,
|
|
if (birthDate != null && birthDate!.isNotEmpty) 'birth_date': birthDate,
|
|
if (dueDate != null && dueDate!.isNotEmpty) 'due_date': dueDate,
|
|
'consent_photo': consentPhoto,
|
|
'is_multiple': isMultiple,
|
|
};
|
|
}
|
|
|
|
static bool _parseBool(dynamic value) {
|
|
if (value == true || value == 1) return true;
|
|
if (value is String) {
|
|
final s = value.trim().toLowerCase();
|
|
return s == 'true' || s == '1' || s == 't' || s == 'yes';
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static String? _dateString(dynamic v) {
|
|
if (v == null) return null;
|
|
if (v is String) return v.split('T').first;
|
|
return v.toString().split('T').first;
|
|
}
|
|
}
|
|
|
|
class EnfantParentLink {
|
|
final String parentId;
|
|
final String? parentName;
|
|
|
|
EnfantParentLink({required this.parentId, this.parentName});
|
|
|
|
EnfantParentLink copyWith({String? parentId, String? parentName}) {
|
|
return EnfantParentLink(
|
|
parentId: parentId ?? this.parentId,
|
|
parentName: parentName ?? this.parentName,
|
|
);
|
|
}
|
|
|
|
factory EnfantParentLink.fromJson(Map<String, dynamic> json) {
|
|
final parentId =
|
|
(json['parentId'] ?? json['id_parent'] ?? '').toString();
|
|
String? name;
|
|
final parent = json['parent'];
|
|
if (parent is Map<String, dynamic>) {
|
|
final user = parent['user'];
|
|
if (user is Map<String, dynamic>) {
|
|
final u = AppUser.fromJson(user);
|
|
name = u.fullName.isNotEmpty ? u.fullName : u.email;
|
|
} else {
|
|
// Parfois le parent est aplati (prenom/nom) sans nested user.
|
|
final prenom = (parent['prenom'] ?? parent['first_name'] ?? '').toString().trim();
|
|
final nom = (parent['nom'] ?? parent['last_name'] ?? '').toString().trim();
|
|
final flat = '$prenom $nom'.trim();
|
|
if (flat.isNotEmpty) name = flat;
|
|
}
|
|
}
|
|
return EnfantParentLink(
|
|
parentId: parentId,
|
|
parentName: name,
|
|
);
|
|
}
|
|
}
|