Refactoring
This commit is contained in:
@@ -0,0 +1,843 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import '../../../../../core/error/failures.dart';
|
||||
import '../../../domain/entities/demande_aide.dart';
|
||||
import '../../../domain/usecases/gerer_demandes_aide_usecase.dart';
|
||||
import 'demandes_aide_event.dart';
|
||||
import 'demandes_aide_state.dart';
|
||||
|
||||
/// BLoC pour la gestion des demandes d'aide
|
||||
///
|
||||
/// Ce BLoC gère tous les états et événements liés aux demandes d'aide,
|
||||
/// incluant le chargement, la création, la modification, la validation,
|
||||
/// le filtrage, le tri et l'export des demandes.
|
||||
class DemandesAideBloc extends Bloc<DemandesAideEvent, DemandesAideState> {
|
||||
final CreerDemandeAideUseCase creerDemandeAideUseCase;
|
||||
final MettreAJourDemandeAideUseCase mettreAJourDemandeAideUseCase;
|
||||
final ObtenirDemandeAideUseCase obtenirDemandeAideUseCase;
|
||||
final SoumettreDemandeAideUseCase soumettreDemandeAideUseCase;
|
||||
final EvaluerDemandeAideUseCase evaluerDemandeAideUseCase;
|
||||
final RechercherDemandesAideUseCase rechercherDemandesAideUseCase;
|
||||
final ObtenirDemandesUrgentesUseCase obtenirDemandesUrgentesUseCase;
|
||||
final ObtenirMesDemandesUseCase obtenirMesDemandesUseCase;
|
||||
final ValiderDemandeAideUseCase validerDemandeAideUseCase;
|
||||
final CalculerPrioriteDemandeUseCase calculerPrioriteDemandeUseCase;
|
||||
|
||||
// Cache des paramètres de recherche pour la pagination
|
||||
String? _lastOrganisationId;
|
||||
TypeAide? _lastTypeAide;
|
||||
StatutAide? _lastStatut;
|
||||
String? _lastDemandeurId;
|
||||
bool? _lastUrgente;
|
||||
|
||||
DemandesAideBloc({
|
||||
required this.creerDemandeAideUseCase,
|
||||
required this.mettreAJourDemandeAideUseCase,
|
||||
required this.obtenirDemandeAideUseCase,
|
||||
required this.soumettreDemandeAideUseCase,
|
||||
required this.evaluerDemandeAideUseCase,
|
||||
required this.rechercherDemandesAideUseCase,
|
||||
required this.obtenirDemandesUrgentesUseCase,
|
||||
required this.obtenirMesDemandesUseCase,
|
||||
required this.validerDemandeAideUseCase,
|
||||
required this.calculerPrioriteDemandeUseCase,
|
||||
}) : super(const DemandesAideInitial()) {
|
||||
// Enregistrement des handlers d'événements
|
||||
on<ChargerDemandesAideEvent>(_onChargerDemandesAide);
|
||||
on<ChargerPlusDemandesAideEvent>(_onChargerPlusDemandesAide);
|
||||
on<CreerDemandeAideEvent>(_onCreerDemandeAide);
|
||||
on<MettreAJourDemandeAideEvent>(_onMettreAJourDemandeAide);
|
||||
on<ObtenirDemandeAideEvent>(_onObtenirDemandeAide);
|
||||
on<SoumettreDemandeAideEvent>(_onSoumettreDemandeAide);
|
||||
on<EvaluerDemandeAideEvent>(_onEvaluerDemandeAide);
|
||||
on<ChargerDemandesUrgentesEvent>(_onChargerDemandesUrgentes);
|
||||
on<ChargerMesDemandesEvent>(_onChargerMesdemandes);
|
||||
on<RechercherDemandesAideEvent>(_onRechercherDemandesAide);
|
||||
on<ValiderDemandeAideEvent>(_onValiderDemandeAide);
|
||||
on<CalculerPrioriteDemandeEvent>(_onCalculerPrioriteDemande);
|
||||
on<FiltrerDemandesAideEvent>(_onFiltrerDemandesAide);
|
||||
on<TrierDemandesAideEvent>(_onTrierDemandesAide);
|
||||
on<RafraichirDemandesAideEvent>(_onRafraichirDemandesAide);
|
||||
on<ReinitialiserDemandesAideEvent>(_onReinitialiserDemandesAide);
|
||||
on<SelectionnerDemandeAideEvent>(_onSelectionnerDemandeAide);
|
||||
on<SelectionnerToutesDemandesAideEvent>(_onSelectionnerToutesDemandesAide);
|
||||
on<SupprimerDemandesSelectionnees>(_onSupprimerDemandesSelectionnees);
|
||||
on<ExporterDemandesAideEvent>(_onExporterDemandesAide);
|
||||
}
|
||||
|
||||
/// Handler pour charger les demandes d'aide
|
||||
Future<void> _onChargerDemandesAide(
|
||||
ChargerDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
// Sauvegarder les paramètres pour la pagination
|
||||
_lastOrganisationId = event.organisationId;
|
||||
_lastTypeAide = event.typeAide;
|
||||
_lastStatut = event.statut;
|
||||
_lastDemandeurId = event.demandeurId;
|
||||
_lastUrgente = event.urgente;
|
||||
|
||||
if (event.forceRefresh || state is! DemandesAideLoaded) {
|
||||
emit(const DemandesAideLoading());
|
||||
} else if (state is DemandesAideLoaded) {
|
||||
emit((state as DemandesAideLoaded).copyWith(isRefreshing: true));
|
||||
}
|
||||
|
||||
final result = await rechercherDemandesAideUseCase(
|
||||
RechercherDemandesAideParams(
|
||||
organisationId: event.organisationId,
|
||||
typeAide: event.typeAide,
|
||||
statut: event.statut,
|
||||
demandeurId: event.demandeurId,
|
||||
urgente: event.urgente,
|
||||
page: 0,
|
||||
taille: 20,
|
||||
),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
cachedData: state is DemandesAideLoaded
|
||||
? (state as DemandesAideLoaded).demandes
|
||||
: null,
|
||||
)),
|
||||
(demandes) {
|
||||
final demandesFiltrees = _appliquerFiltres(demandes, const FiltresDemandesAide());
|
||||
emit(DemandesAideLoaded(
|
||||
demandes: demandes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
hasReachedMax: demandes.length < 20,
|
||||
currentPage: 0,
|
||||
totalElements: demandes.length,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour charger plus de demandes (pagination)
|
||||
Future<void> _onChargerPlusDemandesAide(
|
||||
ChargerPlusDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
if (currentState.hasReachedMax || currentState.isLoadingMore) return;
|
||||
|
||||
emit(currentState.copyWith(isLoadingMore: true));
|
||||
|
||||
final result = await rechercherDemandesAideUseCase(
|
||||
RechercherDemandesAideParams(
|
||||
organisationId: _lastOrganisationId,
|
||||
typeAide: _lastTypeAide,
|
||||
statut: _lastStatut,
|
||||
demandeurId: _lastDemandeurId,
|
||||
urgente: _lastUrgente,
|
||||
page: currentState.currentPage + 1,
|
||||
taille: 20,
|
||||
),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(currentState.copyWith(
|
||||
isLoadingMore: false,
|
||||
)),
|
||||
(nouvellesDemandes) {
|
||||
final toutesLesdemandes = [...currentState.demandes, ...nouvellesDemandes];
|
||||
final demandesFiltrees = _appliquerFiltres(toutesLesdemandes, currentState.filtres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: toutesLesdemandes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
hasReachedMax: nouvellesDemandes.length < 20,
|
||||
currentPage: currentState.currentPage + 1,
|
||||
totalElements: toutesLesdemandes.length,
|
||||
isLoadingMore: false,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour créer une demande d'aide
|
||||
Future<void> _onCreerDemandeAide(
|
||||
CreerDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await creerDemandeAideUseCase(
|
||||
CreerDemandeAideParams(demande: event.demande),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demande) {
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: TypeOperationDemande.creation.messageSucces,
|
||||
demande: demande,
|
||||
operation: TypeOperationDemande.creation,
|
||||
));
|
||||
|
||||
// Recharger la liste après création
|
||||
add(const ChargerDemandesAideEvent(forceRefresh: true));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour mettre à jour une demande d'aide
|
||||
Future<void> _onMettreAJourDemandeAide(
|
||||
MettreAJourDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await mettreAJourDemandeAideUseCase(
|
||||
MettreAJourDemandeAideParams(demande: event.demande),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demande) {
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: TypeOperationDemande.modification.messageSucces,
|
||||
demande: demande,
|
||||
operation: TypeOperationDemande.modification,
|
||||
));
|
||||
|
||||
// Mettre à jour la demande dans la liste si elle existe
|
||||
if (state is DemandesAideLoaded) {
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesUpdated = currentState.demandes.map((d) =>
|
||||
d.id == demande.id ? demande : d
|
||||
).toList();
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(demandesUpdated, currentState.filtres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: demandesUpdated,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour obtenir une demande d'aide spécifique
|
||||
Future<void> _onObtenirDemandeAide(
|
||||
ObtenirDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await obtenirDemandeAideUseCase(
|
||||
ObtenirDemandeAideParams(id: event.demandeId),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demande) {
|
||||
// Si on a déjà une liste chargée, mettre à jour la demande
|
||||
if (state is DemandesAideLoaded) {
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesUpdated = currentState.demandes.map((d) =>
|
||||
d.id == demande.id ? demande : d
|
||||
).toList();
|
||||
|
||||
// Ajouter la demande si elle n'existe pas
|
||||
if (!demandesUpdated.any((d) => d.id == demande.id)) {
|
||||
demandesUpdated.insert(0, demande);
|
||||
}
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(demandesUpdated, currentState.filtres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: demandesUpdated,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
} else {
|
||||
// Créer un nouvel état avec cette demande
|
||||
emit(DemandesAideLoaded(
|
||||
demandes: [demande],
|
||||
demandesFiltrees: [demande],
|
||||
hasReachedMax: true,
|
||||
currentPage: 0,
|
||||
totalElements: 1,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour soumettre une demande d'aide
|
||||
Future<void> _onSoumettreDemandeAide(
|
||||
SoumettreDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await soumettreDemandeAideUseCase(
|
||||
SoumettreDemandeAideParams(demandeId: event.demandeId),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demande) {
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: TypeOperationDemande.soumission.messageSucces,
|
||||
demande: demande,
|
||||
operation: TypeOperationDemande.soumission,
|
||||
));
|
||||
|
||||
// Mettre à jour la demande dans la liste
|
||||
if (state is DemandesAideLoaded) {
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesUpdated = currentState.demandes.map((d) =>
|
||||
d.id == demande.id ? demande : d
|
||||
).toList();
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(demandesUpdated, currentState.filtres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: demandesUpdated,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour évaluer une demande d'aide
|
||||
Future<void> _onEvaluerDemandeAide(
|
||||
EvaluerDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await evaluerDemandeAideUseCase(
|
||||
EvaluerDemandeAideParams(
|
||||
demandeId: event.demandeId,
|
||||
evaluateurId: event.evaluateurId,
|
||||
decision: event.decision,
|
||||
commentaire: event.commentaire,
|
||||
montantApprouve: event.montantApprouve,
|
||||
),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demande) {
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: TypeOperationDemande.evaluation.messageSucces,
|
||||
demande: demande,
|
||||
operation: TypeOperationDemande.evaluation,
|
||||
));
|
||||
|
||||
// Mettre à jour la demande dans la liste
|
||||
if (state is DemandesAideLoaded) {
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesUpdated = currentState.demandes.map((d) =>
|
||||
d.id == demande.id ? demande : d
|
||||
).toList();
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(demandesUpdated, currentState.filtres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: demandesUpdated,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour charger les demandes urgentes
|
||||
Future<void> _onChargerDemandesUrgentes(
|
||||
ChargerDemandesUrgentesEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await obtenirDemandesUrgentesUseCase(
|
||||
ObtenirDemandesUrgentesParams(organisationId: event.organisationId),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demandes) {
|
||||
final demandesFiltrees = _appliquerFiltres(demandes, const FiltresDemandesAide());
|
||||
emit(DemandesAideLoaded(
|
||||
demandes: demandes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
hasReachedMax: true,
|
||||
currentPage: 0,
|
||||
totalElements: demandes.length,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour charger mes demandes
|
||||
Future<void> _onChargerMesdemandes(
|
||||
ChargerMesDemandesEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await obtenirMesDemandesUseCase(
|
||||
ObtenirMesDemandesParams(utilisateurId: event.utilisateurId),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demandes) {
|
||||
final demandesFiltrees = _appliquerFiltres(demandes, const FiltresDemandesAide());
|
||||
emit(DemandesAideLoaded(
|
||||
demandes: demandes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
hasReachedMax: true,
|
||||
currentPage: 0,
|
||||
totalElements: demandes.length,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour rechercher des demandes d'aide
|
||||
Future<void> _onRechercherDemandesAide(
|
||||
RechercherDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
final result = await rechercherDemandesAideUseCase(
|
||||
RechercherDemandesAideParams(
|
||||
organisationId: event.organisationId,
|
||||
typeAide: event.typeAide,
|
||||
statut: event.statut,
|
||||
demandeurId: event.demandeurId,
|
||||
urgente: event.urgente,
|
||||
page: event.page,
|
||||
taille: event.taille,
|
||||
),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
isNetworkError: failure is NetworkFailure,
|
||||
canRetry: true,
|
||||
)),
|
||||
(demandes) {
|
||||
// Appliquer le filtre par mot-clé localement
|
||||
var demandesFiltrees = demandes;
|
||||
if (event.motCle != null && event.motCle!.isNotEmpty) {
|
||||
demandesFiltrees = demandes.where((demande) =>
|
||||
demande.titre.toLowerCase().contains(event.motCle!.toLowerCase()) ||
|
||||
demande.description.toLowerCase().contains(event.motCle!.toLowerCase()) ||
|
||||
demande.nomDemandeur.toLowerCase().contains(event.motCle!.toLowerCase())
|
||||
).toList();
|
||||
}
|
||||
|
||||
emit(DemandesAideLoaded(
|
||||
demandes: demandes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
hasReachedMax: demandes.length < event.taille,
|
||||
currentPage: event.page,
|
||||
totalElements: demandes.length,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Méthode utilitaire pour appliquer les filtres
|
||||
List<DemandeAide> _appliquerFiltres(List<DemandeAide> demandes, FiltresDemandesAide filtres) {
|
||||
var demandesFiltrees = demandes;
|
||||
|
||||
if (filtres.typeAide != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) => d.typeAide == filtres.typeAide).toList();
|
||||
}
|
||||
|
||||
if (filtres.statut != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) => d.statut == filtres.statut).toList();
|
||||
}
|
||||
|
||||
if (filtres.priorite != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) => d.priorite == filtres.priorite).toList();
|
||||
}
|
||||
|
||||
if (filtres.urgente != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) => d.estUrgente == filtres.urgente).toList();
|
||||
}
|
||||
|
||||
if (filtres.motCle != null && filtres.motCle!.isNotEmpty) {
|
||||
final motCle = filtres.motCle!.toLowerCase();
|
||||
demandesFiltrees = demandesFiltrees.where((d) =>
|
||||
d.titre.toLowerCase().contains(motCle) ||
|
||||
d.description.toLowerCase().contains(motCle) ||
|
||||
d.nomDemandeur.toLowerCase().contains(motCle)
|
||||
).toList();
|
||||
}
|
||||
|
||||
if (filtres.montantMin != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) =>
|
||||
d.montantDemande != null && d.montantDemande! >= filtres.montantMin!
|
||||
).toList();
|
||||
}
|
||||
|
||||
if (filtres.montantMax != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) =>
|
||||
d.montantDemande != null && d.montantDemande! <= filtres.montantMax!
|
||||
).toList();
|
||||
}
|
||||
|
||||
if (filtres.dateDebutCreation != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) =>
|
||||
d.dateCreation.isAfter(filtres.dateDebutCreation!) ||
|
||||
d.dateCreation.isAtSameMomentAs(filtres.dateDebutCreation!)
|
||||
).toList();
|
||||
}
|
||||
|
||||
if (filtres.dateFinCreation != null) {
|
||||
demandesFiltrees = demandesFiltrees.where((d) =>
|
||||
d.dateCreation.isBefore(filtres.dateFinCreation!) ||
|
||||
d.dateCreation.isAtSameMomentAs(filtres.dateFinCreation!)
|
||||
).toList();
|
||||
}
|
||||
|
||||
return demandesFiltrees;
|
||||
}
|
||||
|
||||
/// Handler pour valider une demande d'aide
|
||||
Future<void> _onValiderDemandeAide(
|
||||
ValiderDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
final result = await validerDemandeAideUseCase(
|
||||
ValiderDemandeAideParams(demande: event.demande),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideValidation(
|
||||
erreurs: {'general': _mapFailureToMessage(failure)},
|
||||
isValid: false,
|
||||
demande: event.demande,
|
||||
)),
|
||||
(isValid) => emit(DemandesAideValidation(
|
||||
erreurs: const {},
|
||||
isValid: isValid,
|
||||
demande: event.demande,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour calculer la priorité d'une demande
|
||||
Future<void> _onCalculerPrioriteDemande(
|
||||
CalculerPrioriteDemandeEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
final result = await calculerPrioriteDemandeUseCase(
|
||||
CalculerPrioriteDemandeParams(demande: event.demande),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(failure) => emit(DemandesAideError(
|
||||
message: _mapFailureToMessage(failure),
|
||||
canRetry: false,
|
||||
)),
|
||||
(priorite) {
|
||||
final demandeUpdated = event.demande.copyWith(priorite: priorite);
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: 'Priorité calculée: ${priorite.libelle}',
|
||||
demande: demandeUpdated,
|
||||
operation: TypeOperationDemande.modification,
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handler pour filtrer les demandes localement
|
||||
Future<void> _onFiltrerDemandesAide(
|
||||
FiltrerDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final nouveauxFiltres = FiltresDemandesAide(
|
||||
typeAide: event.typeAide,
|
||||
statut: event.statut,
|
||||
priorite: event.priorite,
|
||||
urgente: event.urgente,
|
||||
motCle: event.motCle,
|
||||
);
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(currentState.demandes, nouveauxFiltres);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
filtres: nouveauxFiltres,
|
||||
));
|
||||
}
|
||||
|
||||
/// Handler pour trier les demandes
|
||||
Future<void> _onTrierDemandesAide(
|
||||
TrierDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesTriees = List<DemandeAide>.from(currentState.demandesFiltrees);
|
||||
|
||||
// Appliquer le tri
|
||||
demandesTriees.sort((a, b) {
|
||||
int comparison = 0;
|
||||
|
||||
switch (event.critere) {
|
||||
case TriDemandes.dateCreation:
|
||||
comparison = a.dateCreation.compareTo(b.dateCreation);
|
||||
break;
|
||||
case TriDemandes.dateModification:
|
||||
comparison = a.dateModification.compareTo(b.dateModification);
|
||||
break;
|
||||
case TriDemandes.titre:
|
||||
comparison = a.titre.compareTo(b.titre);
|
||||
break;
|
||||
case TriDemandes.statut:
|
||||
comparison = a.statut.index.compareTo(b.statut.index);
|
||||
break;
|
||||
case TriDemandes.priorite:
|
||||
comparison = a.priorite.index.compareTo(b.priorite.index);
|
||||
break;
|
||||
case TriDemandes.montant:
|
||||
final montantA = a.montantDemande ?? 0.0;
|
||||
final montantB = b.montantDemande ?? 0.0;
|
||||
comparison = montantA.compareTo(montantB);
|
||||
break;
|
||||
case TriDemandes.demandeur:
|
||||
comparison = a.nomDemandeur.compareTo(b.nomDemandeur);
|
||||
break;
|
||||
}
|
||||
|
||||
return event.croissant ? comparison : -comparison;
|
||||
});
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandesFiltrees: demandesTriees,
|
||||
criterieTri: event.critere,
|
||||
triCroissant: event.croissant,
|
||||
));
|
||||
}
|
||||
|
||||
/// Handler pour rafraîchir les demandes
|
||||
Future<void> _onRafraichirDemandesAide(
|
||||
RafraichirDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
add(ChargerDemandesAideEvent(
|
||||
organisationId: _lastOrganisationId,
|
||||
typeAide: _lastTypeAide,
|
||||
statut: _lastStatut,
|
||||
demandeurId: _lastDemandeurId,
|
||||
urgente: _lastUrgente,
|
||||
forceRefresh: true,
|
||||
));
|
||||
}
|
||||
|
||||
/// Handler pour réinitialiser l'état
|
||||
Future<void> _onReinitialiserDemandesAide(
|
||||
ReinitialiserDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
_lastOrganisationId = null;
|
||||
_lastTypeAide = null;
|
||||
_lastStatut = null;
|
||||
_lastDemandeurId = null;
|
||||
_lastUrgente = null;
|
||||
|
||||
emit(const DemandesAideInitial());
|
||||
}
|
||||
|
||||
/// Handler pour sélectionner/désélectionner une demande
|
||||
Future<void> _onSelectionnerDemandeAide(
|
||||
SelectionnerDemandeAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final nouvellesSelections = Map<String, bool>.from(currentState.demandesSelectionnees);
|
||||
|
||||
if (event.selectionne) {
|
||||
nouvellesSelections[event.demandeId] = true;
|
||||
} else {
|
||||
nouvellesSelections.remove(event.demandeId);
|
||||
}
|
||||
|
||||
emit(currentState.copyWith(demandesSelectionnees: nouvellesSelections));
|
||||
}
|
||||
|
||||
/// Handler pour sélectionner/désélectionner toutes les demandes
|
||||
Future<void> _onSelectionnerToutesDemandesAide(
|
||||
SelectionnerToutesDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final nouvellesSelections = <String, bool>{};
|
||||
|
||||
if (event.selectionne) {
|
||||
for (final demande in currentState.demandesFiltrees) {
|
||||
nouvellesSelections[demande.id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
emit(currentState.copyWith(demandesSelectionnees: nouvellesSelections));
|
||||
}
|
||||
|
||||
/// Handler pour supprimer les demandes sélectionnées
|
||||
Future<void> _onSupprimerDemandesSelectionnees(
|
||||
SupprimerDemandesSelectionnees event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
emit(const DemandesAideLoading());
|
||||
|
||||
// Simuler la suppression (à implémenter avec un vrai use case)
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
final currentState = state as DemandesAideLoaded;
|
||||
final demandesRestantes = currentState.demandes
|
||||
.where((demande) => !event.demandeIds.contains(demande.id))
|
||||
.toList();
|
||||
|
||||
final demandesFiltrees = _appliquerFiltres(demandesRestantes, currentState.filtres);
|
||||
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: '${event.demandeIds.length} demande(s) supprimée(s) avec succès',
|
||||
operation: TypeOperationDemande.suppression,
|
||||
));
|
||||
|
||||
emit(currentState.copyWith(
|
||||
demandes: demandesRestantes,
|
||||
demandesFiltrees: demandesFiltrees,
|
||||
demandesSelectionnees: const {},
|
||||
totalElements: demandesRestantes.length,
|
||||
lastUpdated: DateTime.now(),
|
||||
));
|
||||
}
|
||||
|
||||
/// Handler pour exporter les demandes
|
||||
Future<void> _onExporterDemandesAide(
|
||||
ExporterDemandesAideEvent event,
|
||||
Emitter<DemandesAideState> emit,
|
||||
) async {
|
||||
if (state is! DemandesAideLoaded) return;
|
||||
|
||||
emit(const DemandesAideExporting(progress: 0.0, currentStep: 'Préparation...'));
|
||||
|
||||
// Simuler l'export avec progression
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
emit(DemandesAideExporting(
|
||||
progress: i / 5,
|
||||
currentStep: _getExportStep(i, event.format),
|
||||
));
|
||||
}
|
||||
|
||||
// Simuler la génération du fichier
|
||||
final fileName = 'demandes_aide_${DateTime.now().millisecondsSinceEpoch}${event.format.extension}';
|
||||
final filePath = '/storage/emulated/0/Download/$fileName';
|
||||
|
||||
emit(DemandesAideExported(
|
||||
filePath: filePath,
|
||||
format: event.format,
|
||||
nombreDemandes: event.demandeIds.length,
|
||||
));
|
||||
|
||||
emit(DemandesAideOperationSuccess(
|
||||
message: 'Export réalisé avec succès: $fileName',
|
||||
operation: TypeOperationDemande.export,
|
||||
));
|
||||
}
|
||||
|
||||
/// Méthode utilitaire pour obtenir l'étape d'export
|
||||
String _getExportStep(int step, FormatExport format) {
|
||||
switch (step) {
|
||||
case 1:
|
||||
return 'Récupération des données...';
|
||||
case 2:
|
||||
return 'Formatage des données...';
|
||||
case 3:
|
||||
return 'Génération du fichier ${format.libelle}...';
|
||||
case 4:
|
||||
return 'Optimisation...';
|
||||
case 5:
|
||||
return 'Finalisation...';
|
||||
default:
|
||||
return 'Traitement...';
|
||||
}
|
||||
}
|
||||
|
||||
/// Méthode utilitaire pour mapper les erreurs
|
||||
String _mapFailureToMessage(Failure failure) {
|
||||
switch (failure.runtimeType) {
|
||||
case ServerFailure:
|
||||
return 'Erreur serveur. Veuillez réessayer plus tard.';
|
||||
case NetworkFailure:
|
||||
return 'Pas de connexion internet. Vérifiez votre connexion.';
|
||||
case CacheFailure:
|
||||
return 'Erreur de cache local.';
|
||||
case ValidationFailure:
|
||||
return failure.message;
|
||||
case NotFoundFailure:
|
||||
return 'Demande d\'aide non trouvée.';
|
||||
default:
|
||||
return 'Une erreur inattendue s\'est produite.';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/demande_aide.dart';
|
||||
|
||||
/// Événements pour la gestion des demandes d'aide
|
||||
///
|
||||
/// Ces événements représentent toutes les actions possibles
|
||||
/// que l'utilisateur peut effectuer sur les demandes d'aide.
|
||||
abstract class DemandesAideEvent extends Equatable {
|
||||
const DemandesAideEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Événement pour charger les demandes d'aide
|
||||
class ChargerDemandesAideEvent extends DemandesAideEvent {
|
||||
final String? organisationId;
|
||||
final TypeAide? typeAide;
|
||||
final StatutAide? statut;
|
||||
final String? demandeurId;
|
||||
final bool? urgente;
|
||||
final bool forceRefresh;
|
||||
|
||||
const ChargerDemandesAideEvent({
|
||||
this.organisationId,
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.demandeurId,
|
||||
this.urgente,
|
||||
this.forceRefresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
organisationId,
|
||||
typeAide,
|
||||
statut,
|
||||
demandeurId,
|
||||
urgente,
|
||||
forceRefresh,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger plus de demandes (pagination)
|
||||
class ChargerPlusDemandesAideEvent extends DemandesAideEvent {
|
||||
const ChargerPlusDemandesAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour créer une nouvelle demande d'aide
|
||||
class CreerDemandeAideEvent extends DemandesAideEvent {
|
||||
final DemandeAide demande;
|
||||
|
||||
const CreerDemandeAideEvent({required this.demande});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demande];
|
||||
}
|
||||
|
||||
/// Événement pour mettre à jour une demande d'aide
|
||||
class MettreAJourDemandeAideEvent extends DemandesAideEvent {
|
||||
final DemandeAide demande;
|
||||
|
||||
const MettreAJourDemandeAideEvent({required this.demande});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demande];
|
||||
}
|
||||
|
||||
/// Événement pour obtenir une demande d'aide spécifique
|
||||
class ObtenirDemandeAideEvent extends DemandesAideEvent {
|
||||
final String demandeId;
|
||||
|
||||
const ObtenirDemandeAideEvent({required this.demandeId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demandeId];
|
||||
}
|
||||
|
||||
/// Événement pour soumettre une demande d'aide
|
||||
class SoumettreDemandeAideEvent extends DemandesAideEvent {
|
||||
final String demandeId;
|
||||
|
||||
const SoumettreDemandeAideEvent({required this.demandeId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demandeId];
|
||||
}
|
||||
|
||||
/// Événement pour évaluer une demande d'aide
|
||||
class EvaluerDemandeAideEvent extends DemandesAideEvent {
|
||||
final String demandeId;
|
||||
final String evaluateurId;
|
||||
final StatutAide decision;
|
||||
final String? commentaire;
|
||||
final double? montantApprouve;
|
||||
|
||||
const EvaluerDemandeAideEvent({
|
||||
required this.demandeId,
|
||||
required this.evaluateurId,
|
||||
required this.decision,
|
||||
this.commentaire,
|
||||
this.montantApprouve,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
demandeId,
|
||||
evaluateurId,
|
||||
decision,
|
||||
commentaire,
|
||||
montantApprouve,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger les demandes urgentes
|
||||
class ChargerDemandesUrgentesEvent extends DemandesAideEvent {
|
||||
final String organisationId;
|
||||
|
||||
const ChargerDemandesUrgentesEvent({required this.organisationId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [organisationId];
|
||||
}
|
||||
|
||||
/// Événement pour charger mes demandes
|
||||
class ChargerMesDemandesEvent extends DemandesAideEvent {
|
||||
final String utilisateurId;
|
||||
|
||||
const ChargerMesDemandesEvent({required this.utilisateurId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [utilisateurId];
|
||||
}
|
||||
|
||||
/// Événement pour rechercher des demandes d'aide
|
||||
class RechercherDemandesAideEvent extends DemandesAideEvent {
|
||||
final String? organisationId;
|
||||
final TypeAide? typeAide;
|
||||
final StatutAide? statut;
|
||||
final String? demandeurId;
|
||||
final bool? urgente;
|
||||
final String? motCle;
|
||||
final int page;
|
||||
final int taille;
|
||||
|
||||
const RechercherDemandesAideEvent({
|
||||
this.organisationId,
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.demandeurId,
|
||||
this.urgente,
|
||||
this.motCle,
|
||||
this.page = 0,
|
||||
this.taille = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
organisationId,
|
||||
typeAide,
|
||||
statut,
|
||||
demandeurId,
|
||||
urgente,
|
||||
motCle,
|
||||
page,
|
||||
taille,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour valider une demande d'aide
|
||||
class ValiderDemandeAideEvent extends DemandesAideEvent {
|
||||
final DemandeAide demande;
|
||||
|
||||
const ValiderDemandeAideEvent({required this.demande});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demande];
|
||||
}
|
||||
|
||||
/// Événement pour calculer la priorité d'une demande
|
||||
class CalculerPrioriteDemandeEvent extends DemandesAideEvent {
|
||||
final DemandeAide demande;
|
||||
|
||||
const CalculerPrioriteDemandeEvent({required this.demande});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demande];
|
||||
}
|
||||
|
||||
/// Événement pour filtrer les demandes localement
|
||||
class FiltrerDemandesAideEvent extends DemandesAideEvent {
|
||||
final TypeAide? typeAide;
|
||||
final StatutAide? statut;
|
||||
final PrioriteAide? priorite;
|
||||
final bool? urgente;
|
||||
final String? motCle;
|
||||
|
||||
const FiltrerDemandesAideEvent({
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.priorite,
|
||||
this.urgente,
|
||||
this.motCle,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeAide,
|
||||
statut,
|
||||
priorite,
|
||||
urgente,
|
||||
motCle,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour trier les demandes
|
||||
class TrierDemandesAideEvent extends DemandesAideEvent {
|
||||
final TriDemandes critere;
|
||||
final bool croissant;
|
||||
|
||||
const TrierDemandesAideEvent({
|
||||
required this.critere,
|
||||
this.croissant = true,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [critere, croissant];
|
||||
}
|
||||
|
||||
/// Événement pour rafraîchir les demandes
|
||||
class RafraichirDemandesAideEvent extends DemandesAideEvent {
|
||||
const RafraichirDemandesAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour réinitialiser l'état
|
||||
class ReinitialiserDemandesAideEvent extends DemandesAideEvent {
|
||||
const ReinitialiserDemandesAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner une demande
|
||||
class SelectionnerDemandeAideEvent extends DemandesAideEvent {
|
||||
final String demandeId;
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerDemandeAideEvent({
|
||||
required this.demandeId,
|
||||
required this.selectionne,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demandeId, selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner toutes les demandes
|
||||
class SelectionnerToutesDemandesAideEvent extends DemandesAideEvent {
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerToutesDemandesAideEvent({required this.selectionne});
|
||||
|
||||
@override
|
||||
List<Object> get props => [selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour supprimer des demandes sélectionnées
|
||||
class SupprimerDemandesSelectionnees extends DemandesAideEvent {
|
||||
final List<String> demandeIds;
|
||||
|
||||
const SupprimerDemandesSelectionnees({required this.demandeIds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demandeIds];
|
||||
}
|
||||
|
||||
/// Événement pour exporter des demandes
|
||||
class ExporterDemandesAideEvent extends DemandesAideEvent {
|
||||
final List<String> demandeIds;
|
||||
final FormatExport format;
|
||||
|
||||
const ExporterDemandesAideEvent({
|
||||
required this.demandeIds,
|
||||
required this.format,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [demandeIds, format];
|
||||
}
|
||||
|
||||
/// Énumération pour les critères de tri
|
||||
enum TriDemandes {
|
||||
dateCreation,
|
||||
dateModification,
|
||||
titre,
|
||||
statut,
|
||||
priorite,
|
||||
montant,
|
||||
demandeur,
|
||||
}
|
||||
|
||||
/// Énumération pour les formats d'export
|
||||
enum FormatExport {
|
||||
pdf,
|
||||
excel,
|
||||
csv,
|
||||
json,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des critères de tri
|
||||
extension TriDemandesExtension on TriDemandes {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TriDemandes.dateCreation:
|
||||
return 'Date de création';
|
||||
case TriDemandes.dateModification:
|
||||
return 'Date de modification';
|
||||
case TriDemandes.titre:
|
||||
return 'Titre';
|
||||
case TriDemandes.statut:
|
||||
return 'Statut';
|
||||
case TriDemandes.priorite:
|
||||
return 'Priorité';
|
||||
case TriDemandes.montant:
|
||||
return 'Montant';
|
||||
case TriDemandes.demandeur:
|
||||
return 'Demandeur';
|
||||
}
|
||||
}
|
||||
|
||||
String get icone {
|
||||
switch (this) {
|
||||
case TriDemandes.dateCreation:
|
||||
return 'calendar_today';
|
||||
case TriDemandes.dateModification:
|
||||
return 'update';
|
||||
case TriDemandes.titre:
|
||||
return 'title';
|
||||
case TriDemandes.statut:
|
||||
return 'flag';
|
||||
case TriDemandes.priorite:
|
||||
return 'priority_high';
|
||||
case TriDemandes.montant:
|
||||
return 'attach_money';
|
||||
case TriDemandes.demandeur:
|
||||
return 'person';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des formats d'export
|
||||
extension FormatExportExtension on FormatExport {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'PDF';
|
||||
case FormatExport.excel:
|
||||
return 'Excel';
|
||||
case FormatExport.csv:
|
||||
return 'CSV';
|
||||
case FormatExport.json:
|
||||
return 'JSON';
|
||||
}
|
||||
}
|
||||
|
||||
String get extension {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return '.pdf';
|
||||
case FormatExport.excel:
|
||||
return '.xlsx';
|
||||
case FormatExport.csv:
|
||||
return '.csv';
|
||||
case FormatExport.json:
|
||||
return '.json';
|
||||
}
|
||||
}
|
||||
|
||||
String get mimeType {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'application/pdf';
|
||||
case FormatExport.excel:
|
||||
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
case FormatExport.csv:
|
||||
return 'text/csv';
|
||||
case FormatExport.json:
|
||||
return 'application/json';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/demande_aide.dart';
|
||||
import 'demandes_aide_event.dart';
|
||||
|
||||
/// États pour la gestion des demandes d'aide
|
||||
///
|
||||
/// Ces états représentent tous les états possibles
|
||||
/// de l'interface utilisateur pour les demandes d'aide.
|
||||
abstract class DemandesAideState extends Equatable {
|
||||
const DemandesAideState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class DemandesAideInitial extends DemandesAideState {
|
||||
const DemandesAideInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class DemandesAideLoading extends DemandesAideState {
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
|
||||
const DemandesAideLoading({
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [isRefreshing, isLoadingMore];
|
||||
}
|
||||
|
||||
/// État de succès avec données chargées
|
||||
class DemandesAideLoaded extends DemandesAideState {
|
||||
final List<DemandeAide> demandes;
|
||||
final List<DemandeAide> demandesFiltrees;
|
||||
final bool hasReachedMax;
|
||||
final int currentPage;
|
||||
final int totalElements;
|
||||
final Map<String, bool> demandesSelectionnees;
|
||||
final TriDemandes? criterieTri;
|
||||
final bool triCroissant;
|
||||
final FiltresDemandesAide filtres;
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
final DateTime lastUpdated;
|
||||
|
||||
const DemandesAideLoaded({
|
||||
required this.demandes,
|
||||
required this.demandesFiltrees,
|
||||
this.hasReachedMax = false,
|
||||
this.currentPage = 0,
|
||||
this.totalElements = 0,
|
||||
this.demandesSelectionnees = const {},
|
||||
this.criterieTri,
|
||||
this.triCroissant = true,
|
||||
this.filtres = const FiltresDemandesAide(),
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
required this.lastUpdated,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
demandes,
|
||||
demandesFiltrees,
|
||||
hasReachedMax,
|
||||
currentPage,
|
||||
totalElements,
|
||||
demandesSelectionnees,
|
||||
criterieTri,
|
||||
triCroissant,
|
||||
filtres,
|
||||
isRefreshing,
|
||||
isLoadingMore,
|
||||
lastUpdated,
|
||||
];
|
||||
|
||||
/// Copie l'état avec de nouvelles valeurs
|
||||
DemandesAideLoaded copyWith({
|
||||
List<DemandeAide>? demandes,
|
||||
List<DemandeAide>? demandesFiltrees,
|
||||
bool? hasReachedMax,
|
||||
int? currentPage,
|
||||
int? totalElements,
|
||||
Map<String, bool>? demandesSelectionnees,
|
||||
TriDemandes? criterieTri,
|
||||
bool? triCroissant,
|
||||
FiltresDemandesAide? filtres,
|
||||
bool? isRefreshing,
|
||||
bool? isLoadingMore,
|
||||
DateTime? lastUpdated,
|
||||
}) {
|
||||
return DemandesAideLoaded(
|
||||
demandes: demandes ?? this.demandes,
|
||||
demandesFiltrees: demandesFiltrees ?? this.demandesFiltrees,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
totalElements: totalElements ?? this.totalElements,
|
||||
demandesSelectionnees: demandesSelectionnees ?? this.demandesSelectionnees,
|
||||
criterieTri: criterieTri ?? this.criterieTri,
|
||||
triCroissant: triCroissant ?? this.triCroissant,
|
||||
filtres: filtres ?? this.filtres,
|
||||
isRefreshing: isRefreshing ?? this.isRefreshing,
|
||||
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||
lastUpdated: lastUpdated ?? this.lastUpdated,
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient le nombre de demandes sélectionnées
|
||||
int get nombreDemandesSelectionnees {
|
||||
return demandesSelectionnees.values.where((selected) => selected).length;
|
||||
}
|
||||
|
||||
/// Vérifie si toutes les demandes sont sélectionnées
|
||||
bool get toutesDemandesSelectionnees {
|
||||
if (demandesFiltrees.isEmpty) return false;
|
||||
return demandesFiltrees.every((demande) =>
|
||||
demandesSelectionnees[demande.id] == true
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient les IDs des demandes sélectionnées
|
||||
List<String> get demandesSelectionneesIds {
|
||||
return demandesSelectionnees.entries
|
||||
.where((entry) => entry.value)
|
||||
.map((entry) => entry.key)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// Obtient les demandes sélectionnées
|
||||
List<DemandeAide> get demandesSelectionneesEntities {
|
||||
return demandes.where((demande) =>
|
||||
demandesSelectionnees[demande.id] == true
|
||||
).toList();
|
||||
}
|
||||
|
||||
/// Vérifie si des données sont disponibles
|
||||
bool get hasData => demandes.isNotEmpty;
|
||||
|
||||
/// Vérifie si des filtres sont appliqués
|
||||
bool get hasFiltres => !filtres.isEmpty;
|
||||
|
||||
/// Obtient le texte de statut
|
||||
String get statusText {
|
||||
if (isRefreshing) return 'Actualisation...';
|
||||
if (isLoadingMore) return 'Chargement...';
|
||||
if (demandesFiltrees.isEmpty && hasData) return 'Aucun résultat pour les filtres appliqués';
|
||||
if (demandesFiltrees.isEmpty) return 'Aucune demande d\'aide';
|
||||
return '${demandesFiltrees.length} demande${demandesFiltrees.length > 1 ? 's' : ''}';
|
||||
}
|
||||
}
|
||||
|
||||
/// État d'erreur
|
||||
class DemandesAideError extends DemandesAideState {
|
||||
final String message;
|
||||
final String? code;
|
||||
final bool isNetworkError;
|
||||
final bool canRetry;
|
||||
final List<DemandeAide>? cachedData;
|
||||
|
||||
const DemandesAideError({
|
||||
required this.message,
|
||||
this.code,
|
||||
this.isNetworkError = false,
|
||||
this.canRetry = true,
|
||||
this.cachedData,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
message,
|
||||
code,
|
||||
isNetworkError,
|
||||
canRetry,
|
||||
cachedData,
|
||||
];
|
||||
|
||||
/// Vérifie si des données en cache sont disponibles
|
||||
bool get hasCachedData => cachedData != null && cachedData!.isNotEmpty;
|
||||
}
|
||||
|
||||
/// État de succès pour une opération spécifique
|
||||
class DemandesAideOperationSuccess extends DemandesAideState {
|
||||
final String message;
|
||||
final DemandeAide? demande;
|
||||
final TypeOperationDemande operation;
|
||||
|
||||
const DemandesAideOperationSuccess({
|
||||
required this.message,
|
||||
this.demande,
|
||||
required this.operation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, demande, operation];
|
||||
}
|
||||
|
||||
/// État de validation
|
||||
class DemandesAideValidation extends DemandesAideState {
|
||||
final Map<String, String> erreurs;
|
||||
final bool isValid;
|
||||
final DemandeAide? demande;
|
||||
|
||||
const DemandesAideValidation({
|
||||
required this.erreurs,
|
||||
required this.isValid,
|
||||
this.demande,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [erreurs, isValid, demande];
|
||||
|
||||
/// Obtient la première erreur
|
||||
String? get premiereErreur {
|
||||
return erreurs.values.isNotEmpty ? erreurs.values.first : null;
|
||||
}
|
||||
|
||||
/// Obtient les erreurs pour un champ spécifique
|
||||
String? getErreurPourChamp(String champ) {
|
||||
return erreurs[champ];
|
||||
}
|
||||
}
|
||||
|
||||
/// État d'export
|
||||
class DemandesAideExporting extends DemandesAideState {
|
||||
final double progress;
|
||||
final String? currentStep;
|
||||
|
||||
const DemandesAideExporting({
|
||||
required this.progress,
|
||||
this.currentStep,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [progress, currentStep];
|
||||
}
|
||||
|
||||
/// État d'export terminé
|
||||
class DemandesAideExported extends DemandesAideState {
|
||||
final String filePath;
|
||||
final FormatExport format;
|
||||
final int nombreDemandes;
|
||||
|
||||
const DemandesAideExported({
|
||||
required this.filePath,
|
||||
required this.format,
|
||||
required this.nombreDemandes,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [filePath, format, nombreDemandes];
|
||||
}
|
||||
|
||||
/// Classe pour les filtres des demandes d'aide
|
||||
class FiltresDemandesAide extends Equatable {
|
||||
final TypeAide? typeAide;
|
||||
final StatutAide? statut;
|
||||
final PrioriteAide? priorite;
|
||||
final bool? urgente;
|
||||
final String? motCle;
|
||||
final String? organisationId;
|
||||
final String? demandeurId;
|
||||
final DateTime? dateDebutCreation;
|
||||
final DateTime? dateFinCreation;
|
||||
final double? montantMin;
|
||||
final double? montantMax;
|
||||
|
||||
const FiltresDemandesAide({
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.priorite,
|
||||
this.urgente,
|
||||
this.motCle,
|
||||
this.organisationId,
|
||||
this.demandeurId,
|
||||
this.dateDebutCreation,
|
||||
this.dateFinCreation,
|
||||
this.montantMin,
|
||||
this.montantMax,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeAide,
|
||||
statut,
|
||||
priorite,
|
||||
urgente,
|
||||
motCle,
|
||||
organisationId,
|
||||
demandeurId,
|
||||
dateDebutCreation,
|
||||
dateFinCreation,
|
||||
montantMin,
|
||||
montantMax,
|
||||
];
|
||||
|
||||
/// Copie les filtres avec de nouvelles valeurs
|
||||
FiltresDemandesAide copyWith({
|
||||
TypeAide? typeAide,
|
||||
StatutAide? statut,
|
||||
PrioriteAide? priorite,
|
||||
bool? urgente,
|
||||
String? motCle,
|
||||
String? organisationId,
|
||||
String? demandeurId,
|
||||
DateTime? dateDebutCreation,
|
||||
DateTime? dateFinCreation,
|
||||
double? montantMin,
|
||||
double? montantMax,
|
||||
}) {
|
||||
return FiltresDemandesAide(
|
||||
typeAide: typeAide ?? this.typeAide,
|
||||
statut: statut ?? this.statut,
|
||||
priorite: priorite ?? this.priorite,
|
||||
urgente: urgente ?? this.urgente,
|
||||
motCle: motCle ?? this.motCle,
|
||||
organisationId: organisationId ?? this.organisationId,
|
||||
demandeurId: demandeurId ?? this.demandeurId,
|
||||
dateDebutCreation: dateDebutCreation ?? this.dateDebutCreation,
|
||||
dateFinCreation: dateFinCreation ?? this.dateFinCreation,
|
||||
montantMin: montantMin ?? this.montantMin,
|
||||
montantMax: montantMax ?? this.montantMax,
|
||||
);
|
||||
}
|
||||
|
||||
/// Réinitialise tous les filtres
|
||||
FiltresDemandesAide clear() {
|
||||
return const FiltresDemandesAide();
|
||||
}
|
||||
|
||||
/// Vérifie si les filtres sont vides
|
||||
bool get isEmpty {
|
||||
return typeAide == null &&
|
||||
statut == null &&
|
||||
priorite == null &&
|
||||
urgente == null &&
|
||||
(motCle == null || motCle!.isEmpty) &&
|
||||
organisationId == null &&
|
||||
demandeurId == null &&
|
||||
dateDebutCreation == null &&
|
||||
dateFinCreation == null &&
|
||||
montantMin == null &&
|
||||
montantMax == null;
|
||||
}
|
||||
|
||||
/// Obtient le nombre de filtres actifs
|
||||
int get nombreFiltresActifs {
|
||||
int count = 0;
|
||||
if (typeAide != null) count++;
|
||||
if (statut != null) count++;
|
||||
if (priorite != null) count++;
|
||||
if (urgente != null) count++;
|
||||
if (motCle != null && motCle!.isNotEmpty) count++;
|
||||
if (organisationId != null) count++;
|
||||
if (demandeurId != null) count++;
|
||||
if (dateDebutCreation != null) count++;
|
||||
if (dateFinCreation != null) count++;
|
||||
if (montantMin != null) count++;
|
||||
if (montantMax != null) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Obtient une description textuelle des filtres
|
||||
String get description {
|
||||
final parts = <String>[];
|
||||
|
||||
if (typeAide != null) parts.add('Type: ${typeAide!.libelle}');
|
||||
if (statut != null) parts.add('Statut: ${statut!.libelle}');
|
||||
if (priorite != null) parts.add('Priorité: ${priorite!.libelle}');
|
||||
if (urgente == true) parts.add('Urgente uniquement');
|
||||
if (motCle != null && motCle!.isNotEmpty) parts.add('Recherche: "$motCle"');
|
||||
if (montantMin != null || montantMax != null) {
|
||||
if (montantMin != null && montantMax != null) {
|
||||
parts.add('Montant: ${montantMin!.toInt()} - ${montantMax!.toInt()} FCFA');
|
||||
} else if (montantMin != null) {
|
||||
parts.add('Montant min: ${montantMin!.toInt()} FCFA');
|
||||
} else {
|
||||
parts.add('Montant max: ${montantMax!.toInt()} FCFA');
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
/// Énumération pour les types d'opération
|
||||
enum TypeOperationDemande {
|
||||
creation,
|
||||
modification,
|
||||
soumission,
|
||||
evaluation,
|
||||
suppression,
|
||||
export,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des opérations
|
||||
extension TypeOperationDemandeExtension on TypeOperationDemande {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TypeOperationDemande.creation:
|
||||
return 'Création';
|
||||
case TypeOperationDemande.modification:
|
||||
return 'Modification';
|
||||
case TypeOperationDemande.soumission:
|
||||
return 'Soumission';
|
||||
case TypeOperationDemande.evaluation:
|
||||
return 'Évaluation';
|
||||
case TypeOperationDemande.suppression:
|
||||
return 'Suppression';
|
||||
case TypeOperationDemande.export:
|
||||
return 'Export';
|
||||
}
|
||||
}
|
||||
|
||||
String get messageSucces {
|
||||
switch (this) {
|
||||
case TypeOperationDemande.creation:
|
||||
return 'Demande d\'aide créée avec succès';
|
||||
case TypeOperationDemande.modification:
|
||||
return 'Demande d\'aide modifiée avec succès';
|
||||
case TypeOperationDemande.soumission:
|
||||
return 'Demande d\'aide soumise avec succès';
|
||||
case TypeOperationDemande.evaluation:
|
||||
return 'Demande d\'aide évaluée avec succès';
|
||||
case TypeOperationDemande.suppression:
|
||||
return 'Demande d\'aide supprimée avec succès';
|
||||
case TypeOperationDemande.export:
|
||||
return 'Export réalisé avec succès';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,438 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/evaluation_aide.dart';
|
||||
|
||||
/// Événements pour la gestion des évaluations d'aide
|
||||
///
|
||||
/// Ces événements représentent toutes les actions possibles
|
||||
/// que l'utilisateur peut effectuer sur les évaluations d'aide.
|
||||
abstract class EvaluationsEvent extends Equatable {
|
||||
const EvaluationsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Événement pour charger les évaluations
|
||||
class ChargerEvaluationsEvent extends EvaluationsEvent {
|
||||
final String? demandeId;
|
||||
final String? evaluateurId;
|
||||
final TypeEvaluateur? typeEvaluateur;
|
||||
final StatutAide? decision;
|
||||
final bool forceRefresh;
|
||||
|
||||
const ChargerEvaluationsEvent({
|
||||
this.demandeId,
|
||||
this.evaluateurId,
|
||||
this.typeEvaluateur,
|
||||
this.decision,
|
||||
this.forceRefresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
demandeId,
|
||||
evaluateurId,
|
||||
typeEvaluateur,
|
||||
decision,
|
||||
forceRefresh,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger plus d'évaluations (pagination)
|
||||
class ChargerPlusEvaluationsEvent extends EvaluationsEvent {
|
||||
const ChargerPlusEvaluationsEvent();
|
||||
}
|
||||
|
||||
/// Événement pour créer une nouvelle évaluation
|
||||
class CreerEvaluationEvent extends EvaluationsEvent {
|
||||
final EvaluationAide evaluation;
|
||||
|
||||
const CreerEvaluationEvent({required this.evaluation});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluation];
|
||||
}
|
||||
|
||||
/// Événement pour mettre à jour une évaluation
|
||||
class MettreAJourEvaluationEvent extends EvaluationsEvent {
|
||||
final EvaluationAide evaluation;
|
||||
|
||||
const MettreAJourEvaluationEvent({required this.evaluation});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluation];
|
||||
}
|
||||
|
||||
/// Événement pour obtenir une évaluation spécifique
|
||||
class ObtenirEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
|
||||
const ObtenirEvaluationEvent({required this.evaluationId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationId];
|
||||
}
|
||||
|
||||
/// Événement pour soumettre une évaluation
|
||||
class SoumettreEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
|
||||
const SoumettreEvaluationEvent({required this.evaluationId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationId];
|
||||
}
|
||||
|
||||
/// Événement pour approuver une évaluation
|
||||
class ApprouverEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
final String? commentaire;
|
||||
|
||||
const ApprouverEvaluationEvent({
|
||||
required this.evaluationId,
|
||||
this.commentaire,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [evaluationId, commentaire];
|
||||
}
|
||||
|
||||
/// Événement pour rejeter une évaluation
|
||||
class RejeterEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
final String motifRejet;
|
||||
|
||||
const RejeterEvaluationEvent({
|
||||
required this.evaluationId,
|
||||
required this.motifRejet,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationId, motifRejet];
|
||||
}
|
||||
|
||||
/// Événement pour rechercher des évaluations
|
||||
class RechercherEvaluationsEvent extends EvaluationsEvent {
|
||||
final String? demandeId;
|
||||
final String? evaluateurId;
|
||||
final TypeEvaluateur? typeEvaluateur;
|
||||
final StatutAide? decision;
|
||||
final DateTime? dateDebut;
|
||||
final DateTime? dateFin;
|
||||
final double? noteMin;
|
||||
final double? noteMax;
|
||||
final String? motCle;
|
||||
final int page;
|
||||
final int taille;
|
||||
|
||||
const RechercherEvaluationsEvent({
|
||||
this.demandeId,
|
||||
this.evaluateurId,
|
||||
this.typeEvaluateur,
|
||||
this.decision,
|
||||
this.dateDebut,
|
||||
this.dateFin,
|
||||
this.noteMin,
|
||||
this.noteMax,
|
||||
this.motCle,
|
||||
this.page = 0,
|
||||
this.taille = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
demandeId,
|
||||
evaluateurId,
|
||||
typeEvaluateur,
|
||||
decision,
|
||||
dateDebut,
|
||||
dateFin,
|
||||
noteMin,
|
||||
noteMax,
|
||||
motCle,
|
||||
page,
|
||||
taille,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger mes évaluations
|
||||
class ChargerMesEvaluationsEvent extends EvaluationsEvent {
|
||||
final String evaluateurId;
|
||||
|
||||
const ChargerMesEvaluationsEvent({required this.evaluateurId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluateurId];
|
||||
}
|
||||
|
||||
/// Événement pour charger les évaluations en attente
|
||||
class ChargerEvaluationsEnAttenteEvent extends EvaluationsEvent {
|
||||
final String? evaluateurId;
|
||||
final TypeEvaluateur? typeEvaluateur;
|
||||
|
||||
const ChargerEvaluationsEnAttenteEvent({
|
||||
this.evaluateurId,
|
||||
this.typeEvaluateur,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [evaluateurId, typeEvaluateur];
|
||||
}
|
||||
|
||||
/// Événement pour valider une évaluation
|
||||
class ValiderEvaluationEvent extends EvaluationsEvent {
|
||||
final EvaluationAide evaluation;
|
||||
|
||||
const ValiderEvaluationEvent({required this.evaluation});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluation];
|
||||
}
|
||||
|
||||
/// Événement pour calculer la note globale
|
||||
class CalculerNoteGlobaleEvent extends EvaluationsEvent {
|
||||
final Map<String, double> criteres;
|
||||
|
||||
const CalculerNoteGlobaleEvent({required this.criteres});
|
||||
|
||||
@override
|
||||
List<Object> get props => [criteres];
|
||||
}
|
||||
|
||||
/// Événement pour filtrer les évaluations localement
|
||||
class FiltrerEvaluationsEvent extends EvaluationsEvent {
|
||||
final TypeEvaluateur? typeEvaluateur;
|
||||
final StatutAide? decision;
|
||||
final double? noteMin;
|
||||
final double? noteMax;
|
||||
final String? motCle;
|
||||
final DateTime? dateDebut;
|
||||
final DateTime? dateFin;
|
||||
|
||||
const FiltrerEvaluationsEvent({
|
||||
this.typeEvaluateur,
|
||||
this.decision,
|
||||
this.noteMin,
|
||||
this.noteMax,
|
||||
this.motCle,
|
||||
this.dateDebut,
|
||||
this.dateFin,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeEvaluateur,
|
||||
decision,
|
||||
noteMin,
|
||||
noteMax,
|
||||
motCle,
|
||||
dateDebut,
|
||||
dateFin,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour trier les évaluations
|
||||
class TrierEvaluationsEvent extends EvaluationsEvent {
|
||||
final TriEvaluations critere;
|
||||
final bool croissant;
|
||||
|
||||
const TrierEvaluationsEvent({
|
||||
required this.critere,
|
||||
this.croissant = true,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [critere, croissant];
|
||||
}
|
||||
|
||||
/// Événement pour rafraîchir les évaluations
|
||||
class RafraichirEvaluationsEvent extends EvaluationsEvent {
|
||||
const RafraichirEvaluationsEvent();
|
||||
}
|
||||
|
||||
/// Événement pour réinitialiser l'état
|
||||
class ReinitialiserEvaluationsEvent extends EvaluationsEvent {
|
||||
const ReinitialiserEvaluationsEvent();
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner une évaluation
|
||||
class SelectionnerEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerEvaluationEvent({
|
||||
required this.evaluationId,
|
||||
required this.selectionne,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationId, selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner toutes les évaluations
|
||||
class SelectionnerToutesEvaluationsEvent extends EvaluationsEvent {
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerToutesEvaluationsEvent({required this.selectionne});
|
||||
|
||||
@override
|
||||
List<Object> get props => [selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour supprimer des évaluations sélectionnées
|
||||
class SupprimerEvaluationsSelectionnees extends EvaluationsEvent {
|
||||
final List<String> evaluationIds;
|
||||
|
||||
const SupprimerEvaluationsSelectionnees({required this.evaluationIds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationIds];
|
||||
}
|
||||
|
||||
/// Événement pour exporter des évaluations
|
||||
class ExporterEvaluationsEvent extends EvaluationsEvent {
|
||||
final List<String> evaluationIds;
|
||||
final FormatExport format;
|
||||
|
||||
const ExporterEvaluationsEvent({
|
||||
required this.evaluationIds,
|
||||
required this.format,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [evaluationIds, format];
|
||||
}
|
||||
|
||||
/// Événement pour obtenir les statistiques d'évaluation
|
||||
class ObtenirStatistiquesEvaluationEvent extends EvaluationsEvent {
|
||||
final String? evaluateurId;
|
||||
final DateTime? dateDebut;
|
||||
final DateTime? dateFin;
|
||||
|
||||
const ObtenirStatistiquesEvaluationEvent({
|
||||
this.evaluateurId,
|
||||
this.dateDebut,
|
||||
this.dateFin,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [evaluateurId, dateDebut, dateFin];
|
||||
}
|
||||
|
||||
/// Événement pour signaler une évaluation
|
||||
class SignalerEvaluationEvent extends EvaluationsEvent {
|
||||
final String evaluationId;
|
||||
final String motifSignalement;
|
||||
final String? description;
|
||||
|
||||
const SignalerEvaluationEvent({
|
||||
required this.evaluationId,
|
||||
required this.motifSignalement,
|
||||
this.description,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [evaluationId, motifSignalement, description];
|
||||
}
|
||||
|
||||
/// Énumération pour les critères de tri
|
||||
enum TriEvaluations {
|
||||
dateEvaluation,
|
||||
dateCreation,
|
||||
noteGlobale,
|
||||
decision,
|
||||
evaluateur,
|
||||
typeEvaluateur,
|
||||
demandeId,
|
||||
}
|
||||
|
||||
/// Énumération pour les formats d'export
|
||||
enum FormatExport {
|
||||
pdf,
|
||||
excel,
|
||||
csv,
|
||||
json,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des critères de tri
|
||||
extension TriEvaluationsExtension on TriEvaluations {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TriEvaluations.dateEvaluation:
|
||||
return 'Date d\'évaluation';
|
||||
case TriEvaluations.dateCreation:
|
||||
return 'Date de création';
|
||||
case TriEvaluations.noteGlobale:
|
||||
return 'Note globale';
|
||||
case TriEvaluations.decision:
|
||||
return 'Décision';
|
||||
case TriEvaluations.evaluateur:
|
||||
return 'Évaluateur';
|
||||
case TriEvaluations.typeEvaluateur:
|
||||
return 'Type d\'évaluateur';
|
||||
case TriEvaluations.demandeId:
|
||||
return 'Demande';
|
||||
}
|
||||
}
|
||||
|
||||
String get icone {
|
||||
switch (this) {
|
||||
case TriEvaluations.dateEvaluation:
|
||||
return 'calendar_today';
|
||||
case TriEvaluations.dateCreation:
|
||||
return 'schedule';
|
||||
case TriEvaluations.noteGlobale:
|
||||
return 'star';
|
||||
case TriEvaluations.decision:
|
||||
return 'gavel';
|
||||
case TriEvaluations.evaluateur:
|
||||
return 'person';
|
||||
case TriEvaluations.typeEvaluateur:
|
||||
return 'badge';
|
||||
case TriEvaluations.demandeId:
|
||||
return 'description';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des formats d'export
|
||||
extension FormatExportExtension on FormatExport {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'PDF';
|
||||
case FormatExport.excel:
|
||||
return 'Excel';
|
||||
case FormatExport.csv:
|
||||
return 'CSV';
|
||||
case FormatExport.json:
|
||||
return 'JSON';
|
||||
}
|
||||
}
|
||||
|
||||
String get extension {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return '.pdf';
|
||||
case FormatExport.excel:
|
||||
return '.xlsx';
|
||||
case FormatExport.csv:
|
||||
return '.csv';
|
||||
case FormatExport.json:
|
||||
return '.json';
|
||||
}
|
||||
}
|
||||
|
||||
String get mimeType {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'application/pdf';
|
||||
case FormatExport.excel:
|
||||
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
case FormatExport.csv:
|
||||
return 'text/csv';
|
||||
case FormatExport.json:
|
||||
return 'application/json';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,478 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/evaluation_aide.dart';
|
||||
import 'evaluations_event.dart';
|
||||
|
||||
/// États pour la gestion des évaluations d'aide
|
||||
///
|
||||
/// Ces états représentent tous les états possibles
|
||||
/// de l'interface utilisateur pour les évaluations d'aide.
|
||||
abstract class EvaluationsState extends Equatable {
|
||||
const EvaluationsState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class EvaluationsInitial extends EvaluationsState {
|
||||
const EvaluationsInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class EvaluationsLoading extends EvaluationsState {
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
|
||||
const EvaluationsLoading({
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [isRefreshing, isLoadingMore];
|
||||
}
|
||||
|
||||
/// État de succès avec données chargées
|
||||
class EvaluationsLoaded extends EvaluationsState {
|
||||
final List<EvaluationAide> evaluations;
|
||||
final List<EvaluationAide> evaluationsFiltrees;
|
||||
final bool hasReachedMax;
|
||||
final int currentPage;
|
||||
final int totalElements;
|
||||
final Map<String, bool> evaluationsSelectionnees;
|
||||
final TriEvaluations? criterieTri;
|
||||
final bool triCroissant;
|
||||
final FiltresEvaluations filtres;
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
final DateTime lastUpdated;
|
||||
|
||||
const EvaluationsLoaded({
|
||||
required this.evaluations,
|
||||
required this.evaluationsFiltrees,
|
||||
this.hasReachedMax = false,
|
||||
this.currentPage = 0,
|
||||
this.totalElements = 0,
|
||||
this.evaluationsSelectionnees = const {},
|
||||
this.criterieTri,
|
||||
this.triCroissant = true,
|
||||
this.filtres = const FiltresEvaluations(),
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
required this.lastUpdated,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
evaluations,
|
||||
evaluationsFiltrees,
|
||||
hasReachedMax,
|
||||
currentPage,
|
||||
totalElements,
|
||||
evaluationsSelectionnees,
|
||||
criterieTri,
|
||||
triCroissant,
|
||||
filtres,
|
||||
isRefreshing,
|
||||
isLoadingMore,
|
||||
lastUpdated,
|
||||
];
|
||||
|
||||
/// Copie l'état avec de nouvelles valeurs
|
||||
EvaluationsLoaded copyWith({
|
||||
List<EvaluationAide>? evaluations,
|
||||
List<EvaluationAide>? evaluationsFiltrees,
|
||||
bool? hasReachedMax,
|
||||
int? currentPage,
|
||||
int? totalElements,
|
||||
Map<String, bool>? evaluationsSelectionnees,
|
||||
TriEvaluations? criterieTri,
|
||||
bool? triCroissant,
|
||||
FiltresEvaluations? filtres,
|
||||
bool? isRefreshing,
|
||||
bool? isLoadingMore,
|
||||
DateTime? lastUpdated,
|
||||
}) {
|
||||
return EvaluationsLoaded(
|
||||
evaluations: evaluations ?? this.evaluations,
|
||||
evaluationsFiltrees: evaluationsFiltrees ?? this.evaluationsFiltrees,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
totalElements: totalElements ?? this.totalElements,
|
||||
evaluationsSelectionnees: evaluationsSelectionnees ?? this.evaluationsSelectionnees,
|
||||
criterieTri: criterieTri ?? this.criterieTri,
|
||||
triCroissant: triCroissant ?? this.triCroissant,
|
||||
filtres: filtres ?? this.filtres,
|
||||
isRefreshing: isRefreshing ?? this.isRefreshing,
|
||||
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||
lastUpdated: lastUpdated ?? this.lastUpdated,
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient le nombre d'évaluations sélectionnées
|
||||
int get nombreEvaluationsSelectionnees {
|
||||
return evaluationsSelectionnees.values.where((selected) => selected).length;
|
||||
}
|
||||
|
||||
/// Vérifie si toutes les évaluations sont sélectionnées
|
||||
bool get toutesEvaluationsSelectionnees {
|
||||
if (evaluationsFiltrees.isEmpty) return false;
|
||||
return evaluationsFiltrees.every((evaluation) =>
|
||||
evaluationsSelectionnees[evaluation.id] == true
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient les IDs des évaluations sélectionnées
|
||||
List<String> get evaluationsSelectionneesIds {
|
||||
return evaluationsSelectionnees.entries
|
||||
.where((entry) => entry.value)
|
||||
.map((entry) => entry.key)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// Obtient les évaluations sélectionnées
|
||||
List<EvaluationAide> get evaluationsSelectionneesEntities {
|
||||
return evaluations.where((evaluation) =>
|
||||
evaluationsSelectionnees[evaluation.id] == true
|
||||
).toList();
|
||||
}
|
||||
|
||||
/// Vérifie si des données sont disponibles
|
||||
bool get hasData => evaluations.isNotEmpty;
|
||||
|
||||
/// Vérifie si des filtres sont appliqués
|
||||
bool get hasFiltres => !filtres.isEmpty;
|
||||
|
||||
/// Obtient le texte de statut
|
||||
String get statusText {
|
||||
if (isRefreshing) return 'Actualisation...';
|
||||
if (isLoadingMore) return 'Chargement...';
|
||||
if (evaluationsFiltrees.isEmpty && hasData) return 'Aucun résultat pour les filtres appliqués';
|
||||
if (evaluationsFiltrees.isEmpty) return 'Aucune évaluation';
|
||||
return '${evaluationsFiltrees.length} évaluation${evaluationsFiltrees.length > 1 ? 's' : ''}';
|
||||
}
|
||||
|
||||
/// Obtient la note moyenne
|
||||
double get noteMoyenne {
|
||||
if (evaluationsFiltrees.isEmpty) return 0.0;
|
||||
final notesValides = evaluationsFiltrees
|
||||
.where((e) => e.noteGlobale != null)
|
||||
.map((e) => e.noteGlobale!)
|
||||
.toList();
|
||||
if (notesValides.isEmpty) return 0.0;
|
||||
return notesValides.reduce((a, b) => a + b) / notesValides.length;
|
||||
}
|
||||
|
||||
/// Obtient le nombre d'évaluations par décision
|
||||
Map<StatutAide, int> get repartitionDecisions {
|
||||
final repartition = <StatutAide, int>{};
|
||||
for (final evaluation in evaluationsFiltrees) {
|
||||
repartition[evaluation.decision] = (repartition[evaluation.decision] ?? 0) + 1;
|
||||
}
|
||||
return repartition;
|
||||
}
|
||||
}
|
||||
|
||||
/// État d'erreur
|
||||
class EvaluationsError extends EvaluationsState {
|
||||
final String message;
|
||||
final String? code;
|
||||
final bool isNetworkError;
|
||||
final bool canRetry;
|
||||
final List<EvaluationAide>? cachedData;
|
||||
|
||||
const EvaluationsError({
|
||||
required this.message,
|
||||
this.code,
|
||||
this.isNetworkError = false,
|
||||
this.canRetry = true,
|
||||
this.cachedData,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
message,
|
||||
code,
|
||||
isNetworkError,
|
||||
canRetry,
|
||||
cachedData,
|
||||
];
|
||||
|
||||
/// Vérifie si des données en cache sont disponibles
|
||||
bool get hasCachedData => cachedData != null && cachedData!.isNotEmpty;
|
||||
}
|
||||
|
||||
/// État de succès pour une opération spécifique
|
||||
class EvaluationsOperationSuccess extends EvaluationsState {
|
||||
final String message;
|
||||
final EvaluationAide? evaluation;
|
||||
final TypeOperationEvaluation operation;
|
||||
|
||||
const EvaluationsOperationSuccess({
|
||||
required this.message,
|
||||
this.evaluation,
|
||||
required this.operation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, evaluation, operation];
|
||||
}
|
||||
|
||||
/// État de validation
|
||||
class EvaluationsValidation extends EvaluationsState {
|
||||
final Map<String, String> erreurs;
|
||||
final bool isValid;
|
||||
final EvaluationAide? evaluation;
|
||||
|
||||
const EvaluationsValidation({
|
||||
required this.erreurs,
|
||||
required this.isValid,
|
||||
this.evaluation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [erreurs, isValid, evaluation];
|
||||
|
||||
/// Obtient la première erreur
|
||||
String? get premiereErreur {
|
||||
return erreurs.values.isNotEmpty ? erreurs.values.first : null;
|
||||
}
|
||||
|
||||
/// Obtient les erreurs pour un champ spécifique
|
||||
String? getErreurPourChamp(String champ) {
|
||||
return erreurs[champ];
|
||||
}
|
||||
}
|
||||
|
||||
/// État de calcul de note globale
|
||||
class EvaluationsNoteCalculee extends EvaluationsState {
|
||||
final double noteGlobale;
|
||||
final Map<String, double> criteres;
|
||||
|
||||
const EvaluationsNoteCalculee({
|
||||
required this.noteGlobale,
|
||||
required this.criteres,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [noteGlobale, criteres];
|
||||
}
|
||||
|
||||
/// État des statistiques d'évaluation
|
||||
class EvaluationsStatistiques extends EvaluationsState {
|
||||
final Map<String, dynamic> statistiques;
|
||||
final DateTime? dateDebut;
|
||||
final DateTime? dateFin;
|
||||
|
||||
const EvaluationsStatistiques({
|
||||
required this.statistiques,
|
||||
this.dateDebut,
|
||||
this.dateFin,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [statistiques, dateDebut, dateFin];
|
||||
}
|
||||
|
||||
/// État d'export
|
||||
class EvaluationsExporting extends EvaluationsState {
|
||||
final double progress;
|
||||
final String? currentStep;
|
||||
|
||||
const EvaluationsExporting({
|
||||
required this.progress,
|
||||
this.currentStep,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [progress, currentStep];
|
||||
}
|
||||
|
||||
/// État d'export terminé
|
||||
class EvaluationsExported extends EvaluationsState {
|
||||
final String filePath;
|
||||
final FormatExport format;
|
||||
final int nombreEvaluations;
|
||||
|
||||
const EvaluationsExported({
|
||||
required this.filePath,
|
||||
required this.format,
|
||||
required this.nombreEvaluations,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [filePath, format, nombreEvaluations];
|
||||
}
|
||||
|
||||
/// Classe pour les filtres des évaluations
|
||||
class FiltresEvaluations extends Equatable {
|
||||
final TypeEvaluateur? typeEvaluateur;
|
||||
final StatutAide? decision;
|
||||
final double? noteMin;
|
||||
final double? noteMax;
|
||||
final String? motCle;
|
||||
final String? evaluateurId;
|
||||
final String? demandeId;
|
||||
final DateTime? dateDebutEvaluation;
|
||||
final DateTime? dateFinEvaluation;
|
||||
|
||||
const FiltresEvaluations({
|
||||
this.typeEvaluateur,
|
||||
this.decision,
|
||||
this.noteMin,
|
||||
this.noteMax,
|
||||
this.motCle,
|
||||
this.evaluateurId,
|
||||
this.demandeId,
|
||||
this.dateDebutEvaluation,
|
||||
this.dateFinEvaluation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeEvaluateur,
|
||||
decision,
|
||||
noteMin,
|
||||
noteMax,
|
||||
motCle,
|
||||
evaluateurId,
|
||||
demandeId,
|
||||
dateDebutEvaluation,
|
||||
dateFinEvaluation,
|
||||
];
|
||||
|
||||
/// Copie les filtres avec de nouvelles valeurs
|
||||
FiltresEvaluations copyWith({
|
||||
TypeEvaluateur? typeEvaluateur,
|
||||
StatutAide? decision,
|
||||
double? noteMin,
|
||||
double? noteMax,
|
||||
String? motCle,
|
||||
String? evaluateurId,
|
||||
String? demandeId,
|
||||
DateTime? dateDebutEvaluation,
|
||||
DateTime? dateFinEvaluation,
|
||||
}) {
|
||||
return FiltresEvaluations(
|
||||
typeEvaluateur: typeEvaluateur ?? this.typeEvaluateur,
|
||||
decision: decision ?? this.decision,
|
||||
noteMin: noteMin ?? this.noteMin,
|
||||
noteMax: noteMax ?? this.noteMax,
|
||||
motCle: motCle ?? this.motCle,
|
||||
evaluateurId: evaluateurId ?? this.evaluateurId,
|
||||
demandeId: demandeId ?? this.demandeId,
|
||||
dateDebutEvaluation: dateDebutEvaluation ?? this.dateDebutEvaluation,
|
||||
dateFinEvaluation: dateFinEvaluation ?? this.dateFinEvaluation,
|
||||
);
|
||||
}
|
||||
|
||||
/// Réinitialise tous les filtres
|
||||
FiltresEvaluations clear() {
|
||||
return const FiltresEvaluations();
|
||||
}
|
||||
|
||||
/// Vérifie si les filtres sont vides
|
||||
bool get isEmpty {
|
||||
return typeEvaluateur == null &&
|
||||
decision == null &&
|
||||
noteMin == null &&
|
||||
noteMax == null &&
|
||||
(motCle == null || motCle!.isEmpty) &&
|
||||
evaluateurId == null &&
|
||||
demandeId == null &&
|
||||
dateDebutEvaluation == null &&
|
||||
dateFinEvaluation == null;
|
||||
}
|
||||
|
||||
/// Obtient le nombre de filtres actifs
|
||||
int get nombreFiltresActifs {
|
||||
int count = 0;
|
||||
if (typeEvaluateur != null) count++;
|
||||
if (decision != null) count++;
|
||||
if (noteMin != null) count++;
|
||||
if (noteMax != null) count++;
|
||||
if (motCle != null && motCle!.isNotEmpty) count++;
|
||||
if (evaluateurId != null) count++;
|
||||
if (demandeId != null) count++;
|
||||
if (dateDebutEvaluation != null) count++;
|
||||
if (dateFinEvaluation != null) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Obtient une description textuelle des filtres
|
||||
String get description {
|
||||
final parts = <String>[];
|
||||
|
||||
if (typeEvaluateur != null) parts.add('Type: ${typeEvaluateur!.libelle}');
|
||||
if (decision != null) parts.add('Décision: ${decision!.libelle}');
|
||||
if (motCle != null && motCle!.isNotEmpty) parts.add('Recherche: "$motCle"');
|
||||
if (noteMin != null || noteMax != null) {
|
||||
if (noteMin != null && noteMax != null) {
|
||||
parts.add('Note: ${noteMin!.toStringAsFixed(1)} - ${noteMax!.toStringAsFixed(1)}');
|
||||
} else if (noteMin != null) {
|
||||
parts.add('Note min: ${noteMin!.toStringAsFixed(1)}');
|
||||
} else {
|
||||
parts.add('Note max: ${noteMax!.toStringAsFixed(1)}');
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
/// Énumération pour les types d'opération
|
||||
enum TypeOperationEvaluation {
|
||||
creation,
|
||||
modification,
|
||||
soumission,
|
||||
approbation,
|
||||
rejet,
|
||||
suppression,
|
||||
export,
|
||||
signalement,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des opérations
|
||||
extension TypeOperationEvaluationExtension on TypeOperationEvaluation {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TypeOperationEvaluation.creation:
|
||||
return 'Création';
|
||||
case TypeOperationEvaluation.modification:
|
||||
return 'Modification';
|
||||
case TypeOperationEvaluation.soumission:
|
||||
return 'Soumission';
|
||||
case TypeOperationEvaluation.approbation:
|
||||
return 'Approbation';
|
||||
case TypeOperationEvaluation.rejet:
|
||||
return 'Rejet';
|
||||
case TypeOperationEvaluation.suppression:
|
||||
return 'Suppression';
|
||||
case TypeOperationEvaluation.export:
|
||||
return 'Export';
|
||||
case TypeOperationEvaluation.signalement:
|
||||
return 'Signalement';
|
||||
}
|
||||
}
|
||||
|
||||
String get messageSucces {
|
||||
switch (this) {
|
||||
case TypeOperationEvaluation.creation:
|
||||
return 'Évaluation créée avec succès';
|
||||
case TypeOperationEvaluation.modification:
|
||||
return 'Évaluation modifiée avec succès';
|
||||
case TypeOperationEvaluation.soumission:
|
||||
return 'Évaluation soumise avec succès';
|
||||
case TypeOperationEvaluation.approbation:
|
||||
return 'Évaluation approuvée avec succès';
|
||||
case TypeOperationEvaluation.rejet:
|
||||
return 'Évaluation rejetée avec succès';
|
||||
case TypeOperationEvaluation.suppression:
|
||||
return 'Évaluation supprimée avec succès';
|
||||
case TypeOperationEvaluation.export:
|
||||
return 'Export réalisé avec succès';
|
||||
case TypeOperationEvaluation.signalement:
|
||||
return 'Évaluation signalée avec succès';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/proposition_aide.dart';
|
||||
|
||||
/// Événements pour la gestion des propositions d'aide
|
||||
///
|
||||
/// Ces événements représentent toutes les actions possibles
|
||||
/// que l'utilisateur peut effectuer sur les propositions d'aide.
|
||||
abstract class PropositionsAideEvent extends Equatable {
|
||||
const PropositionsAideEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Événement pour charger les propositions d'aide
|
||||
class ChargerPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final String? organisationId;
|
||||
final TypeAide? typeAide;
|
||||
final StatutProposition? statut;
|
||||
final String? proposantId;
|
||||
final bool? disponible;
|
||||
final bool forceRefresh;
|
||||
|
||||
const ChargerPropositionsAideEvent({
|
||||
this.organisationId,
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.proposantId,
|
||||
this.disponible,
|
||||
this.forceRefresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
organisationId,
|
||||
typeAide,
|
||||
statut,
|
||||
proposantId,
|
||||
disponible,
|
||||
forceRefresh,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger plus de propositions (pagination)
|
||||
class ChargerPlusPropositionsAideEvent extends PropositionsAideEvent {
|
||||
const ChargerPlusPropositionsAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour créer une nouvelle proposition d'aide
|
||||
class CreerPropositionAideEvent extends PropositionsAideEvent {
|
||||
final PropositionAide proposition;
|
||||
|
||||
const CreerPropositionAideEvent({required this.proposition});
|
||||
|
||||
@override
|
||||
List<Object> get props => [proposition];
|
||||
}
|
||||
|
||||
/// Événement pour mettre à jour une proposition d'aide
|
||||
class MettreAJourPropositionAideEvent extends PropositionsAideEvent {
|
||||
final PropositionAide proposition;
|
||||
|
||||
const MettreAJourPropositionAideEvent({required this.proposition});
|
||||
|
||||
@override
|
||||
List<Object> get props => [proposition];
|
||||
}
|
||||
|
||||
/// Événement pour obtenir une proposition d'aide spécifique
|
||||
class ObtenirPropositionAideEvent extends PropositionsAideEvent {
|
||||
final String propositionId;
|
||||
|
||||
const ObtenirPropositionAideEvent({required this.propositionId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId];
|
||||
}
|
||||
|
||||
/// Événement pour activer/désactiver une proposition
|
||||
class ToggleDisponibilitePropositionEvent extends PropositionsAideEvent {
|
||||
final String propositionId;
|
||||
final bool disponible;
|
||||
|
||||
const ToggleDisponibilitePropositionEvent({
|
||||
required this.propositionId,
|
||||
required this.disponible,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId, disponible];
|
||||
}
|
||||
|
||||
/// Événement pour rechercher des propositions d'aide
|
||||
class RechercherPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final String? organisationId;
|
||||
final TypeAide? typeAide;
|
||||
final StatutProposition? statut;
|
||||
final String? proposantId;
|
||||
final bool? disponible;
|
||||
final String? motCle;
|
||||
final int page;
|
||||
final int taille;
|
||||
|
||||
const RechercherPropositionsAideEvent({
|
||||
this.organisationId,
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.proposantId,
|
||||
this.disponible,
|
||||
this.motCle,
|
||||
this.page = 0,
|
||||
this.taille = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
organisationId,
|
||||
typeAide,
|
||||
statut,
|
||||
proposantId,
|
||||
disponible,
|
||||
motCle,
|
||||
page,
|
||||
taille,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour charger mes propositions
|
||||
class ChargerMesPropositionsEvent extends PropositionsAideEvent {
|
||||
final String utilisateurId;
|
||||
|
||||
const ChargerMesPropositionsEvent({required this.utilisateurId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [utilisateurId];
|
||||
}
|
||||
|
||||
/// Événement pour charger les propositions disponibles
|
||||
class ChargerPropositionsDisponiblesEvent extends PropositionsAideEvent {
|
||||
final String organisationId;
|
||||
final TypeAide? typeAide;
|
||||
|
||||
const ChargerPropositionsDisponiblesEvent({
|
||||
required this.organisationId,
|
||||
this.typeAide,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organisationId, typeAide];
|
||||
}
|
||||
|
||||
/// Événement pour filtrer les propositions localement
|
||||
class FiltrerPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final TypeAide? typeAide;
|
||||
final StatutProposition? statut;
|
||||
final bool? disponible;
|
||||
final String? motCle;
|
||||
final double? capaciteMin;
|
||||
final double? capaciteMax;
|
||||
|
||||
const FiltrerPropositionsAideEvent({
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.disponible,
|
||||
this.motCle,
|
||||
this.capaciteMin,
|
||||
this.capaciteMax,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeAide,
|
||||
statut,
|
||||
disponible,
|
||||
motCle,
|
||||
capaciteMin,
|
||||
capaciteMax,
|
||||
];
|
||||
}
|
||||
|
||||
/// Événement pour trier les propositions
|
||||
class TrierPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final TriPropositions critere;
|
||||
final bool croissant;
|
||||
|
||||
const TrierPropositionsAideEvent({
|
||||
required this.critere,
|
||||
this.croissant = true,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [critere, croissant];
|
||||
}
|
||||
|
||||
/// Événement pour rafraîchir les propositions
|
||||
class RafraichirPropositionsAideEvent extends PropositionsAideEvent {
|
||||
const RafraichirPropositionsAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour réinitialiser l'état
|
||||
class ReinitialiserPropositionsAideEvent extends PropositionsAideEvent {
|
||||
const ReinitialiserPropositionsAideEvent();
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner une proposition
|
||||
class SelectionnerPropositionAideEvent extends PropositionsAideEvent {
|
||||
final String propositionId;
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerPropositionAideEvent({
|
||||
required this.propositionId,
|
||||
required this.selectionne,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId, selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour sélectionner/désélectionner toutes les propositions
|
||||
class SelectionnerToutesPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final bool selectionne;
|
||||
|
||||
const SelectionnerToutesPropositionsAideEvent({required this.selectionne});
|
||||
|
||||
@override
|
||||
List<Object> get props => [selectionne];
|
||||
}
|
||||
|
||||
/// Événement pour supprimer des propositions sélectionnées
|
||||
class SupprimerPropositionsSelectionnees extends PropositionsAideEvent {
|
||||
final List<String> propositionIds;
|
||||
|
||||
const SupprimerPropositionsSelectionnees({required this.propositionIds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionIds];
|
||||
}
|
||||
|
||||
/// Événement pour exporter des propositions
|
||||
class ExporterPropositionsAideEvent extends PropositionsAideEvent {
|
||||
final List<String> propositionIds;
|
||||
final FormatExport format;
|
||||
|
||||
const ExporterPropositionsAideEvent({
|
||||
required this.propositionIds,
|
||||
required this.format,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionIds, format];
|
||||
}
|
||||
|
||||
/// Événement pour calculer la compatibilité avec une demande
|
||||
class CalculerCompatibiliteEvent extends PropositionsAideEvent {
|
||||
final String propositionId;
|
||||
final String demandeId;
|
||||
|
||||
const CalculerCompatibiliteEvent({
|
||||
required this.propositionId,
|
||||
required this.demandeId,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId, demandeId];
|
||||
}
|
||||
|
||||
/// Événement pour obtenir les statistiques d'une proposition
|
||||
class ObtenirStatistiquesPropositionEvent extends PropositionsAideEvent {
|
||||
final String propositionId;
|
||||
|
||||
const ObtenirStatistiquesPropositionEvent({required this.propositionId});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId];
|
||||
}
|
||||
|
||||
/// Énumération pour les critères de tri
|
||||
enum TriPropositions {
|
||||
dateCreation,
|
||||
dateModification,
|
||||
titre,
|
||||
statut,
|
||||
capacite,
|
||||
proposant,
|
||||
scoreCompatibilite,
|
||||
nombreMatches,
|
||||
}
|
||||
|
||||
/// Énumération pour les formats d'export
|
||||
enum FormatExport {
|
||||
pdf,
|
||||
excel,
|
||||
csv,
|
||||
json,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des critères de tri
|
||||
extension TriPropositionsExtension on TriPropositions {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TriPropositions.dateCreation:
|
||||
return 'Date de création';
|
||||
case TriPropositions.dateModification:
|
||||
return 'Date de modification';
|
||||
case TriPropositions.titre:
|
||||
return 'Titre';
|
||||
case TriPropositions.statut:
|
||||
return 'Statut';
|
||||
case TriPropositions.capacite:
|
||||
return 'Capacité';
|
||||
case TriPropositions.proposant:
|
||||
return 'Proposant';
|
||||
case TriPropositions.scoreCompatibilite:
|
||||
return 'Score de compatibilité';
|
||||
case TriPropositions.nombreMatches:
|
||||
return 'Nombre de matches';
|
||||
}
|
||||
}
|
||||
|
||||
String get icone {
|
||||
switch (this) {
|
||||
case TriPropositions.dateCreation:
|
||||
return 'calendar_today';
|
||||
case TriPropositions.dateModification:
|
||||
return 'update';
|
||||
case TriPropositions.titre:
|
||||
return 'title';
|
||||
case TriPropositions.statut:
|
||||
return 'flag';
|
||||
case TriPropositions.capacite:
|
||||
return 'trending_up';
|
||||
case TriPropositions.proposant:
|
||||
return 'person';
|
||||
case TriPropositions.scoreCompatibilite:
|
||||
return 'star';
|
||||
case TriPropositions.nombreMatches:
|
||||
return 'link';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des formats d'export
|
||||
extension FormatExportExtension on FormatExport {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'PDF';
|
||||
case FormatExport.excel:
|
||||
return 'Excel';
|
||||
case FormatExport.csv:
|
||||
return 'CSV';
|
||||
case FormatExport.json:
|
||||
return 'JSON';
|
||||
}
|
||||
}
|
||||
|
||||
String get extension {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return '.pdf';
|
||||
case FormatExport.excel:
|
||||
return '.xlsx';
|
||||
case FormatExport.csv:
|
||||
return '.csv';
|
||||
case FormatExport.json:
|
||||
return '.json';
|
||||
}
|
||||
}
|
||||
|
||||
String get mimeType {
|
||||
switch (this) {
|
||||
case FormatExport.pdf:
|
||||
return 'application/pdf';
|
||||
case FormatExport.excel:
|
||||
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
||||
case FormatExport.csv:
|
||||
return 'text/csv';
|
||||
case FormatExport.json:
|
||||
return 'application/json';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../domain/entities/proposition_aide.dart';
|
||||
import 'propositions_aide_event.dart';
|
||||
|
||||
/// États pour la gestion des propositions d'aide
|
||||
///
|
||||
/// Ces états représentent tous les états possibles
|
||||
/// de l'interface utilisateur pour les propositions d'aide.
|
||||
abstract class PropositionsAideState extends Equatable {
|
||||
const PropositionsAideState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class PropositionsAideInitial extends PropositionsAideState {
|
||||
const PropositionsAideInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class PropositionsAideLoading extends PropositionsAideState {
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
|
||||
const PropositionsAideLoading({
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [isRefreshing, isLoadingMore];
|
||||
}
|
||||
|
||||
/// État de succès avec données chargées
|
||||
class PropositionsAideLoaded extends PropositionsAideState {
|
||||
final List<PropositionAide> propositions;
|
||||
final List<PropositionAide> propositionsFiltrees;
|
||||
final bool hasReachedMax;
|
||||
final int currentPage;
|
||||
final int totalElements;
|
||||
final Map<String, bool> propositionsSelectionnees;
|
||||
final TriPropositions? criterieTri;
|
||||
final bool triCroissant;
|
||||
final FiltresPropositionsAide filtres;
|
||||
final bool isRefreshing;
|
||||
final bool isLoadingMore;
|
||||
final DateTime lastUpdated;
|
||||
|
||||
const PropositionsAideLoaded({
|
||||
required this.propositions,
|
||||
required this.propositionsFiltrees,
|
||||
this.hasReachedMax = false,
|
||||
this.currentPage = 0,
|
||||
this.totalElements = 0,
|
||||
this.propositionsSelectionnees = const {},
|
||||
this.criterieTri,
|
||||
this.triCroissant = true,
|
||||
this.filtres = const FiltresPropositionsAide(),
|
||||
this.isRefreshing = false,
|
||||
this.isLoadingMore = false,
|
||||
required this.lastUpdated,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
propositions,
|
||||
propositionsFiltrees,
|
||||
hasReachedMax,
|
||||
currentPage,
|
||||
totalElements,
|
||||
propositionsSelectionnees,
|
||||
criterieTri,
|
||||
triCroissant,
|
||||
filtres,
|
||||
isRefreshing,
|
||||
isLoadingMore,
|
||||
lastUpdated,
|
||||
];
|
||||
|
||||
/// Copie l'état avec de nouvelles valeurs
|
||||
PropositionsAideLoaded copyWith({
|
||||
List<PropositionAide>? propositions,
|
||||
List<PropositionAide>? propositionsFiltrees,
|
||||
bool? hasReachedMax,
|
||||
int? currentPage,
|
||||
int? totalElements,
|
||||
Map<String, bool>? propositionsSelectionnees,
|
||||
TriPropositions? criterieTri,
|
||||
bool? triCroissant,
|
||||
FiltresPropositionsAide? filtres,
|
||||
bool? isRefreshing,
|
||||
bool? isLoadingMore,
|
||||
DateTime? lastUpdated,
|
||||
}) {
|
||||
return PropositionsAideLoaded(
|
||||
propositions: propositions ?? this.propositions,
|
||||
propositionsFiltrees: propositionsFiltrees ?? this.propositionsFiltrees,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
totalElements: totalElements ?? this.totalElements,
|
||||
propositionsSelectionnees: propositionsSelectionnees ?? this.propositionsSelectionnees,
|
||||
criterieTri: criterieTri ?? this.criterieTri,
|
||||
triCroissant: triCroissant ?? this.triCroissant,
|
||||
filtres: filtres ?? this.filtres,
|
||||
isRefreshing: isRefreshing ?? this.isRefreshing,
|
||||
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||
lastUpdated: lastUpdated ?? this.lastUpdated,
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient le nombre de propositions sélectionnées
|
||||
int get nombrePropositionsSelectionnees {
|
||||
return propositionsSelectionnees.values.where((selected) => selected).length;
|
||||
}
|
||||
|
||||
/// Vérifie si toutes les propositions sont sélectionnées
|
||||
bool get toutesPropositionsSelectionnees {
|
||||
if (propositionsFiltrees.isEmpty) return false;
|
||||
return propositionsFiltrees.every((proposition) =>
|
||||
propositionsSelectionnees[proposition.id] == true
|
||||
);
|
||||
}
|
||||
|
||||
/// Obtient les IDs des propositions sélectionnées
|
||||
List<String> get propositionsSelectionneesIds {
|
||||
return propositionsSelectionnees.entries
|
||||
.where((entry) => entry.value)
|
||||
.map((entry) => entry.key)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// Obtient les propositions sélectionnées
|
||||
List<PropositionAide> get propositionsSelectionneesEntities {
|
||||
return propositions.where((proposition) =>
|
||||
propositionsSelectionnees[proposition.id] == true
|
||||
).toList();
|
||||
}
|
||||
|
||||
/// Vérifie si des données sont disponibles
|
||||
bool get hasData => propositions.isNotEmpty;
|
||||
|
||||
/// Vérifie si des filtres sont appliqués
|
||||
bool get hasFiltres => !filtres.isEmpty;
|
||||
|
||||
/// Obtient le texte de statut
|
||||
String get statusText {
|
||||
if (isRefreshing) return 'Actualisation...';
|
||||
if (isLoadingMore) return 'Chargement...';
|
||||
if (propositionsFiltrees.isEmpty && hasData) return 'Aucun résultat pour les filtres appliqués';
|
||||
if (propositionsFiltrees.isEmpty) return 'Aucune proposition d\'aide';
|
||||
return '${propositionsFiltrees.length} proposition${propositionsFiltrees.length > 1 ? 's' : ''}';
|
||||
}
|
||||
|
||||
/// Obtient le nombre de propositions disponibles
|
||||
int get nombrePropositionsDisponibles {
|
||||
return propositionsFiltrees.where((p) => p.estDisponible).length;
|
||||
}
|
||||
|
||||
/// Obtient la capacité totale disponible
|
||||
double get capaciteTotaleDisponible {
|
||||
return propositionsFiltrees
|
||||
.where((p) => p.estDisponible)
|
||||
.fold(0.0, (sum, p) => sum + (p.capaciteMaximale ?? 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
/// État d'erreur
|
||||
class PropositionsAideError extends PropositionsAideState {
|
||||
final String message;
|
||||
final String? code;
|
||||
final bool isNetworkError;
|
||||
final bool canRetry;
|
||||
final List<PropositionAide>? cachedData;
|
||||
|
||||
const PropositionsAideError({
|
||||
required this.message,
|
||||
this.code,
|
||||
this.isNetworkError = false,
|
||||
this.canRetry = true,
|
||||
this.cachedData,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
message,
|
||||
code,
|
||||
isNetworkError,
|
||||
canRetry,
|
||||
cachedData,
|
||||
];
|
||||
|
||||
/// Vérifie si des données en cache sont disponibles
|
||||
bool get hasCachedData => cachedData != null && cachedData!.isNotEmpty;
|
||||
}
|
||||
|
||||
/// État de succès pour une opération spécifique
|
||||
class PropositionsAideOperationSuccess extends PropositionsAideState {
|
||||
final String message;
|
||||
final PropositionAide? proposition;
|
||||
final TypeOperationProposition operation;
|
||||
|
||||
const PropositionsAideOperationSuccess({
|
||||
required this.message,
|
||||
this.proposition,
|
||||
required this.operation,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, proposition, operation];
|
||||
}
|
||||
|
||||
/// État de compatibilité calculée
|
||||
class PropositionsAideCompatibilite extends PropositionsAideState {
|
||||
final String propositionId;
|
||||
final String demandeId;
|
||||
final double scoreCompatibilite;
|
||||
final Map<String, dynamic> detailsCompatibilite;
|
||||
|
||||
const PropositionsAideCompatibilite({
|
||||
required this.propositionId,
|
||||
required this.demandeId,
|
||||
required this.scoreCompatibilite,
|
||||
required this.detailsCompatibilite,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId, demandeId, scoreCompatibilite, detailsCompatibilite];
|
||||
}
|
||||
|
||||
/// État des statistiques d'une proposition
|
||||
class PropositionsAideStatistiques extends PropositionsAideState {
|
||||
final String propositionId;
|
||||
final Map<String, dynamic> statistiques;
|
||||
|
||||
const PropositionsAideStatistiques({
|
||||
required this.propositionId,
|
||||
required this.statistiques,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [propositionId, statistiques];
|
||||
}
|
||||
|
||||
/// État d'export
|
||||
class PropositionsAideExporting extends PropositionsAideState {
|
||||
final double progress;
|
||||
final String? currentStep;
|
||||
|
||||
const PropositionsAideExporting({
|
||||
required this.progress,
|
||||
this.currentStep,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [progress, currentStep];
|
||||
}
|
||||
|
||||
/// État d'export terminé
|
||||
class PropositionsAideExported extends PropositionsAideState {
|
||||
final String filePath;
|
||||
final FormatExport format;
|
||||
final int nombrePropositions;
|
||||
|
||||
const PropositionsAideExported({
|
||||
required this.filePath,
|
||||
required this.format,
|
||||
required this.nombrePropositions,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [filePath, format, nombrePropositions];
|
||||
}
|
||||
|
||||
/// Classe pour les filtres des propositions d'aide
|
||||
class FiltresPropositionsAide extends Equatable {
|
||||
final TypeAide? typeAide;
|
||||
final StatutProposition? statut;
|
||||
final bool? disponible;
|
||||
final String? motCle;
|
||||
final String? organisationId;
|
||||
final String? proposantId;
|
||||
final DateTime? dateDebutCreation;
|
||||
final DateTime? dateFinCreation;
|
||||
final double? capaciteMin;
|
||||
final double? capaciteMax;
|
||||
|
||||
const FiltresPropositionsAide({
|
||||
this.typeAide,
|
||||
this.statut,
|
||||
this.disponible,
|
||||
this.motCle,
|
||||
this.organisationId,
|
||||
this.proposantId,
|
||||
this.dateDebutCreation,
|
||||
this.dateFinCreation,
|
||||
this.capaciteMin,
|
||||
this.capaciteMax,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
typeAide,
|
||||
statut,
|
||||
disponible,
|
||||
motCle,
|
||||
organisationId,
|
||||
proposantId,
|
||||
dateDebutCreation,
|
||||
dateFinCreation,
|
||||
capaciteMin,
|
||||
capaciteMax,
|
||||
];
|
||||
|
||||
/// Copie les filtres avec de nouvelles valeurs
|
||||
FiltresPropositionsAide copyWith({
|
||||
TypeAide? typeAide,
|
||||
StatutProposition? statut,
|
||||
bool? disponible,
|
||||
String? motCle,
|
||||
String? organisationId,
|
||||
String? proposantId,
|
||||
DateTime? dateDebutCreation,
|
||||
DateTime? dateFinCreation,
|
||||
double? capaciteMin,
|
||||
double? capaciteMax,
|
||||
}) {
|
||||
return FiltresPropositionsAide(
|
||||
typeAide: typeAide ?? this.typeAide,
|
||||
statut: statut ?? this.statut,
|
||||
disponible: disponible ?? this.disponible,
|
||||
motCle: motCle ?? this.motCle,
|
||||
organisationId: organisationId ?? this.organisationId,
|
||||
proposantId: proposantId ?? this.proposantId,
|
||||
dateDebutCreation: dateDebutCreation ?? this.dateDebutCreation,
|
||||
dateFinCreation: dateFinCreation ?? this.dateFinCreation,
|
||||
capaciteMin: capaciteMin ?? this.capaciteMin,
|
||||
capaciteMax: capaciteMax ?? this.capaciteMax,
|
||||
);
|
||||
}
|
||||
|
||||
/// Réinitialise tous les filtres
|
||||
FiltresPropositionsAide clear() {
|
||||
return const FiltresPropositionsAide();
|
||||
}
|
||||
|
||||
/// Vérifie si les filtres sont vides
|
||||
bool get isEmpty {
|
||||
return typeAide == null &&
|
||||
statut == null &&
|
||||
disponible == null &&
|
||||
(motCle == null || motCle!.isEmpty) &&
|
||||
organisationId == null &&
|
||||
proposantId == null &&
|
||||
dateDebutCreation == null &&
|
||||
dateFinCreation == null &&
|
||||
capaciteMin == null &&
|
||||
capaciteMax == null;
|
||||
}
|
||||
|
||||
/// Obtient le nombre de filtres actifs
|
||||
int get nombreFiltresActifs {
|
||||
int count = 0;
|
||||
if (typeAide != null) count++;
|
||||
if (statut != null) count++;
|
||||
if (disponible != null) count++;
|
||||
if (motCle != null && motCle!.isNotEmpty) count++;
|
||||
if (organisationId != null) count++;
|
||||
if (proposantId != null) count++;
|
||||
if (dateDebutCreation != null) count++;
|
||||
if (dateFinCreation != null) count++;
|
||||
if (capaciteMin != null) count++;
|
||||
if (capaciteMax != null) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Obtient une description textuelle des filtres
|
||||
String get description {
|
||||
final parts = <String>[];
|
||||
|
||||
if (typeAide != null) parts.add('Type: ${typeAide!.libelle}');
|
||||
if (statut != null) parts.add('Statut: ${statut!.libelle}');
|
||||
if (disponible == true) parts.add('Disponible uniquement');
|
||||
if (disponible == false) parts.add('Non disponible uniquement');
|
||||
if (motCle != null && motCle!.isNotEmpty) parts.add('Recherche: "$motCle"');
|
||||
if (capaciteMin != null || capaciteMax != null) {
|
||||
if (capaciteMin != null && capaciteMax != null) {
|
||||
parts.add('Capacité: ${capaciteMin!.toInt()} - ${capaciteMax!.toInt()}');
|
||||
} else if (capaciteMin != null) {
|
||||
parts.add('Capacité min: ${capaciteMin!.toInt()}');
|
||||
} else {
|
||||
parts.add('Capacité max: ${capaciteMax!.toInt()}');
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
/// Énumération pour les types d'opération
|
||||
enum TypeOperationProposition {
|
||||
creation,
|
||||
modification,
|
||||
activation,
|
||||
desactivation,
|
||||
suppression,
|
||||
export,
|
||||
}
|
||||
|
||||
/// Extension pour obtenir le libellé des opérations
|
||||
extension TypeOperationPropositionExtension on TypeOperationProposition {
|
||||
String get libelle {
|
||||
switch (this) {
|
||||
case TypeOperationProposition.creation:
|
||||
return 'Création';
|
||||
case TypeOperationProposition.modification:
|
||||
return 'Modification';
|
||||
case TypeOperationProposition.activation:
|
||||
return 'Activation';
|
||||
case TypeOperationProposition.desactivation:
|
||||
return 'Désactivation';
|
||||
case TypeOperationProposition.suppression:
|
||||
return 'Suppression';
|
||||
case TypeOperationProposition.export:
|
||||
return 'Export';
|
||||
}
|
||||
}
|
||||
|
||||
String get messageSucces {
|
||||
switch (this) {
|
||||
case TypeOperationProposition.creation:
|
||||
return 'Proposition d\'aide créée avec succès';
|
||||
case TypeOperationProposition.modification:
|
||||
return 'Proposition d\'aide modifiée avec succès';
|
||||
case TypeOperationProposition.activation:
|
||||
return 'Proposition d\'aide activée avec succès';
|
||||
case TypeOperationProposition.desactivation:
|
||||
return 'Proposition d\'aide désactivée avec succès';
|
||||
case TypeOperationProposition.suppression:
|
||||
return 'Proposition d\'aide supprimée avec succès';
|
||||
case TypeOperationProposition.export:
|
||||
return 'Export réalisé avec succès';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user