731 lines
23 KiB
Dart
731 lines
23 KiB
Dart
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:injectable/injectable.dart';
|
|
import '../../../../core/models/cotisation_model.dart';
|
|
import '../../../../core/models/payment_model.dart';
|
|
import '../../../../core/services/payment_service.dart';
|
|
import '../../../../core/services/notification_service.dart';
|
|
import '../../domain/repositories/cotisation_repository.dart';
|
|
import 'cotisations_event.dart';
|
|
import 'cotisations_state.dart';
|
|
|
|
/// BLoC pour la gestion des cotisations
|
|
/// Gère l'état et les événements liés aux cotisations
|
|
@injectable
|
|
class CotisationsBloc extends Bloc<CotisationsEvent, CotisationsState> {
|
|
final CotisationRepository _cotisationRepository;
|
|
final PaymentService _paymentService;
|
|
final NotificationService _notificationService;
|
|
|
|
CotisationsBloc(
|
|
this._cotisationRepository,
|
|
this._paymentService,
|
|
this._notificationService,
|
|
) : super(const CotisationsInitial()) {
|
|
// Enregistrement des handlers d'événements
|
|
on<LoadCotisations>(_onLoadCotisations);
|
|
on<LoadCotisationById>(_onLoadCotisationById);
|
|
on<LoadCotisationByReference>(_onLoadCotisationByReference);
|
|
on<CreateCotisation>(_onCreateCotisation);
|
|
on<UpdateCotisation>(_onUpdateCotisation);
|
|
on<DeleteCotisation>(_onDeleteCotisation);
|
|
on<LoadCotisationsByMembre>(_onLoadCotisationsByMembre);
|
|
on<LoadCotisationsByStatut>(_onLoadCotisationsByStatut);
|
|
on<LoadCotisationsEnRetard>(_onLoadCotisationsEnRetard);
|
|
on<SearchCotisations>(_onSearchCotisations);
|
|
on<LoadCotisationsStats>(_onLoadCotisationsStats);
|
|
on<RefreshCotisations>(_onRefreshCotisations);
|
|
on<ResetCotisationsState>(_onResetCotisationsState);
|
|
on<FilterCotisations>(_onFilterCotisations);
|
|
on<SortCotisations>(_onSortCotisations);
|
|
|
|
// Nouveaux handlers pour les paiements et fonctionnalités avancées
|
|
on<InitiatePayment>(_onInitiatePayment);
|
|
on<CheckPaymentStatus>(_onCheckPaymentStatus);
|
|
on<CancelPayment>(_onCancelPayment);
|
|
on<ScheduleNotifications>(_onScheduleNotifications);
|
|
on<SyncWithServer>(_onSyncWithServer);
|
|
on<ApplyAdvancedFilters>(_onApplyAdvancedFilters);
|
|
on<ExportCotisations>(_onExportCotisations);
|
|
}
|
|
|
|
/// Handler pour charger la liste des cotisations
|
|
Future<void> _onLoadCotisations(
|
|
LoadCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh || state is CotisationsInitial) {
|
|
emit(CotisationsLoading(isRefreshing: event.refresh));
|
|
}
|
|
|
|
final cotisations = await _cotisationRepository.getCotisations(
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
List<CotisationModel> allCotisations = [];
|
|
|
|
// Si c'est un refresh ou la première page, remplacer la liste
|
|
if (event.refresh || event.page == 0) {
|
|
allCotisations = cotisations;
|
|
} else {
|
|
// Sinon, ajouter à la liste existante (pagination)
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
allCotisations = [...currentState.cotisations, ...cotisations];
|
|
} else {
|
|
allCotisations = cotisations;
|
|
}
|
|
}
|
|
|
|
emit(CotisationsLoaded(
|
|
cotisations: allCotisations,
|
|
filteredCotisations: allCotisations,
|
|
hasReachedMax: cotisations.length < event.size,
|
|
currentPage: event.page,
|
|
));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement des cotisations: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger une cotisation par ID
|
|
Future<void> _onLoadCotisationById(
|
|
LoadCotisationById event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const CotisationsLoading());
|
|
|
|
final cotisation = await _cotisationRepository.getCotisationById(event.id);
|
|
|
|
emit(CotisationDetailLoaded(cotisation));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement de la cotisation: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger une cotisation par référence
|
|
Future<void> _onLoadCotisationByReference(
|
|
LoadCotisationByReference event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const CotisationsLoading());
|
|
|
|
final cotisation = await _cotisationRepository.getCotisationByReference(event.numeroReference);
|
|
|
|
emit(CotisationDetailLoaded(cotisation));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement de la cotisation: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour créer une nouvelle cotisation
|
|
Future<void> _onCreateCotisation(
|
|
CreateCotisation event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const CotisationOperationLoading('create'));
|
|
|
|
final nouvelleCotisation = await _cotisationRepository.createCotisation(event.cotisation);
|
|
|
|
emit(CotisationCreated(nouvelleCotisation));
|
|
|
|
// Recharger la liste des cotisations
|
|
add(const LoadCotisations(refresh: true));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors de la création de la cotisation: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour mettre à jour une cotisation
|
|
Future<void> _onUpdateCotisation(
|
|
UpdateCotisation event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(CotisationOperationLoading('update', cotisationId: event.id));
|
|
|
|
final cotisationMiseAJour = await _cotisationRepository.updateCotisation(
|
|
event.id,
|
|
event.cotisation,
|
|
);
|
|
|
|
emit(CotisationUpdated(cotisationMiseAJour));
|
|
|
|
// Mettre à jour la liste si elle est chargée
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
final updatedList = currentState.cotisations.map((c) {
|
|
return c.id == event.id ? cotisationMiseAJour : c;
|
|
}).toList();
|
|
|
|
emit(currentState.copyWith(
|
|
cotisations: updatedList,
|
|
filteredCotisations: updatedList,
|
|
));
|
|
}
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors de la mise à jour de la cotisation: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour supprimer une cotisation
|
|
Future<void> _onDeleteCotisation(
|
|
DeleteCotisation event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(CotisationOperationLoading('delete', cotisationId: event.id));
|
|
|
|
await _cotisationRepository.deleteCotisation(event.id);
|
|
|
|
emit(CotisationDeleted(event.id));
|
|
|
|
// Retirer de la liste si elle est chargée
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
final updatedList = currentState.cotisations
|
|
.where((c) => c.id != event.id)
|
|
.toList();
|
|
|
|
emit(currentState.copyWith(
|
|
cotisations: updatedList,
|
|
filteredCotisations: updatedList,
|
|
));
|
|
}
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors de la suppression de la cotisation: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger les cotisations d'un membre
|
|
Future<void> _onLoadCotisationsByMembre(
|
|
LoadCotisationsByMembre event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh || event.page == 0) {
|
|
emit(CotisationsLoading(isRefreshing: event.refresh));
|
|
}
|
|
|
|
final cotisations = await _cotisationRepository.getCotisationsByMembre(
|
|
event.membreId,
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
List<CotisationModel> allCotisations = [];
|
|
|
|
if (event.refresh || event.page == 0) {
|
|
allCotisations = cotisations;
|
|
} else {
|
|
if (state is CotisationsByMembreLoaded) {
|
|
final currentState = state as CotisationsByMembreLoaded;
|
|
allCotisations = [...currentState.cotisations, ...cotisations];
|
|
} else {
|
|
allCotisations = cotisations;
|
|
}
|
|
}
|
|
|
|
emit(CotisationsByMembreLoaded(
|
|
membreId: event.membreId,
|
|
cotisations: allCotisations,
|
|
hasReachedMax: cotisations.length < event.size,
|
|
currentPage: event.page,
|
|
));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement des cotisations du membre: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger les cotisations par statut
|
|
Future<void> _onLoadCotisationsByStatut(
|
|
LoadCotisationsByStatut event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh || event.page == 0) {
|
|
emit(CotisationsLoading(isRefreshing: event.refresh));
|
|
}
|
|
|
|
final cotisations = await _cotisationRepository.getCotisationsByStatut(
|
|
event.statut,
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
List<CotisationModel> allCotisations = [];
|
|
|
|
if (event.refresh || event.page == 0) {
|
|
allCotisations = cotisations;
|
|
} else {
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
allCotisations = [...currentState.cotisations, ...cotisations];
|
|
} else {
|
|
allCotisations = cotisations;
|
|
}
|
|
}
|
|
|
|
emit(CotisationsLoaded(
|
|
cotisations: allCotisations,
|
|
filteredCotisations: allCotisations,
|
|
hasReachedMax: cotisations.length < event.size,
|
|
currentPage: event.page,
|
|
currentFilter: event.statut,
|
|
));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement des cotisations par statut: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger les cotisations en retard
|
|
Future<void> _onLoadCotisationsEnRetard(
|
|
LoadCotisationsEnRetard event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh || event.page == 0) {
|
|
emit(CotisationsLoading(isRefreshing: event.refresh));
|
|
}
|
|
|
|
final cotisations = await _cotisationRepository.getCotisationsEnRetard(
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
List<CotisationModel> allCotisations = [];
|
|
|
|
if (event.refresh || event.page == 0) {
|
|
allCotisations = cotisations;
|
|
} else {
|
|
if (state is CotisationsEnRetardLoaded) {
|
|
final currentState = state as CotisationsEnRetardLoaded;
|
|
allCotisations = [...currentState.cotisations, ...cotisations];
|
|
} else {
|
|
allCotisations = cotisations;
|
|
}
|
|
}
|
|
|
|
emit(CotisationsEnRetardLoaded(
|
|
cotisations: allCotisations,
|
|
hasReachedMax: cotisations.length < event.size,
|
|
currentPage: event.page,
|
|
));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement des cotisations en retard: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour la recherche de cotisations
|
|
Future<void> _onSearchCotisations(
|
|
SearchCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh || event.page == 0) {
|
|
emit(CotisationsLoading(isRefreshing: event.refresh));
|
|
}
|
|
|
|
final cotisations = await _cotisationRepository.rechercherCotisations(
|
|
membreId: event.membreId,
|
|
statut: event.statut,
|
|
typeCotisation: event.typeCotisation,
|
|
annee: event.annee,
|
|
mois: event.mois,
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
final searchCriteria = <String, dynamic>{
|
|
if (event.membreId != null) 'membreId': event.membreId,
|
|
if (event.statut != null) 'statut': event.statut,
|
|
if (event.typeCotisation != null) 'typeCotisation': event.typeCotisation,
|
|
if (event.annee != null) 'annee': event.annee,
|
|
if (event.mois != null) 'mois': event.mois,
|
|
};
|
|
|
|
List<CotisationModel> allCotisations = [];
|
|
|
|
if (event.refresh || event.page == 0) {
|
|
allCotisations = cotisations;
|
|
} else {
|
|
if (state is CotisationsSearchResults) {
|
|
final currentState = state as CotisationsSearchResults;
|
|
allCotisations = [...currentState.cotisations, ...cotisations];
|
|
} else {
|
|
allCotisations = cotisations;
|
|
}
|
|
}
|
|
|
|
emit(CotisationsSearchResults(
|
|
cotisations: allCotisations,
|
|
searchCriteria: searchCriteria,
|
|
hasReachedMax: cotisations.length < event.size,
|
|
currentPage: event.page,
|
|
));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors de la recherche de cotisations: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour charger les statistiques
|
|
Future<void> _onLoadCotisationsStats(
|
|
LoadCotisationsStats event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const CotisationsLoading());
|
|
|
|
final statistics = await _cotisationRepository.getCotisationsStats();
|
|
|
|
emit(CotisationsStatsLoaded(statistics));
|
|
} catch (error) {
|
|
emit(CotisationsError(
|
|
'Erreur lors du chargement des statistiques: ${error.toString()}',
|
|
originalError: error,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour rafraîchir les données
|
|
Future<void> _onRefreshCotisations(
|
|
RefreshCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
add(const LoadCotisations(refresh: true));
|
|
}
|
|
|
|
/// Handler pour réinitialiser l'état
|
|
Future<void> _onResetCotisationsState(
|
|
ResetCotisationsState event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
emit(const CotisationsInitial());
|
|
}
|
|
|
|
/// Handler pour filtrer les cotisations localement
|
|
Future<void> _onFilterCotisations(
|
|
FilterCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
|
|
List<CotisationModel> filteredList = currentState.cotisations;
|
|
|
|
// Filtrage par recherche textuelle
|
|
if (event.searchQuery != null && event.searchQuery!.isNotEmpty) {
|
|
final query = event.searchQuery!.toLowerCase();
|
|
filteredList = filteredList.where((cotisation) {
|
|
return cotisation.numeroReference.toLowerCase().contains(query) ||
|
|
(cotisation.nomMembre?.toLowerCase().contains(query) ?? false) ||
|
|
cotisation.typeCotisation.toLowerCase().contains(query) ||
|
|
(cotisation.description?.toLowerCase().contains(query) ?? false);
|
|
}).toList();
|
|
}
|
|
|
|
// Filtrage par statut
|
|
if (event.statutFilter != null && event.statutFilter!.isNotEmpty) {
|
|
filteredList = filteredList.where((cotisation) {
|
|
return cotisation.statut == event.statutFilter;
|
|
}).toList();
|
|
}
|
|
|
|
// Filtrage par type
|
|
if (event.typeFilter != null && event.typeFilter!.isNotEmpty) {
|
|
filteredList = filteredList.where((cotisation) {
|
|
return cotisation.typeCotisation == event.typeFilter;
|
|
}).toList();
|
|
}
|
|
|
|
emit(currentState.copyWith(
|
|
filteredCotisations: filteredList,
|
|
searchQuery: event.searchQuery,
|
|
currentFilter: event.statutFilter ?? event.typeFilter,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour trier les cotisations
|
|
Future<void> _onSortCotisations(
|
|
SortCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
if (state is CotisationsLoaded) {
|
|
final currentState = state as CotisationsLoaded;
|
|
|
|
List<CotisationModel> sortedList = [...currentState.filteredCotisations];
|
|
|
|
switch (event.sortBy) {
|
|
case 'dateEcheance':
|
|
sortedList.sort((a, b) => event.ascending
|
|
? a.dateEcheance.compareTo(b.dateEcheance)
|
|
: b.dateEcheance.compareTo(a.dateEcheance));
|
|
break;
|
|
case 'montantDu':
|
|
sortedList.sort((a, b) => event.ascending
|
|
? a.montantDu.compareTo(b.montantDu)
|
|
: b.montantDu.compareTo(a.montantDu));
|
|
break;
|
|
case 'statut':
|
|
sortedList.sort((a, b) => event.ascending
|
|
? a.statut.compareTo(b.statut)
|
|
: b.statut.compareTo(a.statut));
|
|
break;
|
|
case 'nomMembre':
|
|
sortedList.sort((a, b) => event.ascending
|
|
? (a.nomMembre ?? '').compareTo(b.nomMembre ?? '')
|
|
: (b.nomMembre ?? '').compareTo(a.nomMembre ?? ''));
|
|
break;
|
|
case 'typeCotisation':
|
|
sortedList.sort((a, b) => event.ascending
|
|
? a.typeCotisation.compareTo(b.typeCotisation)
|
|
: b.typeCotisation.compareTo(a.typeCotisation));
|
|
break;
|
|
default:
|
|
// Tri par défaut par date d'échéance
|
|
sortedList.sort((a, b) => b.dateEcheance.compareTo(a.dateEcheance));
|
|
}
|
|
|
|
emit(currentState.copyWith(filteredCotisations: sortedList));
|
|
}
|
|
}
|
|
|
|
/// Handler pour initier un paiement
|
|
Future<void> _onInitiatePayment(
|
|
InitiatePayment event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
// Valider les données de paiement
|
|
if (!_paymentService.validatePaymentData(
|
|
cotisationId: event.cotisationId,
|
|
montant: event.montant,
|
|
methodePaiement: event.methodePaiement,
|
|
numeroTelephone: event.numeroTelephone,
|
|
)) {
|
|
emit(PaymentFailure(
|
|
cotisationId: event.cotisationId,
|
|
paymentId: '',
|
|
errorMessage: 'Données de paiement invalides',
|
|
errorCode: 'INVALID_DATA',
|
|
));
|
|
return;
|
|
}
|
|
|
|
// Initier le paiement
|
|
final payment = await _paymentService.initiatePayment(
|
|
cotisationId: event.cotisationId,
|
|
montant: event.montant,
|
|
methodePaiement: event.methodePaiement,
|
|
numeroTelephone: event.numeroTelephone,
|
|
nomPayeur: event.nomPayeur,
|
|
emailPayeur: event.emailPayeur,
|
|
);
|
|
|
|
emit(PaymentInProgress(
|
|
cotisationId: event.cotisationId,
|
|
paymentId: payment.id,
|
|
methodePaiement: event.methodePaiement,
|
|
montant: event.montant,
|
|
));
|
|
|
|
} catch (e) {
|
|
emit(PaymentFailure(
|
|
cotisationId: event.cotisationId,
|
|
paymentId: '',
|
|
errorMessage: e.toString(),
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Handler pour vérifier le statut d'un paiement
|
|
Future<void> _onCheckPaymentStatus(
|
|
CheckPaymentStatus event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
final payment = await _paymentService.checkPaymentStatus(event.paymentId);
|
|
|
|
if (payment.isSuccessful) {
|
|
// Récupérer la cotisation mise à jour
|
|
final cotisation = await _cotisationRepository.getCotisationById(payment.cotisationId);
|
|
|
|
emit(PaymentSuccess(
|
|
cotisationId: payment.cotisationId,
|
|
payment: payment,
|
|
updatedCotisation: cotisation,
|
|
));
|
|
|
|
// Envoyer notification de succès
|
|
await _notificationService.showPaymentConfirmation(cotisation, payment.montant);
|
|
|
|
} else if (payment.isFailed) {
|
|
emit(PaymentFailure(
|
|
cotisationId: payment.cotisationId,
|
|
paymentId: payment.id,
|
|
errorMessage: payment.messageErreur ?? 'Paiement échoué',
|
|
));
|
|
|
|
// Envoyer notification d'échec
|
|
final cotisation = await _cotisationRepository.getCotisationById(payment.cotisationId);
|
|
await _notificationService.showPaymentFailure(cotisation, payment.messageErreur ?? 'Erreur inconnue');
|
|
}
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de la vérification du paiement: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Handler pour annuler un paiement
|
|
Future<void> _onCancelPayment(
|
|
CancelPayment event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
final cancelled = await _paymentService.cancelPayment(event.paymentId);
|
|
|
|
if (cancelled) {
|
|
emit(PaymentCancelled(
|
|
cotisationId: event.cotisationId,
|
|
paymentId: event.paymentId,
|
|
));
|
|
} else {
|
|
emit(const CotisationsError('Impossible d\'annuler le paiement'));
|
|
}
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de l\'annulation du paiement: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Handler pour programmer les notifications
|
|
Future<void> _onScheduleNotifications(
|
|
ScheduleNotifications event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
await _notificationService.scheduleAllCotisationsNotifications(event.cotisations);
|
|
|
|
emit(NotificationsScheduled(
|
|
notificationsCount: event.cotisations.length * 2,
|
|
cotisationIds: event.cotisations.map((c) => c.id).toList(),
|
|
));
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de la programmation des notifications: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Handler pour synchroniser avec le serveur
|
|
Future<void> _onSyncWithServer(
|
|
SyncWithServer event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const SyncInProgress('Synchronisation en cours...'));
|
|
|
|
// Recharger les données
|
|
final cotisations = await _cotisationRepository.getCotisations();
|
|
|
|
emit(SyncCompleted(
|
|
itemsSynced: cotisations.length,
|
|
syncTime: DateTime.now(),
|
|
));
|
|
|
|
// Émettre l'état chargé avec les nouvelles données
|
|
emit(CotisationsLoaded(
|
|
cotisations: cotisations,
|
|
filteredCotisations: cotisations,
|
|
));
|
|
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de la synchronisation: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Handler pour appliquer des filtres avancés
|
|
Future<void> _onApplyAdvancedFilters(
|
|
ApplyAdvancedFilters event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const CotisationsLoading());
|
|
|
|
final cotisations = await _cotisationRepository.rechercherCotisations(
|
|
membreId: event.filters['membreId'],
|
|
statut: event.filters['statut'],
|
|
typeCotisation: event.filters['typeCotisation'],
|
|
annee: event.filters['annee'],
|
|
mois: event.filters['mois'],
|
|
);
|
|
|
|
emit(CotisationsSearchResults(
|
|
cotisations: cotisations,
|
|
searchCriteria: event.filters,
|
|
));
|
|
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de l\'application des filtres: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Handler pour exporter les cotisations
|
|
Future<void> _onExportCotisations(
|
|
ExportCotisations event,
|
|
Emitter<CotisationsState> emit,
|
|
) async {
|
|
try {
|
|
final cotisations = event.cotisations ?? [];
|
|
|
|
emit(ExportInProgress(
|
|
format: event.format,
|
|
totalItems: cotisations.length,
|
|
));
|
|
|
|
// TODO: Implémenter l'export réel selon le format
|
|
await Future.delayed(const Duration(seconds: 2)); // Simulation
|
|
|
|
emit(ExportCompleted(
|
|
format: event.format,
|
|
filePath: '/storage/emulated/0/Download/cotisations.${event.format}',
|
|
itemsExported: cotisations.length,
|
|
));
|
|
|
|
} catch (e) {
|
|
emit(CotisationsError('Erreur lors de l\'export: ${e.toString()}'));
|
|
}
|
|
}
|
|
}
|