Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
367
lib/features/contributions/bloc/contributions_bloc.dart
Normal file
367
lib/features/contributions/bloc/contributions_bloc.dart
Normal file
@@ -0,0 +1,367 @@
|
||||
/// BLoC pour la gestion des contributions
|
||||
library contributions_bloc;
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import '../../../core/utils/logger.dart';
|
||||
import '../data/models/contribution_model.dart';
|
||||
import '../data/repositories/contribution_repository.dart' show ContributionPageResult;
|
||||
import '../domain/usecases/get_contributions.dart';
|
||||
import '../domain/usecases/get_contribution_by_id.dart';
|
||||
import '../domain/usecases/create_contribution.dart' as uc;
|
||||
import '../domain/usecases/update_contribution.dart' as uc;
|
||||
import '../domain/usecases/delete_contribution.dart' as uc;
|
||||
import '../domain/usecases/pay_contribution.dart';
|
||||
import '../domain/usecases/get_contribution_stats.dart';
|
||||
import '../domain/repositories/contribution_repository.dart';
|
||||
import 'contributions_event.dart';
|
||||
import 'contributions_state.dart';
|
||||
|
||||
/// BLoC pour gérer l'état des contributions via les use cases (Clean Architecture)
|
||||
@injectable
|
||||
class ContributionsBloc extends Bloc<ContributionsEvent, ContributionsState> {
|
||||
final GetContributions _getContributions;
|
||||
final GetContributionById _getContributionById;
|
||||
final uc.CreateContribution _createContribution;
|
||||
final uc.UpdateContribution _updateContribution;
|
||||
final uc.DeleteContribution _deleteContribution;
|
||||
final PayContribution _payContribution;
|
||||
final GetContributionStats _getContributionStats;
|
||||
final IContributionRepository _repository; // Pour méthodes non-couvertes par use cases
|
||||
|
||||
ContributionsBloc(
|
||||
this._getContributions,
|
||||
this._getContributionById,
|
||||
this._createContribution,
|
||||
this._updateContribution,
|
||||
this._deleteContribution,
|
||||
this._payContribution,
|
||||
this._getContributionStats,
|
||||
this._repository,
|
||||
) : super(const ContributionsInitial()) {
|
||||
on<LoadContributions>(_onLoadContributions);
|
||||
on<LoadContributionById>(_onLoadContributionById);
|
||||
on<CreateContribution>(_onCreateContribution);
|
||||
on<UpdateContribution>(_onUpdateContribution);
|
||||
on<DeleteContribution>(_onDeleteContribution);
|
||||
on<SearchContributions>(_onSearchContributions);
|
||||
on<LoadContributionsByMembre>(_onLoadContributionsByMembre);
|
||||
on<LoadContributionsPayees>(_onLoadContributionsPayees);
|
||||
on<LoadContributionsNonPayees>(_onLoadContributionsNonPayees);
|
||||
on<LoadContributionsEnRetard>(_onLoadContributionsEnRetard);
|
||||
on<RecordPayment>(_onRecordPayment);
|
||||
on<LoadContributionsStats>(_onLoadContributionsStats);
|
||||
on<GenerateAnnualContributions>(_onGenerateAnnualContributions);
|
||||
on<SendPaymentReminder>(_onSendPaymentReminder);
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributions(
|
||||
LoadContributions event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
AppLogger.blocEvent('ContributionsBloc', 'LoadContributions', data: {
|
||||
'page': event.page,
|
||||
'size': event.size,
|
||||
});
|
||||
|
||||
emit(const ContributionsLoading(message: 'Chargement des contributions...'));
|
||||
|
||||
// Use case: Get contributions
|
||||
final result = await _getContributions(page: event.page, size: event.size);
|
||||
|
||||
emit(ContributionsLoaded(
|
||||
contributions: result.contributions,
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
size: result.size,
|
||||
totalPages: result.totalPages,
|
||||
));
|
||||
|
||||
AppLogger.blocState('ContributionsBloc', 'ContributionsLoaded', data: {
|
||||
'count': result.contributions.length,
|
||||
'total': result.total,
|
||||
});
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur lors du chargement des contributions', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors du chargement des contributions', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionById(
|
||||
LoadContributionById event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Chargement de la contribution...'));
|
||||
final contribution = await _getContributionById(event.id);
|
||||
emit(ContributionDetailLoaded(contribution: contribution));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Contribution non trouvée', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onCreateContribution(
|
||||
CreateContribution event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Création de la contribution...'));
|
||||
final created = await _createContribution(event.contribution);
|
||||
emit(ContributionCreated(contribution: created));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors de la création de la contribution', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onUpdateContribution(
|
||||
UpdateContribution event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Mise à jour de la contribution...'));
|
||||
final updated = await _updateContribution(event.id, event.contribution);
|
||||
emit(ContributionUpdated(contribution: updated));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors de la mise à jour', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onDeleteContribution(
|
||||
DeleteContribution event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Suppression de la contribution...'));
|
||||
await _deleteContribution(event.id);
|
||||
emit(ContributionDeleted(id: event.id));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors de la suppression', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSearchContributions(
|
||||
SearchContributions event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Recherche en cours...'));
|
||||
|
||||
final result = await _repository.getCotisations(
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
membreId: event.membreId,
|
||||
statut: event.statut?.name,
|
||||
type: event.type?.name,
|
||||
annee: event.annee,
|
||||
);
|
||||
|
||||
emit(ContributionsLoaded(
|
||||
contributions: result.contributions,
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
size: result.size,
|
||||
totalPages: result.totalPages,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors de la recherche', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionsByMembre(
|
||||
LoadContributionsByMembre event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Chargement des contributions du membre...'));
|
||||
|
||||
final result = await _repository.getCotisations(
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
membreId: event.membreId,
|
||||
);
|
||||
|
||||
emit(ContributionsLoaded(
|
||||
contributions: result.contributions,
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
size: result.size,
|
||||
totalPages: result.totalPages,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors du chargement', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionsPayees(
|
||||
LoadContributionsPayees event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Chargement des contributions payées...'));
|
||||
final result = await _repository.getMesCotisations();
|
||||
final payees = result.contributions.where((c) => c.statut == ContributionStatus.payee).toList();
|
||||
emit(ContributionsLoaded(
|
||||
contributions: payees,
|
||||
total: payees.length,
|
||||
page: 0,
|
||||
size: payees.length,
|
||||
totalPages: payees.isEmpty ? 0 : 1,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionsNonPayees(
|
||||
LoadContributionsNonPayees event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Chargement des contributions non payées...'));
|
||||
final result = await _repository.getMesCotisations();
|
||||
final nonPayees = result.contributions.where((c) => c.statut != ContributionStatus.payee).toList();
|
||||
emit(ContributionsLoaded(
|
||||
contributions: nonPayees,
|
||||
total: nonPayees.length,
|
||||
page: 0,
|
||||
size: nonPayees.length,
|
||||
totalPages: nonPayees.isEmpty ? 0 : 1,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionsEnRetard(
|
||||
LoadContributionsEnRetard event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Chargement des contributions en retard...'));
|
||||
final result = await _repository.getMesCotisations();
|
||||
final enRetard = result.contributions.where((c) => c.statut == ContributionStatus.enRetard || c.estEnRetard).toList();
|
||||
emit(ContributionsLoaded(
|
||||
contributions: enRetard,
|
||||
total: enRetard.length,
|
||||
page: 0,
|
||||
size: enRetard.length,
|
||||
totalPages: enRetard.isEmpty ? 0 : 1,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onRecordPayment(
|
||||
RecordPayment event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Enregistrement du paiement...'));
|
||||
|
||||
final updated = await _payContribution(
|
||||
cotisationId: event.contributionId,
|
||||
montant: event.montant,
|
||||
datePaiement: event.datePaiement,
|
||||
methodePaiement: event.methodePaiement.name,
|
||||
numeroPaiement: event.numeroPaiement,
|
||||
referencePaiement: event.referencePaiement,
|
||||
);
|
||||
|
||||
emit(PaymentRecorded(contribution: updated));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur lors de l\'enregistrement du paiement', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadContributionsStats(
|
||||
LoadContributionsStats event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
List<ContributionModel>? preservedList = state is ContributionsLoaded ? (state as ContributionsLoaded).contributions : null;
|
||||
try {
|
||||
// Charger synthèse + liste pour que la page « Mes statistiques » ait toujours donut et prochaines échéances
|
||||
final mesSynthese = await _getContributionStats();
|
||||
final listResult = preservedList == null ? await _getContributions() : null;
|
||||
final contributions = preservedList ?? listResult?.contributions;
|
||||
|
||||
if (mesSynthese != null && mesSynthese.isNotEmpty) {
|
||||
final normalized = _normalizeSyntheseForStats(mesSynthese);
|
||||
emit(ContributionsStatsLoaded(stats: normalized, contributions: contributions));
|
||||
return;
|
||||
}
|
||||
final stats = await _repository.getStatistiques();
|
||||
emit(ContributionsStatsLoaded(
|
||||
stats: stats.map((k, v) => MapEntry(k, v is num ? v.toDouble() : (v is int ? v.toDouble() : 0.0))),
|
||||
contributions: contributions,
|
||||
));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalise la réponse synthese (mes) pour l'affichage stats (clés numériques + isMesSynthese).
|
||||
Map<String, dynamic> _normalizeSyntheseForStats(Map<String, dynamic> s) {
|
||||
final montantDu = _toDouble(s['montantDu']);
|
||||
final totalPayeAnnee = _toDouble(s['totalPayeAnnee']);
|
||||
final totalAnnee = montantDu + totalPayeAnnee;
|
||||
final taux = totalAnnee > 0 ? (totalPayeAnnee / totalAnnee * 100) : 0.0;
|
||||
return {
|
||||
'isMesSynthese': true,
|
||||
'cotisationsEnAttente': (s['cotisationsEnAttente'] is int) ? s['cotisationsEnAttente'] as int : ((s['cotisationsEnAttente'] as num?)?.toInt() ?? 0),
|
||||
'montantDu': montantDu,
|
||||
'totalPayeAnnee': totalPayeAnnee,
|
||||
'totalMontant': totalAnnee,
|
||||
'tauxPaiement': taux,
|
||||
'prochaineEcheance': s['prochaineEcheance']?.toString(),
|
||||
'anneeEnCours': s['anneeEnCours'] is int ? s['anneeEnCours'] as int : ((s['anneeEnCours'] as num?)?.toInt() ?? DateTime.now().year),
|
||||
};
|
||||
}
|
||||
|
||||
double _toDouble(dynamic v) {
|
||||
if (v == null) return 0;
|
||||
if (v is num) return v.toDouble();
|
||||
if (v is String) return double.tryParse(v) ?? 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Future<void> _onGenerateAnnualContributions(
|
||||
GenerateAnnualContributions event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Génération des contributions...'));
|
||||
final count = await _repository.genererCotisationsAnnuelles(event.annee);
|
||||
emit(ContributionsGenerated(nombreGenere: count));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSendPaymentReminder(
|
||||
SendPaymentReminder event,
|
||||
Emitter<ContributionsState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(const ContributionsLoading(message: 'Envoi du rappel...'));
|
||||
await _repository.envoyerRappel(event.contributionId);
|
||||
emit(ReminderSent(contributionId: event.contributionId));
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error('Erreur', error: e, stackTrace: stackTrace);
|
||||
emit(ContributionsError(message: 'Erreur', error: e));
|
||||
}
|
||||
}
|
||||
}
|
||||
225
lib/features/contributions/bloc/contributions_event.dart
Normal file
225
lib/features/contributions/bloc/contributions_event.dart
Normal file
@@ -0,0 +1,225 @@
|
||||
/// Événements pour le BLoC des contributions
|
||||
library contributions_event;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/contribution_model.dart';
|
||||
|
||||
/// Classe de base pour tous les événements de contributions
|
||||
abstract class ContributionsEvent extends Equatable {
|
||||
const ContributionsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Charger la liste des contributions
|
||||
class LoadContributions extends ContributionsEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadContributions({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Charger une contribution par ID
|
||||
class LoadContributionById extends ContributionsEvent {
|
||||
final String id;
|
||||
|
||||
const LoadContributionById({required this.id});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Créer une nouvelle contribution
|
||||
class CreateContribution extends ContributionsEvent {
|
||||
final ContributionModel contribution;
|
||||
|
||||
const CreateContribution({required this.contribution});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contribution];
|
||||
}
|
||||
|
||||
/// Mettre à jour une contribution
|
||||
class UpdateContribution extends ContributionsEvent {
|
||||
final String id;
|
||||
final ContributionModel contribution;
|
||||
|
||||
const UpdateContribution({
|
||||
required this.id,
|
||||
required this.contribution,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, contribution];
|
||||
}
|
||||
|
||||
/// Supprimer une contribution
|
||||
class DeleteContribution extends ContributionsEvent {
|
||||
final String id;
|
||||
|
||||
const DeleteContribution({required this.id});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Rechercher des contributions
|
||||
class SearchContributions extends ContributionsEvent {
|
||||
final String? membreId;
|
||||
final ContributionStatus? statut;
|
||||
final ContributionType? type;
|
||||
final int? annee;
|
||||
final String? query;
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const SearchContributions({
|
||||
this.membreId,
|
||||
this.statut,
|
||||
this.type,
|
||||
this.annee,
|
||||
this.query,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membreId, statut, type, annee, query, page, size];
|
||||
}
|
||||
|
||||
/// Charger les contributions d'un membre
|
||||
class LoadContributionsByMembre extends ContributionsEvent {
|
||||
final String membreId;
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadContributionsByMembre({
|
||||
required this.membreId,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membreId, page, size];
|
||||
}
|
||||
|
||||
/// Charger les contributions payées
|
||||
class LoadContributionsPayees extends ContributionsEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadContributionsPayees({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Charger les contributions non payées
|
||||
class LoadContributionsNonPayees extends ContributionsEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadContributionsNonPayees({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Charger les contributions en retard
|
||||
class LoadContributionsEnRetard extends ContributionsEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadContributionsEnRetard({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Enregistrer un paiement
|
||||
class RecordPayment extends ContributionsEvent {
|
||||
final String contributionId;
|
||||
final double montant;
|
||||
final PaymentMethod methodePaiement;
|
||||
final String? numeroPaiement;
|
||||
final String? referencePaiement;
|
||||
final DateTime datePaiement;
|
||||
final String? notes;
|
||||
final String? reference;
|
||||
|
||||
const RecordPayment({
|
||||
required this.contributionId,
|
||||
required this.montant,
|
||||
required this.methodePaiement,
|
||||
this.numeroPaiement,
|
||||
this.referencePaiement,
|
||||
required this.datePaiement,
|
||||
this.notes,
|
||||
this.reference,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
contributionId,
|
||||
montant,
|
||||
methodePaiement,
|
||||
numeroPaiement,
|
||||
referencePaiement,
|
||||
datePaiement,
|
||||
notes,
|
||||
reference,
|
||||
];
|
||||
}
|
||||
|
||||
/// Charger les statistiques des contributions
|
||||
class LoadContributionsStats extends ContributionsEvent {
|
||||
final int? annee;
|
||||
|
||||
const LoadContributionsStats({this.annee});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [annee];
|
||||
}
|
||||
|
||||
/// Générer les contributions annuelles
|
||||
class GenerateAnnualContributions extends ContributionsEvent {
|
||||
final int annee;
|
||||
final double montant;
|
||||
final DateTime dateEcheance;
|
||||
|
||||
const GenerateAnnualContributions({
|
||||
required this.annee,
|
||||
required this.montant,
|
||||
required this.dateEcheance,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [annee, montant, dateEcheance];
|
||||
}
|
||||
|
||||
/// Envoyer un rappel de paiement
|
||||
class SendPaymentReminder extends ContributionsEvent {
|
||||
final String contributionId;
|
||||
|
||||
const SendPaymentReminder({required this.contributionId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contributionId];
|
||||
}
|
||||
|
||||
174
lib/features/contributions/bloc/contributions_state.dart
Normal file
174
lib/features/contributions/bloc/contributions_state.dart
Normal file
@@ -0,0 +1,174 @@
|
||||
/// États pour le BLoC des contributions
|
||||
library contributions_state;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/contribution_model.dart';
|
||||
|
||||
/// Classe de base pour tous les états de contributions
|
||||
abstract class ContributionsState extends Equatable {
|
||||
const ContributionsState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class ContributionsInitial extends ContributionsState {
|
||||
const ContributionsInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class ContributionsLoading extends ContributionsState {
|
||||
final String? message;
|
||||
|
||||
const ContributionsLoading({this.message});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
}
|
||||
|
||||
/// État de rafraîchissement
|
||||
class ContributionsRefreshing extends ContributionsState {
|
||||
const ContributionsRefreshing();
|
||||
}
|
||||
|
||||
/// État chargé avec succès
|
||||
class ContributionsLoaded extends ContributionsState {
|
||||
final List<ContributionModel> contributions;
|
||||
final int total;
|
||||
final int page;
|
||||
final int size;
|
||||
final int totalPages;
|
||||
|
||||
const ContributionsLoaded({
|
||||
required this.contributions,
|
||||
required this.total,
|
||||
required this.page,
|
||||
required this.size,
|
||||
required this.totalPages,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contributions, total, page, size, totalPages];
|
||||
}
|
||||
|
||||
/// État détail d'une contribution chargé
|
||||
class ContributionDetailLoaded extends ContributionsState {
|
||||
final ContributionModel contribution;
|
||||
|
||||
const ContributionDetailLoaded({required this.contribution});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contribution];
|
||||
}
|
||||
|
||||
/// État contribution créée
|
||||
class ContributionCreated extends ContributionsState {
|
||||
final ContributionModel contribution;
|
||||
|
||||
const ContributionCreated({required this.contribution});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contribution];
|
||||
}
|
||||
|
||||
/// État contribution mise à jour
|
||||
class ContributionUpdated extends ContributionsState {
|
||||
final ContributionModel contribution;
|
||||
|
||||
const ContributionUpdated({required this.contribution});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contribution];
|
||||
}
|
||||
|
||||
/// État contribution supprimée
|
||||
class ContributionDeleted extends ContributionsState {
|
||||
final String id;
|
||||
|
||||
const ContributionDeleted({required this.id});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État paiement enregistré
|
||||
class PaymentRecorded extends ContributionsState {
|
||||
final ContributionModel contribution;
|
||||
|
||||
const PaymentRecorded({required this.contribution});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contribution];
|
||||
}
|
||||
|
||||
/// État statistiques chargées (liste optionnelle conservée pour ne pas perdre l'onglet Toutes au retour)
|
||||
class ContributionsStatsLoaded extends ContributionsState {
|
||||
final Map<String, dynamic> stats;
|
||||
/// Liste des contributions conservée depuis l'état précédent (ex: au retour de la page Stats).
|
||||
final List<ContributionModel>? contributions;
|
||||
|
||||
const ContributionsStatsLoaded({required this.stats, this.contributions});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [stats, contributions];
|
||||
}
|
||||
|
||||
/// État contributions générées
|
||||
class ContributionsGenerated extends ContributionsState {
|
||||
final int nombreGenere;
|
||||
|
||||
const ContributionsGenerated({required this.nombreGenere});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [nombreGenere];
|
||||
}
|
||||
|
||||
/// État rappel envoyé
|
||||
class ReminderSent extends ContributionsState {
|
||||
final String contributionId;
|
||||
|
||||
const ReminderSent({required this.contributionId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contributionId];
|
||||
}
|
||||
|
||||
/// État d'erreur générique
|
||||
class ContributionsError extends ContributionsState {
|
||||
final String message;
|
||||
final dynamic error;
|
||||
|
||||
const ContributionsError({
|
||||
required this.message,
|
||||
this.error,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, error];
|
||||
}
|
||||
|
||||
/// État d'erreur réseau
|
||||
class ContributionsNetworkError extends ContributionsState {
|
||||
final String message;
|
||||
|
||||
const ContributionsNetworkError({required this.message});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
}
|
||||
|
||||
/// État d'erreur de validation
|
||||
class ContributionsValidationError extends ContributionsState {
|
||||
final String message;
|
||||
final Map<String, String>? fieldErrors;
|
||||
|
||||
const ContributionsValidationError({
|
||||
required this.message,
|
||||
this.fieldErrors,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, fieldErrors];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user