Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user