Files
unionflow-server-impl-quarkus/unionflow-mobile-apps/lib/features/members/data/services/membre_search_service.dart
2025-11-17 16:02:04 +00:00

279 lines
7.3 KiB
Dart

import 'package:dio/dio.dart';
import '../../../../shared/models/membre_search_criteria.dart';
import '../../../../shared/models/membre_search_result.dart';
/// Service pour la recherche avancée de membres
/// Gère les appels API vers l'endpoint de recherche sophistiquée
class MembreSearchService {
final Dio _dio;
MembreSearchService(this._dio);
/// Effectue une recherche avancée de membres
///
/// [criteria] Critères de recherche
/// [page] Numéro de page (0-based)
/// [size] Taille de la page
/// [sortField] Champ de tri
/// [sortDirection] Direction du tri (asc/desc)
///
/// Returns [MembreSearchResult] avec les résultats paginés
Future<MembreSearchResult> searchMembresAdvanced({
required MembreSearchCriteria criteria,
int page = 0,
int size = 20,
String sortField = 'nom',
String sortDirection = 'asc',
}) async {
print('Recherche avancée de membres: ${criteria.description}');
try {
// Validation des critères
if (!criteria.hasAnyCriteria) {
throw Exception('Au moins un critère de recherche doit être spécifié');
}
if (!criteria.isValid) {
throw Exception('Critères de recherche invalides');
}
// Préparation des paramètres de requête
final queryParams = {
'page': page.toString(),
'size': size.toString(),
'sort': sortField,
'direction': sortDirection,
};
// Appel API
final response = await _dio.post(
'/api/membres/search/advanced',
data: criteria.toJson(),
queryParameters: queryParams,
);
// Parsing de la réponse
final result = MembreSearchResult.fromJson(response.data);
print('Recherche terminée: ${result.totalElements} résultats en ${result.executionTimeMs}ms');
return result;
} on DioException catch (e) {
print('Erreur lors de la recherche avancée: $e');
rethrow;
} catch (e) {
print('Erreur inattendue lors de la recherche: $e');
rethrow;
}
}
/// Recherche rapide par terme général
///
/// [query] Terme de recherche
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les résultats
Future<MembreSearchResult> quickSearch({
required String query,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria.quickSearch(query);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Recherche des membres actifs uniquement
///
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres actifs
Future<MembreSearchResult> searchActiveMembers({
int page = 0,
int size = 20,
}) async {
return searchMembresAdvanced(
criteria: MembreSearchCriteria.activeMembers,
page: page,
size: size,
);
}
/// Recherche des membres du bureau
///
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres du bureau
Future<MembreSearchResult> searchBureauMembers({
int page = 0,
int size = 20,
}) async {
return searchMembresAdvanced(
criteria: MembreSearchCriteria.bureauMembers,
page: page,
size: size,
);
}
/// Recherche par organisation
///
/// [organisationIds] Liste des IDs d'organisations
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres des organisations
Future<MembreSearchResult> searchByOrganisations({
required List<String> organisationIds,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria(
organisationIds: organisationIds,
statut: 'ACTIF',
);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Recherche par tranche d'âge
///
/// [ageMin] Âge minimum
/// [ageMax] Âge maximum
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres dans la tranche d'âge
Future<MembreSearchResult> searchByAgeRange({
int? ageMin,
int? ageMax,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria(
ageMin: ageMin,
ageMax: ageMax,
statut: 'ACTIF',
);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Recherche par région
///
/// [region] Nom de la région
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres de la région
Future<MembreSearchResult> searchByRegion({
required String region,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria(
region: region,
statut: 'ACTIF',
);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Recherche par rôles
///
/// [roles] Liste des rôles
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres ayant ces rôles
Future<MembreSearchResult> searchByRoles({
required List<String> roles,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria(
roles: roles,
statut: 'ACTIF',
);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Recherche par période d'adhésion
///
/// [dateMin] Date minimum (ISO 8601)
/// [dateMax] Date maximum (ISO 8601)
/// [page] Numéro de page
/// [size] Taille de la page
///
/// Returns [MembreSearchResult] avec les membres adhérés dans la période
Future<MembreSearchResult> searchByAdhesionPeriod({
String? dateMin,
String? dateMax,
int page = 0,
int size = 20,
}) async {
final criteria = MembreSearchCriteria(
dateAdhesionMin: dateMin,
dateAdhesionMax: dateMax,
statut: 'ACTIF',
);
return searchMembresAdvanced(
criteria: criteria,
page: page,
size: size,
);
}
/// Valide les critères de recherche avant envoi
bool validateCriteria(MembreSearchCriteria criteria) {
if (!criteria.hasAnyCriteria) {
print('Aucun critère de recherche spécifié');
return false;
}
if (!criteria.isValid) {
print('Critères de recherche invalides: ${criteria.description}');
return false;
}
return true;
}
/// Estime le temps de recherche basé sur les critères
Duration estimateSearchTime(MembreSearchCriteria criteria) {
// Estimation basique - peut être améliorée avec des métriques réelles
int complexityScore = 0;
if (criteria.query?.isNotEmpty == true) complexityScore += 2;
if (criteria.organisationIds?.isNotEmpty == true) complexityScore += 1;
if (criteria.roles?.isNotEmpty == true) complexityScore += 1;
if (criteria.ageMin != null || criteria.ageMax != null) complexityScore += 1;
if (criteria.dateAdhesionMin != null || criteria.dateAdhesionMax != null) complexityScore += 1;
// Temps de base + complexité
const baseTime = 100; // 100ms de base
final additionalTime = complexityScore * 50; // 50ms par critère
return Duration(milliseconds: baseTime + additionalTime);
}
}