Clean project: remove test files, debug logs, and add documentation
This commit is contained in:
@@ -0,0 +1,419 @@
|
||||
/// 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<MembresEvent, MembresState> {
|
||||
final MembreRepository _repository;
|
||||
|
||||
MembresBloc(this._repository) : super(const MembresInitial()) {
|
||||
on<LoadMembres>(_onLoadMembres);
|
||||
on<LoadMembreById>(_onLoadMembreById);
|
||||
on<CreateMembre>(_onCreateMembre);
|
||||
on<UpdateMembre>(_onUpdateMembre);
|
||||
on<DeleteMembre>(_onDeleteMembre);
|
||||
on<ActivateMembre>(_onActivateMembre);
|
||||
on<DeactivateMembre>(_onDeactivateMembre);
|
||||
on<SearchMembres>(_onSearchMembres);
|
||||
on<LoadActiveMembres>(_onLoadActiveMembres);
|
||||
on<LoadBureauMembres>(_onLoadBureauMembres);
|
||||
on<LoadMembresStats>(_onLoadMembresStats);
|
||||
}
|
||||
|
||||
/// Charge la liste des membres
|
||||
Future<void> _onLoadMembres(
|
||||
LoadMembres event,
|
||||
Emitter<MembresState> 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<void> _onLoadMembreById(
|
||||
LoadMembreById event,
|
||||
Emitter<MembresState> 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<void> _onCreateMembre(
|
||||
CreateMembre event,
|
||||
Emitter<MembresState> 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<void> _onUpdateMembre(
|
||||
UpdateMembre event,
|
||||
Emitter<MembresState> 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<void> _onDeleteMembre(
|
||||
DeleteMembre event,
|
||||
Emitter<MembresState> 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<void> _onActivateMembre(
|
||||
ActivateMembre event,
|
||||
Emitter<MembresState> 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<void> _onDeactivateMembre(
|
||||
DeactivateMembre event,
|
||||
Emitter<MembresState> 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<void> _onSearchMembres(
|
||||
SearchMembres event,
|
||||
Emitter<MembresState> 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<void> _onLoadActiveMembres(
|
||||
LoadActiveMembres event,
|
||||
Emitter<MembresState> 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<void> _onLoadBureauMembres(
|
||||
LoadBureauMembres event,
|
||||
Emitter<MembresState> 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<void> _onLoadMembresStats(
|
||||
LoadMembresStats event,
|
||||
Emitter<MembresState> 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<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.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/// Événements pour le BLoC des membres
|
||||
library membres_event;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/membre_complete_model.dart';
|
||||
import '../../../core/models/membre_search_criteria.dart';
|
||||
|
||||
/// Classe de base pour tous les événements des membres
|
||||
abstract class MembresEvent extends Equatable {
|
||||
const MembresEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Événement pour charger la liste des membres
|
||||
class LoadMembres extends MembresEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
final String? recherche;
|
||||
final bool refresh;
|
||||
|
||||
const LoadMembres({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.recherche,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, recherche, refresh];
|
||||
}
|
||||
|
||||
/// Événement pour charger un membre par ID
|
||||
class LoadMembreById extends MembresEvent {
|
||||
final String id;
|
||||
|
||||
const LoadMembreById(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour créer un nouveau membre
|
||||
class CreateMembre extends MembresEvent {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const CreateMembre(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// Événement pour mettre à jour un membre
|
||||
class UpdateMembre extends MembresEvent {
|
||||
final String id;
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const UpdateMembre(this.id, this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, membre];
|
||||
}
|
||||
|
||||
/// Événement pour supprimer un membre
|
||||
class DeleteMembre extends MembresEvent {
|
||||
final String id;
|
||||
|
||||
const DeleteMembre(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour activer un membre
|
||||
class ActivateMembre extends MembresEvent {
|
||||
final String id;
|
||||
|
||||
const ActivateMembre(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour désactiver un membre
|
||||
class DeactivateMembre extends MembresEvent {
|
||||
final String id;
|
||||
|
||||
const DeactivateMembre(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Événement pour recherche avancée
|
||||
class SearchMembres extends MembresEvent {
|
||||
final MembreSearchCriteria criteria;
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const SearchMembres({
|
||||
required this.criteria,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [criteria, page, size];
|
||||
}
|
||||
|
||||
/// Événement pour charger les membres actifs
|
||||
class LoadActiveMembres extends MembresEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadActiveMembres({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Événement pour charger les membres du bureau
|
||||
class LoadBureauMembres extends MembresEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
|
||||
const LoadBureauMembres({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size];
|
||||
}
|
||||
|
||||
/// Événement pour charger les statistiques
|
||||
class LoadMembresStats extends MembresEvent {
|
||||
const LoadMembresStats();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/// États pour le BLoC des membres
|
||||
library membres_state;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../data/models/membre_complete_model.dart';
|
||||
|
||||
/// Classe de base pour tous les états des membres
|
||||
abstract class MembresState extends Equatable {
|
||||
const MembresState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// État initial
|
||||
class MembresInitial extends MembresState {
|
||||
const MembresInitial();
|
||||
}
|
||||
|
||||
/// État de chargement
|
||||
class MembresLoading extends MembresState {
|
||||
const MembresLoading();
|
||||
}
|
||||
|
||||
/// État de chargement avec données existantes (pour refresh)
|
||||
class MembresRefreshing extends MembresState {
|
||||
final List<MembreCompletModel> currentMembres;
|
||||
|
||||
const MembresRefreshing(this.currentMembres);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [currentMembres];
|
||||
}
|
||||
|
||||
/// État de succès avec liste de membres
|
||||
class MembresLoaded extends MembresState {
|
||||
final List<MembreCompletModel> membres;
|
||||
final int totalElements;
|
||||
final int currentPage;
|
||||
final int pageSize;
|
||||
final int totalPages;
|
||||
final bool hasMore;
|
||||
|
||||
const MembresLoaded({
|
||||
required this.membres,
|
||||
required this.totalElements,
|
||||
this.currentPage = 0,
|
||||
this.pageSize = 20,
|
||||
required this.totalPages,
|
||||
}) : hasMore = currentPage < totalPages - 1;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membres, totalElements, currentPage, pageSize, totalPages, hasMore];
|
||||
|
||||
MembresLoaded copyWith({
|
||||
List<MembreCompletModel>? membres,
|
||||
int? totalElements,
|
||||
int? currentPage,
|
||||
int? pageSize,
|
||||
int? totalPages,
|
||||
}) {
|
||||
return MembresLoaded(
|
||||
membres: membres ?? this.membres,
|
||||
totalElements: totalElements ?? this.totalElements,
|
||||
currentPage: currentPage ?? this.currentPage,
|
||||
pageSize: pageSize ?? this.pageSize,
|
||||
totalPages: totalPages ?? this.totalPages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// État de succès avec un seul membre
|
||||
class MembreDetailLoaded extends MembresState {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const MembreDetailLoaded(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// État de succès après création
|
||||
class MembreCreated extends MembresState {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const MembreCreated(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// État de succès après mise à jour
|
||||
class MembreUpdated extends MembresState {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const MembreUpdated(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// État de succès après suppression
|
||||
class MembreDeleted extends MembresState {
|
||||
final String id;
|
||||
|
||||
const MembreDeleted(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// État de succès après activation
|
||||
class MembreActivated extends MembresState {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const MembreActivated(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// État de succès après désactivation
|
||||
class MembreDeactivated extends MembresState {
|
||||
final MembreCompletModel membre;
|
||||
|
||||
const MembreDeactivated(this.membre);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [membre];
|
||||
}
|
||||
|
||||
/// État avec statistiques
|
||||
class MembresStatsLoaded extends MembresState {
|
||||
final Map<String, dynamic> stats;
|
||||
|
||||
const MembresStatsLoaded(this.stats);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [stats];
|
||||
}
|
||||
|
||||
/// État d'erreur
|
||||
class MembresError extends MembresState {
|
||||
final String message;
|
||||
final String? code;
|
||||
final dynamic error;
|
||||
|
||||
const MembresError({
|
||||
required this.message,
|
||||
this.code,
|
||||
this.error,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, code, error];
|
||||
}
|
||||
|
||||
/// État d'erreur réseau
|
||||
class MembresNetworkError extends MembresError {
|
||||
const MembresNetworkError({
|
||||
required String message,
|
||||
String? code,
|
||||
dynamic error,
|
||||
}) : super(message: message, code: code, error: error);
|
||||
}
|
||||
|
||||
/// État d'erreur de validation
|
||||
class MembresValidationError extends MembresError {
|
||||
final Map<String, String> validationErrors;
|
||||
|
||||
const MembresValidationError({
|
||||
required String message,
|
||||
required this.validationErrors,
|
||||
String? code,
|
||||
}) : super(message: message, code: code);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message, code, validationErrors];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user