329 lines
9.5 KiB
Dart
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'})';
|
|
}
|