Files
unionflow-server-impl-quarkus/unionflow-mobile-apps/lib/shared/models/membre_search_criteria.dart
2025-11-17 16:02:04 +00:00

329 lines
9.5 KiB
Dart

/// Modèle pour les critères de recherche avancée des membres
/// Correspond au DTO Java MembreSearchCriteria
class MembreSearchCriteria {
/// Terme de recherche général (nom, prénom, email)
final String? query;
/// Recherche par nom exact ou partiel
final String? nom;
/// Recherche par prénom exact ou partiel
final String? prenom;
/// Recherche par email exact ou partiel
final String? email;
/// Filtre par numéro de téléphone
final String? telephone;
/// Liste des IDs d'organisations
final List<String>? organisationIds;
/// Liste des rôles à rechercher
final List<String>? roles;
/// Filtre par statut d'activité
final String? statut;
/// Date d'adhésion minimum (format ISO 8601)
final String? dateAdhesionMin;
/// Date d'adhésion maximum (format ISO 8601)
final String? dateAdhesionMax;
/// Âge minimum
final int? ageMin;
/// Âge maximum
final int? ageMax;
/// Filtre par région
final String? region;
/// Filtre par ville
final String? ville;
/// Filtre par profession
final String? profession;
/// Filtre par nationalité
final String? nationalite;
/// Filtre membres du bureau uniquement
final bool? membreBureau;
/// Filtre responsables uniquement
final bool? responsable;
/// Inclure les membres inactifs dans la recherche
final bool includeInactifs;
const MembreSearchCriteria({
this.query,
this.nom,
this.prenom,
this.email,
this.telephone,
this.organisationIds,
this.roles,
this.statut,
this.dateAdhesionMin,
this.dateAdhesionMax,
this.ageMin,
this.ageMax,
this.region,
this.ville,
this.profession,
this.nationalite,
this.membreBureau,
this.responsable,
this.includeInactifs = false,
});
/// Factory constructor pour créer depuis JSON
factory MembreSearchCriteria.fromJson(Map<String, dynamic> json) {
return MembreSearchCriteria(
query: json['query'] as String?,
nom: json['nom'] as String?,
prenom: json['prenom'] as String?,
email: json['email'] as String?,
telephone: json['telephone'] as String?,
organisationIds: (json['organisationIds'] as List<dynamic>?)?.cast<String>(),
roles: (json['roles'] as List<dynamic>?)?.cast<String>(),
statut: json['statut'] as String?,
dateAdhesionMin: json['dateAdhesionMin'] as String?,
dateAdhesionMax: json['dateAdhesionMax'] as String?,
ageMin: json['ageMin'] as int?,
ageMax: json['ageMax'] as int?,
region: json['region'] as String?,
ville: json['ville'] as String?,
profession: json['profession'] as String?,
nationalite: json['nationalite'] as String?,
membreBureau: json['membreBureau'] as bool?,
responsable: json['responsable'] as bool?,
includeInactifs: json['includeInactifs'] as bool? ?? false,
);
}
/// Convertit vers JSON
Map<String, dynamic> toJson() {
return {
'query': query,
'nom': nom,
'prenom': prenom,
'email': email,
'telephone': telephone,
'organisationIds': organisationIds,
'roles': roles,
'statut': statut,
'dateAdhesionMin': dateAdhesionMin,
'dateAdhesionMax': dateAdhesionMax,
'ageMin': ageMin,
'ageMax': ageMax,
'region': region,
'ville': ville,
'profession': profession,
'nationalite': nationalite,
'membreBureau': membreBureau,
'responsable': responsable,
'includeInactifs': includeInactifs,
};
}
/// Vérifie si au moins un critère de recherche est défini
bool get hasAnyCriteria {
return query?.isNotEmpty == true ||
nom?.isNotEmpty == true ||
prenom?.isNotEmpty == true ||
email?.isNotEmpty == true ||
telephone?.isNotEmpty == true ||
organisationIds?.isNotEmpty == true ||
roles?.isNotEmpty == true ||
statut?.isNotEmpty == true ||
dateAdhesionMin?.isNotEmpty == true ||
dateAdhesionMax?.isNotEmpty == true ||
ageMin != null ||
ageMax != null ||
region?.isNotEmpty == true ||
ville?.isNotEmpty == true ||
profession?.isNotEmpty == true ||
nationalite?.isNotEmpty == true ||
membreBureau != null ||
responsable != null;
}
/// Valide la cohérence des critères de recherche
bool get isValid {
// Validation des âges
if (ageMin != null && ageMax != null) {
if (ageMin! > ageMax!) {
return false;
}
}
// Validation des dates (si implémentée)
if (dateAdhesionMin != null && dateAdhesionMax != null) {
try {
final dateMin = DateTime.parse(dateAdhesionMin!);
final dateMax = DateTime.parse(dateAdhesionMax!);
if (dateMin.isAfter(dateMax)) {
return false;
}
} catch (e) {
return false;
}
}
return true;
}
/// Retourne une description textuelle des critères actifs
String get description {
final parts = <String>[];
if (query?.isNotEmpty == true) parts.add("Recherche: '$query'");
if (nom?.isNotEmpty == true) parts.add("Nom: '$nom'");
if (prenom?.isNotEmpty == true) parts.add("Prénom: '$prenom'");
if (email?.isNotEmpty == true) parts.add("Email: '$email'");
if (statut?.isNotEmpty == true) parts.add("Statut: $statut");
if (organisationIds?.isNotEmpty == true) {
parts.add("Organisations: ${organisationIds!.length}");
}
if (roles?.isNotEmpty == true) {
parts.add("Rôles: ${roles!.join(', ')}");
}
if (dateAdhesionMin?.isNotEmpty == true) {
parts.add("Adhésion >= $dateAdhesionMin");
}
if (dateAdhesionMax?.isNotEmpty == true) {
parts.add("Adhésion <= $dateAdhesionMax");
}
if (ageMin != null) parts.add("Âge >= $ageMin");
if (ageMax != null) parts.add("Âge <= $ageMax");
if (region?.isNotEmpty == true) parts.add("Région: '$region'");
if (ville?.isNotEmpty == true) parts.add("Ville: '$ville'");
if (profession?.isNotEmpty == true) parts.add("Profession: '$profession'");
if (nationalite?.isNotEmpty == true) parts.add("Nationalité: '$nationalite'");
if (membreBureau == true) parts.add("Membre bureau");
if (responsable == true) parts.add("Responsable");
return parts.join('');
}
/// Crée une copie avec des modifications
MembreSearchCriteria copyWith({
String? query,
String? nom,
String? prenom,
String? email,
String? telephone,
List<String>? organisationIds,
List<String>? roles,
String? statut,
String? dateAdhesionMin,
String? dateAdhesionMax,
int? ageMin,
int? ageMax,
String? region,
String? ville,
String? profession,
String? nationalite,
bool? membreBureau,
bool? responsable,
bool? includeInactifs,
}) {
return MembreSearchCriteria(
query: query ?? this.query,
nom: nom ?? this.nom,
prenom: prenom ?? this.prenom,
email: email ?? this.email,
telephone: telephone ?? this.telephone,
organisationIds: organisationIds ?? this.organisationIds,
roles: roles ?? this.roles,
statut: statut ?? this.statut,
dateAdhesionMin: dateAdhesionMin ?? this.dateAdhesionMin,
dateAdhesionMax: dateAdhesionMax ?? this.dateAdhesionMax,
ageMin: ageMin ?? this.ageMin,
ageMax: ageMax ?? this.ageMax,
region: region ?? this.region,
ville: ville ?? this.ville,
profession: profession ?? this.profession,
nationalite: nationalite ?? this.nationalite,
membreBureau: membreBureau ?? this.membreBureau,
responsable: responsable ?? this.responsable,
includeInactifs: includeInactifs ?? this.includeInactifs,
);
}
/// Critères vides
static const empty = MembreSearchCriteria();
/// Critères pour recherche rapide par nom/prénom
static MembreSearchCriteria quickSearch(String query) {
return MembreSearchCriteria(query: query);
}
/// Critères pour membres actifs uniquement
static const activeMembers = MembreSearchCriteria(
statut: 'ACTIF',
includeInactifs: false,
);
/// Critères pour membres du bureau
static const bureauMembers = MembreSearchCriteria(
membreBureau: true,
statut: 'ACTIF',
);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MembreSearchCriteria &&
runtimeType == other.runtimeType &&
query == other.query &&
nom == other.nom &&
prenom == other.prenom &&
email == other.email &&
telephone == other.telephone &&
organisationIds == other.organisationIds &&
roles == other.roles &&
statut == other.statut &&
dateAdhesionMin == other.dateAdhesionMin &&
dateAdhesionMax == other.dateAdhesionMax &&
ageMin == other.ageMin &&
ageMax == other.ageMax &&
region == other.region &&
ville == other.ville &&
profession == other.profession &&
nationalite == other.nationalite &&
membreBureau == other.membreBureau &&
responsable == other.responsable &&
includeInactifs == other.includeInactifs;
@override
int get hashCode => Object.hashAll([
query,
nom,
prenom,
email,
telephone,
organisationIds,
roles,
statut,
dateAdhesionMin,
dateAdhesionMax,
ageMin,
ageMax,
region,
ville,
profession,
nationalite,
membreBureau,
responsable,
includeInactifs,
]);
@override
String toString() => 'MembreSearchCriteria(${description.isNotEmpty ? description : 'empty'})';
}