Refactoring - Version OK
This commit is contained in:
@@ -0,0 +1,488 @@
|
||||
/// BLoC pour la gestion des organisations
|
||||
library organizations_bloc;
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../data/models/organization_model.dart';
|
||||
import '../data/services/organization_service.dart';
|
||||
import 'organizations_event.dart';
|
||||
import 'organizations_state.dart';
|
||||
|
||||
/// BLoC principal pour la gestion des organisations
|
||||
class OrganizationsBloc extends Bloc<OrganizationsEvent, OrganizationsState> {
|
||||
final OrganizationService _organizationService;
|
||||
|
||||
OrganizationsBloc(this._organizationService) : super(const OrganizationsInitial()) {
|
||||
// Enregistrement des handlers d'événements
|
||||
on<LoadOrganizations>(_onLoadOrganizations);
|
||||
on<LoadMoreOrganizations>(_onLoadMoreOrganizations);
|
||||
on<SearchOrganizations>(_onSearchOrganizations);
|
||||
on<AdvancedSearchOrganizations>(_onAdvancedSearchOrganizations);
|
||||
on<LoadOrganizationById>(_onLoadOrganizationById);
|
||||
on<CreateOrganization>(_onCreateOrganization);
|
||||
on<UpdateOrganization>(_onUpdateOrganization);
|
||||
on<DeleteOrganization>(_onDeleteOrganization);
|
||||
on<ActivateOrganization>(_onActivateOrganization);
|
||||
on<FilterOrganizationsByStatus>(_onFilterOrganizationsByStatus);
|
||||
on<FilterOrganizationsByType>(_onFilterOrganizationsByType);
|
||||
on<SortOrganizations>(_onSortOrganizations);
|
||||
on<LoadOrganizationsStats>(_onLoadOrganizationsStats);
|
||||
on<ClearOrganizationsFilters>(_onClearOrganizationsFilters);
|
||||
on<RefreshOrganizations>(_onRefreshOrganizations);
|
||||
on<ResetOrganizationsState>(_onResetOrganizationsState);
|
||||
}
|
||||
|
||||
/// Charge la liste des organisations
|
||||
Future<void> _onLoadOrganizations(
|
||||
LoadOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (event.refresh || state is! OrganizationsLoaded) {
|
||||
emit(const OrganizationsLoading());
|
||||
}
|
||||
|
||||
final organizations = await _organizationService.getOrganizations(
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
recherche: event.recherche,
|
||||
);
|
||||
|
||||
emit(OrganizationsLoaded(
|
||||
organizations: organizations,
|
||||
filteredOrganizations: organizations,
|
||||
hasReachedMax: organizations.length < event.size,
|
||||
currentPage: event.page,
|
||||
currentSearch: event.recherche,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors du chargement des organisations',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charge plus d'organisations (pagination)
|
||||
Future<void> _onLoadMoreOrganizations(
|
||||
LoadMoreOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded || currentState.hasReachedMax) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit(OrganizationsLoadingMore(currentState.organizations));
|
||||
|
||||
try {
|
||||
final nextPage = currentState.currentPage + 1;
|
||||
final newOrganizations = await _organizationService.getOrganizations(
|
||||
page: nextPage,
|
||||
size: 20,
|
||||
recherche: currentState.currentSearch,
|
||||
);
|
||||
|
||||
final allOrganizations = [...currentState.organizations, ...newOrganizations];
|
||||
final filteredOrganizations = _applyCurrentFilters(allOrganizations, currentState);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
organizations: allOrganizations,
|
||||
filteredOrganizations: filteredOrganizations,
|
||||
hasReachedMax: newOrganizations.length < 20,
|
||||
currentPage: nextPage,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors du chargement de plus d\'organisations',
|
||||
details: e.toString(),
|
||||
previousOrganizations: currentState.organizations,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Recherche des organisations
|
||||
Future<void> _onSearchOrganizations(
|
||||
SearchOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded) {
|
||||
// Si pas encore chargé, charger avec recherche
|
||||
add(LoadOrganizations(recherche: event.query, refresh: true));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (event.query.isEmpty) {
|
||||
// Recherche vide, afficher toutes les organisations
|
||||
final filteredOrganizations = _applyCurrentFilters(
|
||||
currentState.organizations,
|
||||
currentState.copyWith(clearSearch: true),
|
||||
);
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: filteredOrganizations,
|
||||
clearSearch: true,
|
||||
));
|
||||
} else {
|
||||
// Recherche locale d'abord
|
||||
final localResults = _organizationService.searchLocal(
|
||||
currentState.organizations,
|
||||
event.query,
|
||||
);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: localResults,
|
||||
currentSearch: event.query,
|
||||
));
|
||||
|
||||
// Puis recherche serveur pour plus de résultats
|
||||
final serverResults = await _organizationService.getOrganizations(
|
||||
page: 0,
|
||||
size: 50,
|
||||
recherche: event.query,
|
||||
);
|
||||
|
||||
final filteredResults = _applyCurrentFilters(serverResults, currentState);
|
||||
emit(currentState.copyWith(
|
||||
organizations: serverResults,
|
||||
filteredOrganizations: filteredResults,
|
||||
currentSearch: event.query,
|
||||
currentPage: 0,
|
||||
hasReachedMax: true,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de la recherche',
|
||||
details: e.toString(),
|
||||
previousOrganizations: currentState.organizations,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Recherche avancée
|
||||
Future<void> _onAdvancedSearchOrganizations(
|
||||
AdvancedSearchOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(const OrganizationsLoading());
|
||||
|
||||
try {
|
||||
final organizations = await _organizationService.searchOrganizations(
|
||||
nom: event.nom,
|
||||
type: event.type,
|
||||
statut: event.statut,
|
||||
ville: event.ville,
|
||||
region: event.region,
|
||||
pays: event.pays,
|
||||
page: event.page,
|
||||
size: event.size,
|
||||
);
|
||||
|
||||
emit(OrganizationsLoaded(
|
||||
organizations: organizations,
|
||||
filteredOrganizations: organizations,
|
||||
hasReachedMax: organizations.length < event.size,
|
||||
currentPage: event.page,
|
||||
typeFilter: event.type,
|
||||
statusFilter: event.statut,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de la recherche avancée',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Charge une organisation par ID
|
||||
Future<void> _onLoadOrganizationById(
|
||||
LoadOrganizationById event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(OrganizationLoading(event.id));
|
||||
|
||||
try {
|
||||
final organization = await _organizationService.getOrganizationById(event.id);
|
||||
if (organization != null) {
|
||||
emit(OrganizationLoaded(organization));
|
||||
} else {
|
||||
emit(OrganizationError('Organisation non trouvée', organizationId: event.id));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationError(
|
||||
'Erreur lors du chargement de l\'organisation',
|
||||
organizationId: event.id,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Crée une nouvelle organisation
|
||||
Future<void> _onCreateOrganization(
|
||||
CreateOrganization event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(const OrganizationCreating());
|
||||
|
||||
try {
|
||||
final createdOrganization = await _organizationService.createOrganization(event.organization);
|
||||
emit(OrganizationCreated(createdOrganization));
|
||||
|
||||
// Recharger la liste si elle était déjà chargée
|
||||
if (state is OrganizationsLoaded) {
|
||||
add(const RefreshOrganizations());
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de la création de l\'organisation',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Met à jour une organisation
|
||||
Future<void> _onUpdateOrganization(
|
||||
UpdateOrganization event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(OrganizationUpdating(event.id));
|
||||
|
||||
try {
|
||||
final updatedOrganization = await _organizationService.updateOrganization(
|
||||
event.id,
|
||||
event.organization,
|
||||
);
|
||||
emit(OrganizationUpdated(updatedOrganization));
|
||||
|
||||
// Mettre à jour la liste si elle était déjà chargée
|
||||
final currentState = state;
|
||||
if (currentState is OrganizationsLoaded) {
|
||||
final updatedList = currentState.organizations.map((org) {
|
||||
return org.id == event.id ? updatedOrganization : org;
|
||||
}).toList();
|
||||
|
||||
final filteredList = _applyCurrentFilters(updatedList, currentState);
|
||||
emit(currentState.copyWith(
|
||||
organizations: updatedList,
|
||||
filteredOrganizations: filteredList,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de la mise à jour de l\'organisation',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Supprime une organisation
|
||||
Future<void> _onDeleteOrganization(
|
||||
DeleteOrganization event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(OrganizationDeleting(event.id));
|
||||
|
||||
try {
|
||||
await _organizationService.deleteOrganization(event.id);
|
||||
emit(OrganizationDeleted(event.id));
|
||||
|
||||
// Retirer de la liste si elle était déjà chargée
|
||||
final currentState = state;
|
||||
if (currentState is OrganizationsLoaded) {
|
||||
final updatedList = currentState.organizations.where((org) => org.id != event.id).toList();
|
||||
final filteredList = _applyCurrentFilters(updatedList, currentState);
|
||||
emit(currentState.copyWith(
|
||||
organizations: updatedList,
|
||||
filteredOrganizations: filteredList,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de la suppression de l\'organisation',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Active une organisation
|
||||
Future<void> _onActivateOrganization(
|
||||
ActivateOrganization event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(OrganizationActivating(event.id));
|
||||
|
||||
try {
|
||||
final activatedOrganization = await _organizationService.activateOrganization(event.id);
|
||||
emit(OrganizationActivated(activatedOrganization));
|
||||
|
||||
// Mettre à jour la liste si elle était déjà chargée
|
||||
final currentState = state;
|
||||
if (currentState is OrganizationsLoaded) {
|
||||
final updatedList = currentState.organizations.map((org) {
|
||||
return org.id == event.id ? activatedOrganization : org;
|
||||
}).toList();
|
||||
|
||||
final filteredList = _applyCurrentFilters(updatedList, currentState);
|
||||
emit(currentState.copyWith(
|
||||
organizations: updatedList,
|
||||
filteredOrganizations: filteredList,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(OrganizationsError(
|
||||
'Erreur lors de l\'activation de l\'organisation',
|
||||
details: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Filtre par statut
|
||||
void _onFilterOrganizationsByStatus(
|
||||
FilterOrganizationsByStatus event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded) return;
|
||||
|
||||
final filteredOrganizations = _applyCurrentFilters(
|
||||
currentState.organizations,
|
||||
currentState.copyWith(statusFilter: event.statut),
|
||||
);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: filteredOrganizations,
|
||||
statusFilter: event.statut,
|
||||
));
|
||||
}
|
||||
|
||||
/// Filtre par type
|
||||
void _onFilterOrganizationsByType(
|
||||
FilterOrganizationsByType event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded) return;
|
||||
|
||||
final filteredOrganizations = _applyCurrentFilters(
|
||||
currentState.organizations,
|
||||
currentState.copyWith(typeFilter: event.type),
|
||||
);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: filteredOrganizations,
|
||||
typeFilter: event.type,
|
||||
));
|
||||
}
|
||||
|
||||
/// Trie les organisations
|
||||
void _onSortOrganizations(
|
||||
SortOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded) return;
|
||||
|
||||
List<OrganizationModel> sortedOrganizations;
|
||||
switch (event.sortType) {
|
||||
case OrganizationSortType.name:
|
||||
sortedOrganizations = _organizationService.sortByName(
|
||||
currentState.filteredOrganizations,
|
||||
ascending: event.ascending,
|
||||
);
|
||||
break;
|
||||
case OrganizationSortType.creationDate:
|
||||
sortedOrganizations = _organizationService.sortByCreationDate(
|
||||
currentState.filteredOrganizations,
|
||||
ascending: event.ascending,
|
||||
);
|
||||
break;
|
||||
case OrganizationSortType.memberCount:
|
||||
sortedOrganizations = _organizationService.sortByMemberCount(
|
||||
currentState.filteredOrganizations,
|
||||
ascending: event.ascending,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
sortedOrganizations = currentState.filteredOrganizations;
|
||||
}
|
||||
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: sortedOrganizations,
|
||||
sortType: event.sortType,
|
||||
sortAscending: event.ascending,
|
||||
));
|
||||
}
|
||||
|
||||
/// Charge les statistiques
|
||||
Future<void> _onLoadOrganizationsStats(
|
||||
LoadOrganizationsStats event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) async {
|
||||
emit(const OrganizationsStatsLoading());
|
||||
|
||||
try {
|
||||
final stats = await _organizationService.getOrganizationsStats();
|
||||
emit(OrganizationsStatsLoaded(stats));
|
||||
} catch (e) {
|
||||
emit(const OrganizationsStatsError('Erreur lors du chargement des statistiques'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Efface les filtres
|
||||
void _onClearOrganizationsFilters(
|
||||
ClearOrganizationsFilters event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
final currentState = state;
|
||||
if (currentState is! OrganizationsLoaded) return;
|
||||
|
||||
emit(currentState.copyWith(
|
||||
filteredOrganizations: currentState.organizations,
|
||||
clearSearch: true,
|
||||
clearStatusFilter: true,
|
||||
clearTypeFilter: true,
|
||||
clearSort: true,
|
||||
));
|
||||
}
|
||||
|
||||
/// Rafraîchit les données
|
||||
void _onRefreshOrganizations(
|
||||
RefreshOrganizations event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
add(const LoadOrganizations(refresh: true));
|
||||
}
|
||||
|
||||
/// Remet à zéro l'état
|
||||
void _onResetOrganizationsState(
|
||||
ResetOrganizationsState event,
|
||||
Emitter<OrganizationsState> emit,
|
||||
) {
|
||||
emit(const OrganizationsInitial());
|
||||
}
|
||||
|
||||
/// Applique les filtres actuels à une liste d'organisations
|
||||
List<OrganizationModel> _applyCurrentFilters(
|
||||
List<OrganizationModel> organizations,
|
||||
OrganizationsLoaded state,
|
||||
) {
|
||||
var filtered = organizations;
|
||||
|
||||
// Filtre par recherche
|
||||
if (state.currentSearch?.isNotEmpty == true) {
|
||||
filtered = _organizationService.searchLocal(filtered, state.currentSearch!);
|
||||
}
|
||||
|
||||
// Filtre par statut
|
||||
if (state.statusFilter != null) {
|
||||
filtered = _organizationService.filterByStatus(filtered, state.statusFilter!);
|
||||
}
|
||||
|
||||
// Filtre par type
|
||||
if (state.typeFilter != null) {
|
||||
filtered = _organizationService.filterByType(filtered, state.typeFilter!);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/// Événements pour le BLoC des organisations
|
||||
library organizations_event;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/organization_model.dart';
|
||||
|
||||
/// Classe de base pour tous les événements des organisations
|
||||
abstract class OrganizationsEvent extends Equatable {
|
||||
const OrganizationsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Événement pour charger la liste des organisations
|
||||
class LoadOrganizations extends OrganizationsEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
final String? recherche;
|
||||
final bool refresh;
|
||||
|
||||
const LoadOrganizations({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.recherche,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, recherche, refresh];
|
||||
}
|
||||
|
||||
/// Événement pour charger plus d'organisations (pagination)
|
||||
class LoadMoreOrganizations extends OrganizationsEvent {
|
||||
const LoadMoreOrganizations();
|
||||
}
|
||||
|
||||
/// Événement pour rechercher des organisations
|
||||
class SearchOrganizations extends OrganizationsEvent {
|
||||
final String query;
|
||||
|
||||
const SearchOrganizations(this.query);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [query];
|
||||
}
|
||||
|
||||
/// Événement pour recherche avancée
|
||||
class AdvancedSearchOrganizations extends OrganizationsEvent {
|
||||
final String? nom;
|
||||
final TypeOrganization? type;
|
||||
final StatutOrganization? statut;
|
||||
final String? ville;
|
||||
final String? region;
|
||||
final String? pays;
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const AdvancedSearchOrganizations({
|
||||
this.nom,
|
||||
this.type,
|
||||
this.statut,
|
||||
this.ville,
|
||||
this.region,
|
||||
this.pays,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [nom, type, statut, ville, region, pays, page, size];
|
||||
}
|
||||
|
||||
/// Événement pour charger une organisation spécifique
|
||||
class LoadOrganizationById extends OrganizationsEvent {
|
||||
final String id;
|
||||
|
||||
const LoadOrganizationById(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour créer une nouvelle organisation
|
||||
class CreateOrganization extends OrganizationsEvent {
|
||||
final OrganizationModel organization;
|
||||
|
||||
const CreateOrganization(this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organization];
|
||||
}
|
||||
|
||||
/// Événement pour mettre à jour une organisation
|
||||
class UpdateOrganization extends OrganizationsEvent {
|
||||
final String id;
|
||||
final OrganizationModel organization;
|
||||
|
||||
const UpdateOrganization(this.id, this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, organization];
|
||||
}
|
||||
|
||||
/// Événement pour supprimer une organisation
|
||||
class DeleteOrganization extends OrganizationsEvent {
|
||||
final String id;
|
||||
|
||||
const DeleteOrganization(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour activer une organisation
|
||||
class ActivateOrganization extends OrganizationsEvent {
|
||||
final String id;
|
||||
|
||||
const ActivateOrganization(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour filtrer les organisations par statut
|
||||
class FilterOrganizationsByStatus extends OrganizationsEvent {
|
||||
final StatutOrganization? statut;
|
||||
|
||||
const FilterOrganizationsByStatus(this.statut);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [statut];
|
||||
}
|
||||
|
||||
/// Événement pour filtrer les organisations par type
|
||||
class FilterOrganizationsByType extends OrganizationsEvent {
|
||||
final TypeOrganization? type;
|
||||
|
||||
const FilterOrganizationsByType(this.type);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [type];
|
||||
}
|
||||
|
||||
/// Événement pour trier les organisations
|
||||
class SortOrganizations extends OrganizationsEvent {
|
||||
final OrganizationSortType sortType;
|
||||
final bool ascending;
|
||||
|
||||
const SortOrganizations(this.sortType, {this.ascending = true});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [sortType, ascending];
|
||||
}
|
||||
|
||||
/// Événement pour charger les statistiques des organisations
|
||||
class LoadOrganizationsStats extends OrganizationsEvent {
|
||||
const LoadOrganizationsStats();
|
||||
}
|
||||
|
||||
/// Événement pour effacer les filtres
|
||||
class ClearOrganizationsFilters extends OrganizationsEvent {
|
||||
const ClearOrganizationsFilters();
|
||||
}
|
||||
|
||||
/// Événement pour rafraîchir les données
|
||||
class RefreshOrganizations extends OrganizationsEvent {
|
||||
const RefreshOrganizations();
|
||||
}
|
||||
|
||||
/// Événement pour réinitialiser l'état
|
||||
class ResetOrganizationsState extends OrganizationsEvent {
|
||||
const ResetOrganizationsState();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
/// États pour le BLoC des organisations
|
||||
library organizations_state;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/organization_model.dart';
|
||||
|
||||
/// Classe de base pour tous les états des organisations
|
||||
abstract class OrganizationsState extends Equatable {
|
||||
const OrganizationsState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class OrganizationsInitial extends OrganizationsState {
|
||||
const OrganizationsInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class OrganizationsLoading extends OrganizationsState {
|
||||
const OrganizationsLoading();
|
||||
}
|
||||
|
||||
/// État de chargement de plus d'éléments (pagination)
|
||||
class OrganizationsLoadingMore extends OrganizationsState {
|
||||
final List<OrganizationModel> currentOrganizations;
|
||||
|
||||
const OrganizationsLoadingMore(this.currentOrganizations);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [currentOrganizations];
|
||||
}
|
||||
|
||||
/// État de succès avec données
|
||||
class OrganizationsLoaded extends OrganizationsState {
|
||||
final List<OrganizationModel> organizations;
|
||||
final List<OrganizationModel> filteredOrganizations;
|
||||
final bool hasReachedMax;
|
||||
final int currentPage;
|
||||
final String? currentSearch;
|
||||
final StatutOrganization? statusFilter;
|
||||
final TypeOrganization? typeFilter;
|
||||
final OrganizationSortType? sortType;
|
||||
final bool sortAscending;
|
||||
final Map<String, dynamic>? stats;
|
||||
|
||||
const OrganizationsLoaded({
|
||||
required this.organizations,
|
||||
required this.filteredOrganizations,
|
||||
this.hasReachedMax = false,
|
||||
this.currentPage = 0,
|
||||
this.currentSearch,
|
||||
this.statusFilter,
|
||||
this.typeFilter,
|
||||
this.sortType,
|
||||
this.sortAscending = true,
|
||||
this.stats,
|
||||
});
|
||||
|
||||
/// Copie avec modifications
|
||||
OrganizationsLoaded copyWith({
|
||||
List<OrganizationModel>? organizations,
|
||||
List<OrganizationModel>? filteredOrganizations,
|
||||
bool? hasReachedMax,
|
||||
int? currentPage,
|
||||
String? currentSearch,
|
||||
StatutOrganization? statusFilter,
|
||||
TypeOrganization? typeFilter,
|
||||
OrganizationSortType? sortType,
|
||||
bool? sortAscending,
|
||||
Map<String, dynamic>? stats,
|
||||
bool clearSearch = false,
|
||||
bool clearStatusFilter = false,
|
||||
bool clearTypeFilter = false,
|
||||
bool clearSort = false,
|
||||
}) {
|
||||
return OrganizationsLoaded(
|
||||
organizations: organizations ?? this.organizations,
|
||||
filteredOrganizations: filteredOrganizations ?? this.filteredOrganizations,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
currentSearch: clearSearch ? null : (currentSearch ?? this.currentSearch),
|
||||
statusFilter: clearStatusFilter ? null : (statusFilter ?? this.statusFilter),
|
||||
typeFilter: clearTypeFilter ? null : (typeFilter ?? this.typeFilter),
|
||||
sortType: clearSort ? null : (sortType ?? this.sortType),
|
||||
sortAscending: sortAscending ?? this.sortAscending,
|
||||
stats: stats ?? this.stats,
|
||||
);
|
||||
}
|
||||
|
||||
/// Nombre total d'organisations
|
||||
int get totalCount => organizations.length;
|
||||
|
||||
/// Nombre d'organisations filtrées
|
||||
int get filteredCount => filteredOrganizations.length;
|
||||
|
||||
/// Indique si des filtres sont appliqués
|
||||
bool get hasFilters =>
|
||||
currentSearch?.isNotEmpty == true ||
|
||||
statusFilter != null ||
|
||||
typeFilter != null;
|
||||
|
||||
/// Indique si un tri est appliqué
|
||||
bool get hasSorting => sortType != null;
|
||||
|
||||
/// Statistiques rapides
|
||||
Map<String, int> get quickStats {
|
||||
final actives = organizations.where((org) => org.statut == StatutOrganization.active).length;
|
||||
final inactives = organizations.length - actives;
|
||||
final totalMembres = organizations.fold<int>(0, (sum, org) => sum + org.nombreMembres);
|
||||
|
||||
return {
|
||||
'total': organizations.length,
|
||||
'actives': actives,
|
||||
'inactives': inactives,
|
||||
'totalMembres': totalMembres,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
organizations,
|
||||
filteredOrganizations,
|
||||
hasReachedMax,
|
||||
currentPage,
|
||||
currentSearch,
|
||||
statusFilter,
|
||||
typeFilter,
|
||||
sortType,
|
||||
sortAscending,
|
||||
stats,
|
||||
];
|
||||
}
|
||||
|
||||
/// État d'erreur
|
||||
class OrganizationsError extends OrganizationsState {
|
||||
final String message;
|
||||
final String? details;
|
||||
final List<OrganizationModel>? previousOrganizations;
|
||||
|
||||
const OrganizationsError(
|
||||
this.message, {
|
||||
this.details,
|
||||
this.previousOrganizations,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, details, previousOrganizations];
|
||||
}
|
||||
|
||||
/// État de chargement d'une organisation spécifique
|
||||
class OrganizationLoading extends OrganizationsState {
|
||||
final String id;
|
||||
|
||||
const OrganizationLoading(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État d'organisation chargée
|
||||
class OrganizationLoaded extends OrganizationsState {
|
||||
final OrganizationModel organization;
|
||||
|
||||
const OrganizationLoaded(this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organization];
|
||||
}
|
||||
|
||||
/// État d'erreur pour une organisation spécifique
|
||||
class OrganizationError extends OrganizationsState {
|
||||
final String message;
|
||||
final String? organizationId;
|
||||
|
||||
const OrganizationError(this.message, {this.organizationId});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, organizationId];
|
||||
}
|
||||
|
||||
/// État de création d'organisation
|
||||
class OrganizationCreating extends OrganizationsState {
|
||||
const OrganizationCreating();
|
||||
}
|
||||
|
||||
/// État de succès de création
|
||||
class OrganizationCreated extends OrganizationsState {
|
||||
final OrganizationModel organization;
|
||||
|
||||
const OrganizationCreated(this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organization];
|
||||
}
|
||||
|
||||
/// État de mise à jour d'organisation
|
||||
class OrganizationUpdating extends OrganizationsState {
|
||||
final String id;
|
||||
|
||||
const OrganizationUpdating(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État de succès de mise à jour
|
||||
class OrganizationUpdated extends OrganizationsState {
|
||||
final OrganizationModel organization;
|
||||
|
||||
const OrganizationUpdated(this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organization];
|
||||
}
|
||||
|
||||
/// État de suppression d'organisation
|
||||
class OrganizationDeleting extends OrganizationsState {
|
||||
final String id;
|
||||
|
||||
const OrganizationDeleting(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État de succès de suppression
|
||||
class OrganizationDeleted extends OrganizationsState {
|
||||
final String id;
|
||||
|
||||
const OrganizationDeleted(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État d'activation d'organisation
|
||||
class OrganizationActivating extends OrganizationsState {
|
||||
final String id;
|
||||
|
||||
const OrganizationActivating(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État de succès d'activation
|
||||
class OrganizationActivated extends OrganizationsState {
|
||||
final OrganizationModel organization;
|
||||
|
||||
const OrganizationActivated(this.organization);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [organization];
|
||||
}
|
||||
|
||||
/// État de chargement des statistiques
|
||||
class OrganizationsStatsLoading extends OrganizationsState {
|
||||
const OrganizationsStatsLoading();
|
||||
}
|
||||
|
||||
/// État des statistiques chargées
|
||||
class OrganizationsStatsLoaded extends OrganizationsState {
|
||||
final Map<String, dynamic> stats;
|
||||
|
||||
const OrganizationsStatsLoaded(this.stats);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [stats];
|
||||
}
|
||||
|
||||
/// État d'erreur des statistiques
|
||||
class OrganizationsStatsError extends OrganizationsState {
|
||||
final String message;
|
||||
|
||||
const OrganizationsStatsError(this.message);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
}
|
||||
Reference in New Issue
Block a user