- Ajout de deux endpoints distincts dans Urls: getSentFriendRequestsWithUserId et getReceivedFriendRequestsWithUserId - Ajout de méthodes dans FriendsRepository et FriendsRepositoryImpl pour récupérer séparément les demandes envoyées et reçues - Ajout de la méthode cancelFriendRequest pour annuler une demande envoyée - Modification de FriendsProvider pour gérer deux listes distinctes: sentRequests et receivedRequests - Mise à jour de FriendsScreen pour afficher deux sections: - Demandes reçues: avec boutons Accepter/Rejeter - Demandes envoyées: avec bouton Annuler uniquement - Correction du mapping JSON dans FriendRequest.fromJson (userNom/userPrenoms correctement mappés) - Amélioration de FriendRequestCard pour gérer les deux types de demandes - Correction de la validation d'URL d'image dans FriendDetailScreen - Support du champ uuid dans UserModel.fromJson pour compatibilité backend
687 lines
21 KiB
Dart
687 lines
21 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import '../../core/constants/env_config.dart';
|
|
import '../../core/constants/urls.dart';
|
|
import '../../core/errors/exceptions.dart';
|
|
import '../../domain/entities/friend.dart';
|
|
import '../../domain/entities/friend_request.dart';
|
|
import 'friends_repository.dart';
|
|
|
|
/// Implémentation de [FriendsRepository] pour gérer les appels API relatifs aux amis.
|
|
///
|
|
/// Cette classe gère toutes les opérations sur les amis via l'API backend,
|
|
/// avec gestion d'erreurs robuste, timeouts, et validation des réponses.
|
|
///
|
|
/// **Usage:**
|
|
/// ```dart
|
|
/// final repository = FriendsRepositoryImpl(client: http.Client());
|
|
/// final friends = await repository.fetchFriends('user123', 0, 20);
|
|
/// ```
|
|
class FriendsRepositoryImpl implements FriendsRepository {
|
|
/// Crée une nouvelle instance de [FriendsRepositoryImpl].
|
|
///
|
|
/// [client] Le client HTTP à utiliser pour les requêtes
|
|
FriendsRepositoryImpl({required this.client});
|
|
|
|
/// Client HTTP pour effectuer les requêtes réseau
|
|
final http.Client client;
|
|
|
|
/// Headers par défaut pour les requêtes
|
|
static const Map<String, String> _defaultHeaders = {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
};
|
|
|
|
/// Timeout pour les requêtes réseau
|
|
Duration get _timeout => Duration(seconds: EnvConfig.networkTimeout);
|
|
|
|
// ============================================================================
|
|
// MÉTHODES PRIVÉES UTILITAIRES
|
|
// ============================================================================
|
|
|
|
/// Effectue une requête HTTP avec gestion d'erreurs et timeout.
|
|
Future<http.Response> _performRequest(
|
|
String method,
|
|
Uri uri, {
|
|
Map<String, String>? headers,
|
|
Object? body,
|
|
}) async {
|
|
try {
|
|
final requestHeaders = {
|
|
..._defaultHeaders,
|
|
if (headers != null) ...headers,
|
|
};
|
|
|
|
http.Response response;
|
|
|
|
switch (method.toUpperCase()) {
|
|
case 'GET':
|
|
response = await client
|
|
.get(uri, headers: requestHeaders)
|
|
.timeout(_timeout);
|
|
break;
|
|
case 'POST':
|
|
response = await client
|
|
.post(uri, headers: requestHeaders, body: body)
|
|
.timeout(_timeout);
|
|
break;
|
|
case 'DELETE':
|
|
response = await client
|
|
.delete(uri, headers: requestHeaders)
|
|
.timeout(_timeout);
|
|
break;
|
|
case 'PATCH':
|
|
response = await client
|
|
.patch(uri, headers: requestHeaders, body: body)
|
|
.timeout(_timeout);
|
|
break;
|
|
default:
|
|
throw ArgumentError('Méthode HTTP non supportée: $method');
|
|
}
|
|
|
|
return response;
|
|
} on SocketException {
|
|
throw ServerException(
|
|
'Erreur de connexion réseau. Vérifiez votre connexion Internet.',
|
|
statusCode: null,
|
|
);
|
|
} on HttpException catch (e) {
|
|
throw ServerException(
|
|
'Erreur HTTP: ${e.message}',
|
|
statusCode: null,
|
|
);
|
|
} on FormatException catch (e) {
|
|
throw ServerException(
|
|
'Erreur de format de réponse: ${e.message}',
|
|
statusCode: null,
|
|
);
|
|
} catch (e) {
|
|
if (e is ServerException) rethrow;
|
|
throw ServerException(
|
|
'Erreur inattendue: $e',
|
|
statusCode: null,
|
|
originalError: e,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Parse une réponse JSON et gère les erreurs.
|
|
dynamic _parseJsonResponse(
|
|
http.Response response,
|
|
List<int> expectedStatusCodes,
|
|
) {
|
|
if (!expectedStatusCodes.contains(response.statusCode)) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
try {
|
|
if (response.body.isEmpty) {
|
|
return null;
|
|
}
|
|
return json.decode(response.body);
|
|
} on FormatException catch (e) {
|
|
throw ServerException(
|
|
'Erreur de parsing JSON: ${e.message}',
|
|
statusCode: response.statusCode,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Gère les erreurs de réponse HTTP.
|
|
void _handleErrorResponse(http.Response response) {
|
|
String errorMessage;
|
|
|
|
try {
|
|
if (response.body.isNotEmpty) {
|
|
final errorBody = json.decode(response.body);
|
|
|
|
// Gérer le format Bean Validation (Quarkus)
|
|
if (errorBody is Map && errorBody.containsKey('attributeName')) {
|
|
final attributeName = errorBody['attributeName'] as String? ?? 'champ';
|
|
final value = errorBody['value'] as String?;
|
|
final objectName = errorBody['objectName'] as String? ?? '';
|
|
|
|
// Construire un message d'erreur plus clair
|
|
if (attributeName == 'friendId' && value != null) {
|
|
errorMessage = 'L\'identifiant "$value" n\'est pas valide. Veuillez utiliser l\'ID utilisateur (UUID) et non l\'email.';
|
|
} else {
|
|
errorMessage = 'Erreur de validation sur le champ "$attributeName"';
|
|
if (value != null) {
|
|
errorMessage += ': valeur "$value" invalide';
|
|
}
|
|
}
|
|
} else {
|
|
// Essayer plusieurs formats de réponse d'erreur standard
|
|
errorMessage = errorBody['message'] as String? ??
|
|
errorBody['error'] as String? ??
|
|
errorBody['errorMessage'] as String? ??
|
|
(errorBody is Map && errorBody.isNotEmpty
|
|
? errorBody.values.first.toString()
|
|
: 'Erreur serveur inconnue');
|
|
}
|
|
|
|
// Log détaillé pour le débogage
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Réponse d\'erreur du serveur (${response.statusCode}): ${response.body}');
|
|
_log('Message d\'erreur extrait: $errorMessage');
|
|
}
|
|
} else {
|
|
errorMessage = 'Erreur serveur (${response.statusCode})';
|
|
}
|
|
} catch (e) {
|
|
// Si le parsing JSON échoue, utiliser le body brut
|
|
errorMessage = response.body.isNotEmpty
|
|
? response.body
|
|
: 'Erreur serveur (${response.statusCode})';
|
|
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Erreur lors du parsing de la réponse d\'erreur: $e');
|
|
_log('Body brut: ${response.body}');
|
|
}
|
|
}
|
|
|
|
switch (response.statusCode) {
|
|
case 400:
|
|
throw ValidationException(errorMessage);
|
|
case 401:
|
|
throw UnauthorizedException(errorMessage);
|
|
case 404:
|
|
throw ServerException(
|
|
'Ressource non trouvée: $errorMessage',
|
|
statusCode: 404,
|
|
);
|
|
case 409:
|
|
throw ConflictException(errorMessage);
|
|
case 500:
|
|
case 502:
|
|
case 503:
|
|
throw ServerException(
|
|
'Erreur serveur: $errorMessage',
|
|
statusCode: response.statusCode,
|
|
);
|
|
default:
|
|
throw ServerException(
|
|
errorMessage,
|
|
statusCode: response.statusCode,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Vérifie si une chaîne est un UUID valide
|
|
bool _isValidUUID(String value) {
|
|
final uuidRegex = RegExp(
|
|
r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
|
|
caseSensitive: false,
|
|
);
|
|
return uuidRegex.hasMatch(value);
|
|
}
|
|
|
|
/// Log un message si le mode debug est activé.
|
|
void _log(String message) {
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
print('[FriendsRepositoryImpl] $message');
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// MÉTHODES PUBLIQUES
|
|
// ============================================================================
|
|
|
|
/// Récupère la liste paginée des amis pour un utilisateur donné.
|
|
///
|
|
/// [userId] L'identifiant unique de l'utilisateur
|
|
/// [page] Le numéro de page (commence à 0)
|
|
/// [size] Le nombre d'amis par page
|
|
///
|
|
/// Returns une liste d'objets [Friend]
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
///
|
|
/// **Exemple:**
|
|
/// ```dart
|
|
/// final friends = await repository.fetchFriends('user123', 0, 20);
|
|
/// ```
|
|
@override
|
|
Future<List<Friend>> fetchFriends(String userId, int page, int size) async {
|
|
_log('Récupération des amis pour l\'utilisateur $userId (page $page, taille $size)');
|
|
|
|
if (userId.isEmpty) {
|
|
throw ValidationException('L\'ID utilisateur ne peut pas être vide');
|
|
}
|
|
|
|
if (page < 0) {
|
|
throw ValidationException('Le numéro de page doit être >= 0');
|
|
}
|
|
|
|
if (size <= 0) {
|
|
throw ValidationException('La taille de page doit être > 0');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse('${Urls.friendsBase}/list/$userId')
|
|
.replace(queryParameters: {
|
|
'page': page.toString(),
|
|
'size': size.toString(),
|
|
});
|
|
|
|
final response = await _performRequest('GET', uri);
|
|
|
|
// Gérer le cas 404 comme une liste vide
|
|
if (response.statusCode == 404) {
|
|
_log('Aucun ami trouvé (404) - retour d\'une liste vide');
|
|
return [];
|
|
}
|
|
|
|
final jsonResponse = _parseJsonResponse(response, [200]) as List<dynamic>?;
|
|
|
|
if (jsonResponse == null) {
|
|
return [];
|
|
}
|
|
|
|
final friends = jsonResponse
|
|
.map((json) => Friend.fromJson(json as Map<String, dynamic>))
|
|
.toList();
|
|
|
|
_log('${friends.length} amis récupérés avec succès');
|
|
return friends;
|
|
} catch (e) {
|
|
_log('Erreur lors de la récupération des amis: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Envoie une demande pour ajouter un nouvel ami.
|
|
///
|
|
/// [userId] L'identifiant unique de l'utilisateur qui envoie la demande
|
|
/// [friendId] L'identifiant unique de l'ami à ajouter
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
///
|
|
/// **Exemple:**
|
|
/// ```dart
|
|
/// await repository.addFriend('user-uuid', 'friend-uuid');
|
|
/// ```
|
|
@override
|
|
Future<void> addFriend(String userId, String friendId) async {
|
|
_log('Ajout de l\'ami: userId=$userId, friendId=$friendId');
|
|
|
|
if (userId.isEmpty) {
|
|
throw ValidationException('L\'ID de l\'utilisateur ne peut pas être vide');
|
|
}
|
|
|
|
if (friendId.isEmpty) {
|
|
throw ValidationException('L\'ID de l\'ami ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse('${Urls.friendsBase}/send');
|
|
|
|
// Le backend attend userId et friendId dans FriendshipCreateOneRequestDTO
|
|
final bodyJson = {
|
|
'userId': userId,
|
|
'friendId': friendId,
|
|
};
|
|
final body = jsonEncode(bodyJson);
|
|
|
|
// Log détaillé du body envoyé
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Envoi de la demande d\'ami à: $uri');
|
|
_log('Body JSON: $body');
|
|
}
|
|
|
|
final response = await _performRequest(
|
|
'POST',
|
|
uri,
|
|
body: body,
|
|
);
|
|
|
|
// Log de la réponse
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Réponse du serveur (${response.statusCode}): ${response.body}');
|
|
}
|
|
|
|
if (![200, 201].contains(response.statusCode)) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Ami ajouté avec succès: $friendId');
|
|
} catch (e) {
|
|
_log('Erreur lors de l\'ajout de l\'ami: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Supprime un ami existant.
|
|
///
|
|
/// [friendId] L'identifiant unique de l'ami à supprimer
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
///
|
|
/// **Exemple:**
|
|
/// ```dart
|
|
/// await repository.removeFriend('friend123');
|
|
/// ```
|
|
@override
|
|
Future<void> removeFriend(String friendId) async {
|
|
_log('Suppression de l\'ami $friendId');
|
|
|
|
if (friendId.isEmpty) {
|
|
throw ValidationException('L\'ID de l\'ami ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse('${Urls.friendsBase}/$friendId');
|
|
final response = await _performRequest('DELETE', uri);
|
|
|
|
if (![200, 204].contains(response.statusCode)) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Ami $friendId supprimé avec succès');
|
|
} catch (e) {
|
|
_log('Erreur lors de la suppression de l\'ami $friendId: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Récupère les détails d'un ami.
|
|
///
|
|
/// [friendId] L'identifiant unique de l'ami
|
|
/// [userId] L'identifiant unique de l'utilisateur connecté
|
|
///
|
|
/// Returns un [Friend] avec les informations de l'ami, ou `null` si non trouvé
|
|
///
|
|
/// **Exemple:**
|
|
/// ```dart
|
|
/// final friend = await repository.getFriendDetails('friend123', 'user123');
|
|
/// ```
|
|
@override
|
|
Future<Friend?> getFriendDetails(String friendId, String userId) async {
|
|
_log('Récupération des détails de l\'ami $friendId pour l\'utilisateur $userId');
|
|
|
|
if (friendId.isEmpty || userId.isEmpty) {
|
|
throw ValidationException('Les IDs ne peuvent pas être vides');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse('${Urls.friendsBase}/details');
|
|
final body = jsonEncode({
|
|
'friendId': friendId,
|
|
'userId': userId,
|
|
});
|
|
|
|
final response = await _performRequest(
|
|
'POST',
|
|
uri,
|
|
body: body,
|
|
);
|
|
|
|
// Gérer le cas 404 comme null
|
|
if (response.statusCode == 404) {
|
|
_log('Ami $friendId non trouvé (404)');
|
|
return null;
|
|
}
|
|
|
|
final jsonResponse = _parseJsonResponse(response, [200]) as Map<String, dynamic>?;
|
|
|
|
if (jsonResponse == null) {
|
|
return null;
|
|
}
|
|
|
|
final friend = Friend.fromJson(jsonResponse);
|
|
_log('Détails de l\'ami $friendId récupérés avec succès');
|
|
return friend;
|
|
} catch (e) {
|
|
_log('Erreur lors de la récupération des détails de l\'ami $friendId: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Met à jour le statut d'un ami (par exemple, "accepté", "bloqué").
|
|
///
|
|
/// [friendId] L'identifiant unique de l'ami
|
|
/// [status] Le nouveau statut sous forme de chaîne de caractères
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
///
|
|
/// **Exemple:**
|
|
/// ```dart
|
|
/// await repository.updateFriendStatus('friend123', 'accepted');
|
|
/// ```
|
|
@override
|
|
Future<void> updateFriendStatus(String friendId, String status) async {
|
|
_log('Mise à jour du statut de l\'ami $friendId: $status');
|
|
|
|
if (friendId.isEmpty) {
|
|
throw ValidationException('L\'ID de l\'ami ne peut pas être vide');
|
|
}
|
|
|
|
if (status.isEmpty) {
|
|
throw ValidationException('Le statut ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse('${Urls.friendsBase}/$friendId/status');
|
|
final body = jsonEncode({'status': status});
|
|
|
|
final response = await _performRequest(
|
|
'PATCH',
|
|
uri,
|
|
body: body,
|
|
);
|
|
|
|
if (response.statusCode != 200) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Statut de l\'ami $friendId mis à jour avec succès');
|
|
} catch (e) {
|
|
_log('Erreur lors de la mise à jour du statut de l\'ami $friendId: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Récupère les demandes d'amitié en attente pour un utilisateur.
|
|
///
|
|
/// [userId] L'identifiant unique de l'utilisateur
|
|
/// [page] Le numéro de la page pour la pagination
|
|
/// [size] La taille de la page
|
|
///
|
|
/// Retourne une liste de [FriendRequest]
|
|
@override
|
|
Future<List<FriendRequest>> getPendingFriendRequests(String userId, int page, int size) async {
|
|
_log('Récupération des demandes d\'amitié en attente pour l\'utilisateur $userId (page $page, taille $size)');
|
|
|
|
try {
|
|
final uri = Uri.parse(Urls.getPendingFriendRequestsWithUserId(userId, page: page, size: size));
|
|
final response = await _performRequest('GET', uri);
|
|
|
|
if (response.statusCode != 200) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
final jsonResponse = _parseJsonResponse(response, [200]) as List<dynamic>;
|
|
final requests = jsonResponse
|
|
.map((json) => FriendRequest.fromJson(json as Map<String, dynamic>))
|
|
.toList();
|
|
|
|
_log('${requests.length} demandes d\'amitié en attente récupérées avec succès');
|
|
return requests;
|
|
} catch (e) {
|
|
_log('Erreur lors de la récupération des demandes d\'amitié en attente: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Accepte une demande d'amitié.
|
|
///
|
|
/// [friendshipId] L'identifiant unique de la relation d'amitié
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
@override
|
|
Future<void> acceptFriendRequest(String friendshipId) async {
|
|
_log('Acceptation de la demande d\'amitié: $friendshipId');
|
|
|
|
if (friendshipId.isEmpty) {
|
|
throw ValidationException('L\'ID de la relation d\'amitié ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse(Urls.acceptFriendRequestWithId(friendshipId));
|
|
final response = await _performRequest('PATCH', uri);
|
|
|
|
if (response.statusCode != 200) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Demande d\'amitié acceptée avec succès: $friendshipId');
|
|
} catch (e) {
|
|
_log('Erreur lors de l\'acceptation de la demande d\'amitié: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Rejette une demande d'amitié.
|
|
///
|
|
/// [friendshipId] L'identifiant unique de la relation d'amitié
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
@override
|
|
Future<void> rejectFriendRequest(String friendshipId) async {
|
|
_log('Rejet de la demande d\'amitié: $friendshipId');
|
|
|
|
if (friendshipId.isEmpty) {
|
|
throw ValidationException('L\'ID de la relation d\'amitié ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
final uri = Uri.parse(Urls.rejectFriendRequestWithId(friendshipId));
|
|
final response = await _performRequest('PATCH', uri);
|
|
|
|
if (response.statusCode != 204) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Demande d\'amitié rejetée avec succès: $friendshipId');
|
|
} catch (e) {
|
|
_log('Erreur lors du rejet de la demande d\'amitié: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Récupère les demandes d'amitié envoyées par un utilisateur.
|
|
///
|
|
/// [userId] L'identifiant unique de l'utilisateur
|
|
/// [page] Le numéro de page (commence à 0)
|
|
/// [size] Le nombre de demandes par page
|
|
///
|
|
/// Returns une liste d'objets [FriendRequest]
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
@override
|
|
Future<List<FriendRequest>> getSentFriendRequests(String userId, int page, int size) async {
|
|
_log('Récupération des demandes d\'amitié envoyées pour l\'utilisateur $userId (page $page, taille $size)');
|
|
|
|
try {
|
|
final uri = Uri.parse(Urls.getSentFriendRequestsWithUserId(userId, page: page, size: size));
|
|
final response = await _performRequest('GET', uri);
|
|
|
|
if (response.statusCode == 404) {
|
|
_log('Aucune demande envoyée trouvée (404) - retour d\'une liste vide');
|
|
return [];
|
|
}
|
|
|
|
final jsonResponse = _parseJsonResponse(response, [200]) as List<dynamic>;
|
|
final requests = jsonResponse
|
|
.map((json) => FriendRequest.fromJson(json as Map<String, dynamic>))
|
|
.toList();
|
|
|
|
_log('${requests.length} demandes d\'amitié envoyées récupérées avec succès');
|
|
return requests;
|
|
} catch (e) {
|
|
_log('Erreur lors de la récupération des demandes d\'amitié envoyées: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Récupère les demandes d'amitié reçues par un utilisateur.
|
|
///
|
|
/// [userId] L'identifiant unique de l'utilisateur
|
|
/// [page] Le numéro de page (commence à 0)
|
|
/// [size] Le nombre de demandes par page
|
|
///
|
|
/// Returns une liste d'objets [FriendRequest]
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
@override
|
|
Future<List<FriendRequest>> getReceivedFriendRequests(String userId, int page, int size) async {
|
|
_log('Récupération des demandes d\'amitié reçues pour l\'utilisateur $userId (page $page, taille $size)');
|
|
|
|
try {
|
|
final uri = Uri.parse(Urls.getReceivedFriendRequestsWithUserId(userId, page: page, size: size));
|
|
final response = await _performRequest('GET', uri);
|
|
|
|
if (response.statusCode == 404) {
|
|
_log('Aucune demande reçue trouvée (404) - retour d\'une liste vide');
|
|
return [];
|
|
}
|
|
|
|
final jsonResponse = _parseJsonResponse(response, [200]) as List<dynamic>;
|
|
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Réponse JSON brute: $jsonResponse');
|
|
}
|
|
|
|
final requests = jsonResponse
|
|
.map((json) {
|
|
if (EnvConfig.enableDetailedLogs) {
|
|
_log('Parsing demande: $json');
|
|
}
|
|
return FriendRequest.fromJson(json as Map<String, dynamic>);
|
|
})
|
|
.toList();
|
|
|
|
_log('${requests.length} demandes d\'amitié reçues récupérées avec succès');
|
|
if (EnvConfig.enableDetailedLogs && requests.isNotEmpty) {
|
|
_log('Première demande: userId=${requests.first.userId}, friendId=${requests.first.friendId}, userFullName=${requests.first.userFullName}');
|
|
}
|
|
return requests;
|
|
} catch (e) {
|
|
_log('Erreur lors de la récupération des demandes d\'amitié reçues: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Annule une demande d'amitié envoyée (supprime la relation).
|
|
///
|
|
/// [friendshipId] L'identifiant unique de la relation d'amitié
|
|
///
|
|
/// Throws [ServerException] en cas d'erreur
|
|
@override
|
|
Future<void> cancelFriendRequest(String friendshipId) async {
|
|
_log('Annulation de la demande d\'amitié: $friendshipId');
|
|
|
|
if (friendshipId.isEmpty) {
|
|
throw ValidationException('L\'ID de la relation d\'amitié ne peut pas être vide');
|
|
}
|
|
|
|
try {
|
|
// Utiliser l'endpoint DELETE existant pour supprimer la relation
|
|
final uri = Uri.parse('${Urls.friendsBase}/$friendshipId');
|
|
final response = await _performRequest('DELETE', uri);
|
|
|
|
if (response.statusCode != 204) {
|
|
_handleErrorResponse(response);
|
|
}
|
|
|
|
_log('Demande d\'amitié annulée avec succès: $friendshipId');
|
|
} catch (e) {
|
|
_log('Erreur lors de l\'annulation de la demande d\'amitié: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
}
|