Clean project: remove test files, debug logs, and add documentation

This commit is contained in:
dahoud
2025-10-05 13:41:33 +00:00
parent 96a17eadbd
commit 291847924c
438 changed files with 65754 additions and 32713 deletions

View File

@@ -0,0 +1,445 @@
/// 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.';
}
}
}

View File

@@ -0,0 +1,150 @@
/// Événements pour le BLoC des événements
library evenements_event;
import 'package:equatable/equatable.dart';
import '../data/models/evenement_model.dart';
/// Classe de base pour tous les événements
abstract class EvenementsEvent extends Equatable {
const EvenementsEvent();
@override
List<Object?> get props => [];
}
/// Événement pour charger la liste des événements
class LoadEvenements extends EvenementsEvent {
final int page;
final int size;
final String? recherche;
final bool refresh;
const LoadEvenements({
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 événement par ID
class LoadEvenementById extends EvenementsEvent {
final String id;
const LoadEvenementById(this.id);
@override
List<Object?> get props => [id];
}
/// Événement pour créer un nouvel événement
class CreateEvenement extends EvenementsEvent {
final EvenementModel evenement;
const CreateEvenement(this.evenement);
@override
List<Object?> get props => [evenement];
}
/// Événement pour mettre à jour un événement
class UpdateEvenement extends EvenementsEvent {
final String id;
final EvenementModel evenement;
const UpdateEvenement(this.id, this.evenement);
@override
List<Object?> get props => [id, evenement];
}
/// Événement pour supprimer un événement
class DeleteEvenement extends EvenementsEvent {
final String id;
const DeleteEvenement(this.id);
@override
List<Object?> get props => [id];
}
/// Événement pour charger les événements à venir
class LoadEvenementsAVenir extends EvenementsEvent {
final int page;
final int size;
const LoadEvenementsAVenir({
this.page = 0,
this.size = 20,
});
@override
List<Object?> get props => [page, size];
}
/// Événement pour charger les événements en cours
class LoadEvenementsEnCours extends EvenementsEvent {
final int page;
final int size;
const LoadEvenementsEnCours({
this.page = 0,
this.size = 20,
});
@override
List<Object?> get props => [page, size];
}
/// Événement pour charger les événements passés
class LoadEvenementsPasses extends EvenementsEvent {
final int page;
final int size;
const LoadEvenementsPasses({
this.page = 0,
this.size = 20,
});
@override
List<Object?> get props => [page, size];
}
/// Événement pour s'inscrire à un événement
class InscrireEvenement extends EvenementsEvent {
final String evenementId;
const InscrireEvenement(this.evenementId);
@override
List<Object?> get props => [evenementId];
}
/// Événement pour se désinscrire d'un événement
class DesinscrireEvenement extends EvenementsEvent {
final String evenementId;
const DesinscrireEvenement(this.evenementId);
@override
List<Object?> get props => [evenementId];
}
/// Événement pour charger les participants
class LoadParticipants extends EvenementsEvent {
final String evenementId;
const LoadParticipants(this.evenementId);
@override
List<Object?> get props => [evenementId];
}
/// Événement pour charger les statistiques
class LoadEvenementsStats extends EvenementsEvent {
const LoadEvenementsStats();
}

View File

@@ -0,0 +1,194 @@
/// États pour le BLoC des événements
library evenements_state;
import 'package:equatable/equatable.dart';
import '../data/models/evenement_model.dart';
/// Classe de base pour tous les états
abstract class EvenementsState extends Equatable {
const EvenementsState();
@override
List<Object?> get props => [];
}
/// État initial
class EvenementsInitial extends EvenementsState {
const EvenementsInitial();
}
/// État de chargement
class EvenementsLoading extends EvenementsState {
const EvenementsLoading();
}
/// État de chargement avec données existantes (pour refresh)
class EvenementsRefreshing extends EvenementsState {
final List<EvenementModel> currentEvenements;
const EvenementsRefreshing(this.currentEvenements);
@override
List<Object?> get props => [currentEvenements];
}
/// État de succès avec liste d'événements
class EvenementsLoaded extends EvenementsState {
final List<EvenementModel> evenements;
final int total;
final int page;
final int size;
final int totalPages;
final bool hasMore;
const EvenementsLoaded({
required this.evenements,
required this.total,
this.page = 0,
this.size = 20,
required this.totalPages,
}) : hasMore = page < totalPages - 1;
@override
List<Object?> get props => [evenements, total, page, size, totalPages, hasMore];
EvenementsLoaded copyWith({
List<EvenementModel>? evenements,
int? total,
int? page,
int? size,
int? totalPages,
}) {
return EvenementsLoaded(
evenements: evenements ?? this.evenements,
total: total ?? this.total,
page: page ?? this.page,
size: size ?? this.size,
totalPages: totalPages ?? this.totalPages,
);
}
}
/// État de succès avec un seul événement
class EvenementDetailLoaded extends EvenementsState {
final EvenementModel evenement;
const EvenementDetailLoaded(this.evenement);
@override
List<Object?> get props => [evenement];
}
/// État de succès après création
class EvenementCreated extends EvenementsState {
final EvenementModel evenement;
const EvenementCreated(this.evenement);
@override
List<Object?> get props => [evenement];
}
/// État de succès après mise à jour
class EvenementUpdated extends EvenementsState {
final EvenementModel evenement;
const EvenementUpdated(this.evenement);
@override
List<Object?> get props => [evenement];
}
/// État de succès après suppression
class EvenementDeleted extends EvenementsState {
final String id;
const EvenementDeleted(this.id);
@override
List<Object?> get props => [id];
}
/// État de succès après inscription
class EvenementInscrit extends EvenementsState {
final String evenementId;
const EvenementInscrit(this.evenementId);
@override
List<Object?> get props => [evenementId];
}
/// État de succès après désinscription
class EvenementDesinscrit extends EvenementsState {
final String evenementId;
const EvenementDesinscrit(this.evenementId);
@override
List<Object?> get props => [evenementId];
}
/// État avec liste de participants
class ParticipantsLoaded extends EvenementsState {
final String evenementId;
final List<Map<String, dynamic>> participants;
const ParticipantsLoaded({
required this.evenementId,
required this.participants,
});
@override
List<Object?> get props => [evenementId, participants];
}
/// État avec statistiques
class EvenementsStatsLoaded extends EvenementsState {
final Map<String, dynamic> stats;
const EvenementsStatsLoaded(this.stats);
@override
List<Object?> get props => [stats];
}
/// État d'erreur
class EvenementsError extends EvenementsState {
final String message;
final String? code;
final dynamic error;
const EvenementsError({
required this.message,
this.code,
this.error,
});
@override
List<Object?> get props => [message, code, error];
}
/// État d'erreur réseau
class EvenementsNetworkError extends EvenementsError {
const EvenementsNetworkError({
required String message,
String? code,
dynamic error,
}) : super(message: message, code: code, error: error);
}
/// État d'erreur de validation
class EvenementsValidationError extends EvenementsError {
final Map<String, String> validationErrors;
const EvenementsValidationError({
required String message,
required this.validationErrors,
String? code,
}) : super(message: message, code: code);
@override
List<Object?> get props => [message, code, validationErrors];
}