Initial commit: unionflow-mobile-apps

Application Flutter complète (sans build artifacts).

Signed-off-by: lions dev Team
This commit is contained in:
dahoud
2026-03-15 16:30:08 +00:00
commit d094d6db9c
1790 changed files with 507435 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
/// Implémentation du repository pour la gestion des événements
/// Interface avec l'API backend EvenementResource
library evenement_repository_impl;
import 'package:dio/dio.dart';
import 'package:unionflow_mobile_apps/core/network/api_client.dart';
import 'package:injectable/injectable.dart';
import '../../domain/repositories/evenement_repository.dart';
import '../models/evenement_model.dart';
/// Résultat de recherche paginé
class EvenementSearchResult {
final List<EvenementModel> evenements;
final int total;
final int page;
final int size;
final int totalPages;
const EvenementSearchResult({
required this.evenements,
required this.total,
required this.page,
required this.size,
required this.totalPages,
});
factory EvenementSearchResult.fromJson(Map<String, dynamic> json) {
// Support pour les deux formats de réponse
if (json.containsKey('data')) {
// Format paginé avec métadonnées
return EvenementSearchResult(
evenements: (json['data'] as List<dynamic>)
.map((e) => EvenementModel.fromJson(e as Map<String, dynamic>))
.toList(),
total: json['total'] as int,
page: json['page'] as int,
size: json['size'] as int,
totalPages: json['totalPages'] as int,
);
} else {
// Format simple (liste directe) - pour compatibilité backend
return EvenementSearchResult(
evenements: (json['content'] as List<dynamic>)
.map((e) => EvenementModel.fromJson(e as Map<String, dynamic>))
.toList(),
total: json['totalElements'] as int? ?? 0,
page: json['number'] as int? ?? 0,
size: json['size'] as int? ?? 20,
totalPages: json['totalPages'] as int? ?? 1,
);
}
}
}
/// Implémentation du repository des événements
@LazySingleton(as: IEvenementRepository)
class EvenementRepositoryImpl implements IEvenementRepository {
final ApiClient _apiClient;
static const String _baseUrl = '/api/evenements';
EvenementRepositoryImpl(this._apiClient);
/// Parse une réponse API : liste directe ou objet paginé (content / data).
EvenementSearchResult _parseSearchResponse(dynamic data, int page, int size) {
if (data is List) {
final evenements = (data as List<dynamic>)
.map((e) => EvenementModel.fromJson(e as Map<String, dynamic>))
.toList();
return EvenementSearchResult(
evenements: evenements,
total: evenements.length,
page: page,
size: size,
totalPages: 1,
);
}
return EvenementSearchResult.fromJson(data as Map<String, dynamic>);
}
@override
Future<EvenementSearchResult> getEvenements({
int page = 0,
int size = 20,
String? recherche,
}) async {
try {
final queryParams = <String, dynamic>{
'page': page,
'size': size,
};
if (recherche?.isNotEmpty == true) {
queryParams['recherche'] = recherche;
}
final response = await _apiClient.get(
_baseUrl,
queryParameters: queryParams,
);
if (response.statusCode == 200) {
// Le backend peut retourner soit une liste directe, soit un objet paginé
if (response.data is List) {
// Format liste directe
final evenements = (response.data as List<dynamic>)
.map((e) => EvenementModel.fromJson(e as Map<String, dynamic>))
.toList();
return EvenementSearchResult(
evenements: evenements,
total: evenements.length,
page: page,
size: size,
totalPages: 1,
);
} else {
// Format objet paginé
return EvenementSearchResult.fromJson(response.data as Map<String, dynamic>);
}
} else {
throw Exception('Erreur lors de la récupération des événements: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.response != null) {
throw Exception('Erreur HTTP ${e.response!.statusCode}: ${e.response!.data}');
} else {
throw Exception('Erreur réseau: ${e.type} - ${e.message ?? e.error}');
}
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des événements: $e');
}
}
@override
Future<EvenementModel?> getEvenementById(String id) async {
try {
final response = await _apiClient.get('$_baseUrl/$id');
if (response.statusCode == 200) {
return EvenementModel.fromJson(response.data as Map<String, dynamic>);
} else if (response.statusCode == 404) {
return null;
} else {
throw Exception('Erreur lors de la récupération de l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.response?.statusCode == 404) {
return null;
}
throw Exception('Erreur réseau lors de la récupération de l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération de l\'événement: $e');
}
}
@override
Future<EvenementModel> createEvenement(EvenementModel evenement) async {
try {
final response = await _apiClient.post(
_baseUrl,
data: evenement.toJson(),
);
if (response.statusCode == 201 || response.statusCode == 200) {
return EvenementModel.fromJson(response.data as Map<String, dynamic>);
} else {
throw Exception('Erreur lors de la création de l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la création de l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la création de l\'événement: $e');
}
}
@override
Future<EvenementModel> updateEvenement(String id, EvenementModel evenement) async {
try {
final response = await _apiClient.put(
'$_baseUrl/$id',
data: evenement.toJson(),
);
if (response.statusCode == 200) {
return EvenementModel.fromJson(response.data as Map<String, dynamic>);
} else {
throw Exception('Erreur lors de la mise à jour de l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la mise à jour de l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la mise à jour de l\'événement: $e');
}
}
@override
Future<void> deleteEvenement(String id) async {
try {
final response = await _apiClient.delete('$_baseUrl/$id');
if (response.statusCode != 204 && response.statusCode != 200) {
throw Exception('Erreur lors de la suppression de l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la suppression de l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la suppression de l\'événement: $e');
}
}
@override
Future<EvenementSearchResult> getEvenementsAVenir({int page = 0, int size = 20}) async {
try {
final response = await _apiClient.get(
'$_baseUrl/a-venir',
queryParameters: {'page': page, 'size': size},
);
if (response.statusCode == 200) {
return _parseSearchResponse(response.data, page, size);
} else {
throw Exception('Erreur lors de la récupération des événements à venir: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la récupération des événements à venir: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des événements à venir: $e');
}
}
@override
Future<EvenementSearchResult> getEvenementsEnCours({int page = 0, int size = 20}) async {
try {
final response = await _apiClient.get(
'$_baseUrl/en-cours',
queryParameters: {'page': page, 'size': size},
);
if (response.statusCode == 200) {
return _parseSearchResponse(response.data, page, size);
} else {
throw Exception('Erreur lors de la récupération des événements en cours: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la récupération des événements en cours: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des événements en cours: $e');
}
}
@override
Future<EvenementSearchResult> getEvenementsPasses({int page = 0, int size = 20}) async {
try {
final response = await _apiClient.get(
'$_baseUrl/passes',
queryParameters: {'page': page, 'size': size},
);
if (response.statusCode == 200) {
return _parseSearchResponse(response.data, page, size);
} else {
throw Exception('Erreur lors de la récupération des événements passés: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la récupération des événements passés: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des événements passés: $e');
}
}
@override
Future<void> inscrireEvenement(String evenementId) async {
try {
final response = await _apiClient.post('$_baseUrl/$evenementId/inscrire');
if (response.statusCode != 200 && response.statusCode != 201) {
throw Exception('Erreur lors de l\'inscription à l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de l\'inscription à l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de l\'inscription à l\'événement: $e');
}
}
@override
Future<void> desinscrireEvenement(String evenementId) async {
try {
final response = await _apiClient.delete('$_baseUrl/$evenementId/desinscrire');
if (response.statusCode != 200 && response.statusCode != 204) {
throw Exception('Erreur lors de la désinscription de l\'événement: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la désinscription de l\'événement: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la désinscription de l\'événement: $e');
}
}
@override
Future<List<Map<String, dynamic>>> getParticipants(String evenementId) async {
try {
final response = await _apiClient.get('$_baseUrl/$evenementId/participants');
if (response.statusCode == 200) {
return (response.data as List<dynamic>)
.map((e) => e as Map<String, dynamic>)
.toList();
} else {
throw Exception('Erreur lors de la récupération des participants: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la récupération des participants: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des participants: $e');
}
}
@override
Future<bool> getInscriptionStatus(String evenementId) async {
try {
final response = await _apiClient.get('$_baseUrl/$evenementId/me/inscrit');
if (response.statusCode == 200 && response.data is Map) {
final data = response.data as Map<String, dynamic>;
return data['inscrit'] == true;
}
return false;
} on DioException catch (_) {
return false;
} catch (_) {
return false;
}
}
@override
Future<Map<String, dynamic>> getEvenementsStats() async {
try {
final response = await _apiClient.get('$_baseUrl/statistiques');
if (response.statusCode == 200) {
return response.data as Map<String, dynamic>;
} else {
throw Exception('Erreur lors de la récupération des statistiques: ${response.statusCode}');
}
} on DioException catch (e) {
throw Exception('Erreur réseau lors de la récupération des statistiques: ${e.message}');
} catch (e) {
throw Exception('Erreur inattendue lors de la récupération des statistiques: $e');
}
}
}