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';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user