/// BLoC pour la gestion des membres library membres_bloc; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dio/dio.dart'; import 'membres_event.dart'; import 'membres_state.dart'; import '../data/repositories/membre_repository_impl.dart'; /// BLoC pour la gestion des membres class MembresBloc extends Bloc { final MembreRepository _repository; MembresBloc(this._repository) : super(const MembresInitial()) { on(_onLoadMembres); on(_onLoadMembreById); on(_onCreateMembre); on(_onUpdateMembre); on(_onDeleteMembre); on(_onActivateMembre); on(_onDeactivateMembre); on(_onSearchMembres); on(_onLoadActiveMembres); on(_onLoadBureauMembres); on(_onLoadMembresStats); } /// Charge la liste des membres Future _onLoadMembres( LoadMembres event, Emitter emit, ) async { try { // Si refresh et qu'on a déjà des données, on garde l'état actuel if (event.refresh && state is MembresLoaded) { final currentState = state as MembresLoaded; emit(MembresRefreshing(currentState.membres)); } else { emit(const MembresLoading()); } final result = await _repository.getMembres( page: event.page, size: event.size, recherche: event.recherche, ); emit(MembresLoaded( membres: result.membres, totalElements: result.totalElements, currentPage: result.currentPage, pageSize: result.pageSize, totalPages: result.totalPages, )); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur inattendue lors du chargement des membres: $e', error: e, )); } } /// Charge un membre par ID Future _onLoadMembreById( LoadMembreById event, Emitter emit, ) async { try { emit(const MembresLoading()); final membre = await _repository.getMembreById(event.id); if (membre != null) { emit(MembreDetailLoaded(membre)); } else { emit(const MembresError( message: 'Membre non trouvé', code: '404', )); } } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors du chargement du membre: $e', error: e, )); } } /// Crée un nouveau membre Future _onCreateMembre( CreateMembre event, Emitter emit, ) async { try { emit(const MembresLoading()); final membre = await _repository.createMembre(event.membre); emit(MembreCreated(membre)); } on DioException catch (e) { if (e.response?.statusCode == 400) { // Erreur de validation final errors = _extractValidationErrors(e.response?.data); emit(MembresValidationError( message: 'Erreur de validation', validationErrors: errors, code: '400', )); } else { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } } catch (e) { emit(MembresError( message: 'Erreur lors de la création du membre: $e', error: e, )); } } /// Met à jour un membre Future _onUpdateMembre( UpdateMembre event, Emitter emit, ) async { try { emit(const MembresLoading()); final membre = await _repository.updateMembre(event.id, event.membre); emit(MembreUpdated(membre)); } on DioException catch (e) { if (e.response?.statusCode == 400) { final errors = _extractValidationErrors(e.response?.data); emit(MembresValidationError( message: 'Erreur de validation', validationErrors: errors, code: '400', )); } else { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } } catch (e) { emit(MembresError( message: 'Erreur lors de la mise à jour du membre: $e', error: e, )); } } /// Supprime un membre Future _onDeleteMembre( DeleteMembre event, Emitter emit, ) async { try { emit(const MembresLoading()); await _repository.deleteMembre(event.id); emit(MembreDeleted(event.id)); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors de la suppression du membre: $e', error: e, )); } } /// Active un membre Future _onActivateMembre( ActivateMembre event, Emitter emit, ) async { try { emit(const MembresLoading()); final membre = await _repository.activateMembre(event.id); emit(MembreActivated(membre)); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors de l\'activation du membre: $e', error: e, )); } } /// Désactive un membre Future _onDeactivateMembre( DeactivateMembre event, Emitter emit, ) async { try { emit(const MembresLoading()); final membre = await _repository.deactivateMembre(event.id); emit(MembreDeactivated(membre)); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors de la désactivation du membre: $e', error: e, )); } } /// Recherche avancée de membres Future _onSearchMembres( SearchMembres event, Emitter emit, ) async { try { emit(const MembresLoading()); final result = await _repository.searchMembres( criteria: event.criteria, page: event.page, size: event.size, ); emit(MembresLoaded( membres: result.membres, totalElements: result.totalElements, currentPage: result.currentPage, pageSize: result.pageSize, totalPages: result.totalPages, )); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors de la recherche de membres: $e', error: e, )); } } /// Charge les membres actifs Future _onLoadActiveMembres( LoadActiveMembres event, Emitter emit, ) async { try { emit(const MembresLoading()); final result = await _repository.getActiveMembers( page: event.page, size: event.size, ); emit(MembresLoaded( membres: result.membres, totalElements: result.totalElements, currentPage: result.currentPage, pageSize: result.pageSize, totalPages: result.totalPages, )); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors du chargement des membres actifs: $e', error: e, )); } } /// Charge les membres du bureau Future _onLoadBureauMembres( LoadBureauMembres event, Emitter emit, ) async { try { emit(const MembresLoading()); final result = await _repository.getBureauMembers( page: event.page, size: event.size, ); emit(MembresLoaded( membres: result.membres, totalElements: result.totalElements, currentPage: result.currentPage, pageSize: result.pageSize, totalPages: result.totalPages, )); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors du chargement des membres du bureau: $e', error: e, )); } } /// Charge les statistiques Future _onLoadMembresStats( LoadMembresStats event, Emitter emit, ) async { try { emit(const MembresLoading()); final stats = await _repository.getMembresStats(); emit(MembresStatsLoaded(stats)); } on DioException catch (e) { emit(MembresNetworkError( message: _getNetworkErrorMessage(e), code: e.response?.statusCode.toString(), error: e, )); } catch (e) { emit(MembresError( message: 'Erreur lors du chargement des statistiques: $e', error: e, )); } } /// Extrait les erreurs de validation de la réponse 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.'; } } }