/// 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 { final EvenementRepository _repository; EvenementsBloc(this._repository) : super(const EvenementsInitial()) { on(_onLoadEvenements); on(_onLoadEvenementById); on(_onCreateEvenement); on(_onUpdateEvenement); on(_onDeleteEvenement); on(_onLoadEvenementsAVenir); on(_onLoadEvenementsEnCours); on(_onLoadEvenementsPasses); on(_onInscrireEvenement); on(_onDesinscrireEvenement); on(_onLoadParticipants); on(_onLoadEvenementsStats); } /// Charge la liste des événements Future _onLoadEvenements( LoadEvenements event, Emitter 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 _onLoadEvenementById( LoadEvenementById event, Emitter 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 _onCreateEvenement( CreateEvenement event, Emitter 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 _onUpdateEvenement( UpdateEvenement event, Emitter 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 _onDeleteEvenement( DeleteEvenement event, Emitter 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 _onLoadEvenementsAVenir( LoadEvenementsAVenir event, Emitter 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 _onLoadEvenementsEnCours( LoadEvenementsEnCours event, Emitter 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 _onLoadEvenementsPasses( LoadEvenementsPasses event, Emitter 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 _onInscrireEvenement( InscrireEvenement event, Emitter 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 _onDesinscrireEvenement( DesinscrireEvenement event, Emitter 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 _onLoadParticipants( LoadParticipants event, Emitter 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 _onLoadEvenementsStats( LoadEvenementsStats event, Emitter 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 _extractValidationErrors(dynamic data) { final errors = {}; if (data is Map && data.containsKey('errors')) { final errorsData = data['errors']; if (errorsData is Map) { 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.'; } } }