446 lines
12 KiB
Dart
446 lines
12 KiB
Dart
/// BLoC pour la gestion des événements
|
|
library evenements_bloc;
|
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'evenements_event.dart';
|
|
import 'evenements_state.dart';
|
|
import '../data/repositories/evenement_repository_impl.dart';
|
|
|
|
/// BLoC pour la gestion des événements
|
|
class EvenementsBloc extends Bloc<EvenementsEvent, EvenementsState> {
|
|
final EvenementRepository _repository;
|
|
|
|
EvenementsBloc(this._repository) : super(const EvenementsInitial()) {
|
|
on<LoadEvenements>(_onLoadEvenements);
|
|
on<LoadEvenementById>(_onLoadEvenementById);
|
|
on<CreateEvenement>(_onCreateEvenement);
|
|
on<UpdateEvenement>(_onUpdateEvenement);
|
|
on<DeleteEvenement>(_onDeleteEvenement);
|
|
on<LoadEvenementsAVenir>(_onLoadEvenementsAVenir);
|
|
on<LoadEvenementsEnCours>(_onLoadEvenementsEnCours);
|
|
on<LoadEvenementsPasses>(_onLoadEvenementsPasses);
|
|
on<InscrireEvenement>(_onInscrireEvenement);
|
|
on<DesinscrireEvenement>(_onDesinscrireEvenement);
|
|
on<LoadParticipants>(_onLoadParticipants);
|
|
on<LoadEvenementsStats>(_onLoadEvenementsStats);
|
|
}
|
|
|
|
/// Charge la liste des événements
|
|
Future<void> _onLoadEvenements(
|
|
LoadEvenements event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
if (event.refresh && state is EvenementsLoaded) {
|
|
final currentState = state as EvenementsLoaded;
|
|
emit(EvenementsRefreshing(currentState.evenements));
|
|
} else {
|
|
emit(const EvenementsLoading());
|
|
}
|
|
|
|
final result = await _repository.getEvenements(
|
|
page: event.page,
|
|
size: event.size,
|
|
recherche: event.recherche,
|
|
);
|
|
|
|
emit(EvenementsLoaded(
|
|
evenements: result.evenements,
|
|
total: result.total,
|
|
page: result.page,
|
|
size: result.size,
|
|
totalPages: result.totalPages,
|
|
));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur inattendue lors du chargement des événements: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge un événement par ID
|
|
Future<void> _onLoadEvenementById(
|
|
LoadEvenementById event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final evenement = await _repository.getEvenementById(event.id);
|
|
|
|
if (evenement != null) {
|
|
emit(EvenementDetailLoaded(evenement));
|
|
} else {
|
|
emit(const EvenementsError(
|
|
message: 'Événement non trouvé',
|
|
code: '404',
|
|
));
|
|
}
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement de l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Crée un nouvel événement
|
|
Future<void> _onCreateEvenement(
|
|
CreateEvenement event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final evenement = await _repository.createEvenement(event.evenement);
|
|
|
|
emit(EvenementCreated(evenement));
|
|
} on DioException catch (e) {
|
|
if (e.response?.statusCode == 400) {
|
|
final errors = _extractValidationErrors(e.response?.data);
|
|
emit(EvenementsValidationError(
|
|
message: 'Erreur de validation',
|
|
validationErrors: errors,
|
|
code: '400',
|
|
));
|
|
} else {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
}
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors de la création de l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Met à jour un événement
|
|
Future<void> _onUpdateEvenement(
|
|
UpdateEvenement event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final evenement = await _repository.updateEvenement(event.id, event.evenement);
|
|
|
|
emit(EvenementUpdated(evenement));
|
|
} on DioException catch (e) {
|
|
if (e.response?.statusCode == 400) {
|
|
final errors = _extractValidationErrors(e.response?.data);
|
|
emit(EvenementsValidationError(
|
|
message: 'Erreur de validation',
|
|
validationErrors: errors,
|
|
code: '400',
|
|
));
|
|
} else {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
}
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors de la mise à jour de l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Supprime un événement
|
|
Future<void> _onDeleteEvenement(
|
|
DeleteEvenement event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
await _repository.deleteEvenement(event.id);
|
|
|
|
emit(EvenementDeleted(event.id));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors de la suppression de l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge les événements à venir
|
|
Future<void> _onLoadEvenementsAVenir(
|
|
LoadEvenementsAVenir event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final result = await _repository.getEvenementsAVenir(
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
emit(EvenementsLoaded(
|
|
evenements: result.evenements,
|
|
total: result.total,
|
|
page: result.page,
|
|
size: result.size,
|
|
totalPages: result.totalPages,
|
|
));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement des événements à venir: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge les événements en cours
|
|
Future<void> _onLoadEvenementsEnCours(
|
|
LoadEvenementsEnCours event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final result = await _repository.getEvenementsEnCours(
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
emit(EvenementsLoaded(
|
|
evenements: result.evenements,
|
|
total: result.total,
|
|
page: result.page,
|
|
size: result.size,
|
|
totalPages: result.totalPages,
|
|
));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement des événements en cours: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge les événements passés
|
|
Future<void> _onLoadEvenementsPasses(
|
|
LoadEvenementsPasses event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final result = await _repository.getEvenementsPasses(
|
|
page: event.page,
|
|
size: event.size,
|
|
);
|
|
|
|
emit(EvenementsLoaded(
|
|
evenements: result.evenements,
|
|
total: result.total,
|
|
page: result.page,
|
|
size: result.size,
|
|
totalPages: result.totalPages,
|
|
));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement des événements passés: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// S'inscrire à un événement
|
|
Future<void> _onInscrireEvenement(
|
|
InscrireEvenement event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
await _repository.inscrireEvenement(event.evenementId);
|
|
|
|
emit(EvenementInscrit(event.evenementId));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors de l\'inscription à l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Se désinscrire d'un événement
|
|
Future<void> _onDesinscrireEvenement(
|
|
DesinscrireEvenement event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
await _repository.desinscrireEvenement(event.evenementId);
|
|
|
|
emit(EvenementDesinscrit(event.evenementId));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors de la désinscription de l\'événement: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge les participants
|
|
Future<void> _onLoadParticipants(
|
|
LoadParticipants event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final participants = await _repository.getParticipants(event.evenementId);
|
|
|
|
emit(ParticipantsLoaded(
|
|
evenementId: event.evenementId,
|
|
participants: participants,
|
|
));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement des participants: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Charge les statistiques
|
|
Future<void> _onLoadEvenementsStats(
|
|
LoadEvenementsStats event,
|
|
Emitter<EvenementsState> emit,
|
|
) async {
|
|
try {
|
|
emit(const EvenementsLoading());
|
|
|
|
final stats = await _repository.getEvenementsStats();
|
|
|
|
emit(EvenementsStatsLoaded(stats));
|
|
} on DioException catch (e) {
|
|
emit(EvenementsNetworkError(
|
|
message: _getNetworkErrorMessage(e),
|
|
code: e.response?.statusCode.toString(),
|
|
error: e,
|
|
));
|
|
} catch (e) {
|
|
emit(EvenementsError(
|
|
message: 'Erreur lors du chargement des statistiques: $e',
|
|
error: e,
|
|
));
|
|
}
|
|
}
|
|
|
|
/// Extrait les erreurs de validation
|
|
Map<String, String> _extractValidationErrors(dynamic data) {
|
|
final errors = <String, String>{};
|
|
if (data is Map<String, dynamic> && data.containsKey('errors')) {
|
|
final errorsData = data['errors'];
|
|
if (errorsData is Map<String, dynamic>) {
|
|
errorsData.forEach((key, value) {
|
|
errors[key] = value.toString();
|
|
});
|
|
}
|
|
}
|
|
return errors;
|
|
}
|
|
|
|
/// Génère un message d'erreur réseau approprié
|
|
String _getNetworkErrorMessage(DioException e) {
|
|
switch (e.type) {
|
|
case DioExceptionType.connectionTimeout:
|
|
return 'Délai de connexion dépassé. Vérifiez votre connexion internet.';
|
|
case DioExceptionType.sendTimeout:
|
|
return 'Délai d\'envoi dépassé. Vérifiez votre connexion internet.';
|
|
case DioExceptionType.receiveTimeout:
|
|
return 'Délai de réception dépassé. Vérifiez votre connexion internet.';
|
|
case DioExceptionType.badResponse:
|
|
final statusCode = e.response?.statusCode;
|
|
if (statusCode == 401) {
|
|
return 'Non autorisé. Veuillez vous reconnecter.';
|
|
} else if (statusCode == 403) {
|
|
return 'Accès refusé. Vous n\'avez pas les permissions nécessaires.';
|
|
} else if (statusCode == 404) {
|
|
return 'Ressource non trouvée.';
|
|
} else if (statusCode == 409) {
|
|
return 'Conflit. Cette ressource existe déjà.';
|
|
} else if (statusCode != null && statusCode >= 500) {
|
|
return 'Erreur serveur. Veuillez réessayer plus tard.';
|
|
}
|
|
return 'Erreur lors de la communication avec le serveur.';
|
|
case DioExceptionType.cancel:
|
|
return 'Requête annulée.';
|
|
case DioExceptionType.unknown:
|
|
return 'Erreur de connexion. Vérifiez votre connexion internet.';
|
|
default:
|
|
return 'Erreur réseau inattendue.';
|
|
}
|
|
}
|
|
}
|
|
|