feat(frontend): Séparation des demandes d'amitié envoyées et reçues

- 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
This commit is contained in:
dahoud
2026-01-07 16:33:27 +00:00
parent 69c8c21591
commit 06031b01f2
10 changed files with 2599 additions and 373 deletions

View File

@@ -1,32 +1,374 @@
import 'env_config.dart';
/// Classe utilitaire pour gérer toutes les URLs de l'API backend.
///
/// Cette classe centralise toutes les URLs de l'API pour faciliter
/// la maintenance et éviter la duplication de code.
///
/// **Usage:**
/// ```dart
/// // URL simple
/// final url = Urls.authenticateUser;
///
/// // URL avec paramètres dynamiques
/// final userUrl = Urls.getUserByIdWithId('123');
/// final eventUrl = Urls.getEventByIdWithId('456');
/// ```
class Urls {
static const String baseUrl = 'http://192.168.1.16:8080';
/// Constructeur privé pour empêcher l'instanciation
Urls._();
// Authentication and Users Endpoints
static const String authenticateUser = '$baseUrl/users/authenticate';
static const String createUser = '$baseUrl/users';
static const String getUserById = '$baseUrl/users'; // Append '/{id}' dynamically
static const String deleteUser = '$baseUrl/users'; // Append '/{id}' dynamically
static const String updateUserProfileImage = '$baseUrl/users'; // Append '/{id}/profile-image' dynamically
/// URL de base de l'API
static String get baseUrl => EnvConfig.apiBaseUrl;
// Events Endpoints
static const String createEvent = '$baseUrl/events';
static const String getEventById = '$baseUrl/events'; // Append '/{id}' dynamically
static const String deleteEvent = '$baseUrl/events'; // Append '/{id}' dynamically
static const String getEventsAfterDate = '$baseUrl/events/after-date';
static const String addParticipant = '$baseUrl/events'; // Append '/{id}/participants' dynamically
static const String removeParticipant = '$baseUrl/events'; // Append '/{id}/participants/{userId}' dynamically
static const String getNumberOfParticipants = '$baseUrl/events'; // Append '/{id}/participants/count' dynamically
static const String closeEvent = '$baseUrl/events'; // Append '/{id}/close' dynamically
static const String reopenEvent = '$baseUrl/events'; // Append '/{id}/reopen' dynamically
static const String updateEvent = '$baseUrl/events'; // Append '/{id}' dynamically
static const String updateEventImage = '$baseUrl/events'; // Append '/{id}/image' dynamically
static const String getAllEvents = '$baseUrl/events';
static const String getEventsByCategory = '$baseUrl/events/category'; // Append '/{category}' dynamically
static const String updateEventStatus = '$baseUrl/events'; // Append '/{id}/status' dynamically
static const String searchEvents = '$baseUrl/events/search'; // Use query parameter for 'keyword'
static const String getEventsByUser = '$baseUrl/events/user'; // Append '/{userId}' dynamically
static const String getEventsByStatus = '$baseUrl/events/status'; // Append '/{status}' dynamically
static const String getEventsBetweenDates = '$baseUrl/events/between-dates'; // Use query parameters for startDate and endDate
// ============================================================================
// AUTHENTIFICATION ET UTILISATEURS
// ============================================================================
// Other URLs can be added here as the project expands
/// Endpoint pour authentifier un utilisateur
static String get authenticateUser => '$baseUrl/users/authenticate';
/// Endpoint pour créer un nouvel utilisateur
static String get createUser => '$baseUrl/users';
/// Endpoint de base pour les opérations sur les utilisateurs
static String get usersBase => '$baseUrl/users';
/// Retourne l'URL pour obtenir un utilisateur par son ID
///
/// [userId] L'ID de l'utilisateur
static String getUserByIdWithId(String userId) => '$usersBase/$userId';
/// Retourne l'URL pour rechercher un utilisateur par email
///
/// [email] L'email de l'utilisateur à rechercher
static String searchUserByEmail(String email) =>
'$usersBase/search?email=${Uri.encodeComponent(email)}';
/// Retourne l'URL pour supprimer un utilisateur par son ID
///
/// [userId] L'ID de l'utilisateur
static String deleteUserWithId(String userId) => '$usersBase/$userId';
/// Retourne l'URL pour mettre à jour l'image de profil d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String updateUserProfileImageWithId(String userId) =>
'$usersBase/$userId/profile-image';
/// Retourne l'URL pour mettre à jour un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String updateUserWithId(String userId) => '$usersBase/$userId';
// ============================================================================
// ÉVÉNEMENTS
// ============================================================================
/// Endpoint de base pour les opérations sur les événements
static String get eventsBase => '$baseUrl/events';
/// Endpoint pour créer un nouvel événement
static String get createEvent => eventsBase;
/// Endpoint pour obtenir tous les événements
static String get getAllEvents => eventsBase;
/// Endpoint pour obtenir les événements créés par un utilisateur et ses amis
static String get getEventsCreatedByUserAndFriends =>
'$eventsBase/created-by-user-and-friends';
/// Retourne l'URL pour obtenir un événement par son ID
///
/// [eventId] L'ID de l'événement
static String getEventByIdWithId(String eventId) => '$eventsBase/$eventId';
/// Retourne l'URL pour supprimer un événement par son ID
///
/// [eventId] L'ID de l'événement
static String deleteEventWithId(String eventId) => '$eventsBase/$eventId';
/// Retourne l'URL pour mettre à jour un événement
///
/// [eventId] L'ID de l'événement
static String updateEventWithId(String eventId) => '$eventsBase/$eventId';
/// Retourne l'URL pour mettre à jour l'image d'un événement
///
/// [eventId] L'ID de l'événement
static String updateEventImageWithId(String eventId) =>
'$eventsBase/$eventId/image';
/// Retourne l'URL pour fermer un événement
///
/// [eventId] L'ID de l'événement
static String closeEventWithId(String eventId) => '$eventsBase/$eventId/close';
/// Retourne l'URL pour rouvrir un événement
///
/// [eventId] L'ID de l'événement
static String reopenEventWithId(String eventId) =>
'$eventsBase/$eventId/reopen';
/// Retourne l'URL pour mettre à jour le statut d'un événement
///
/// [eventId] L'ID de l'événement
static String updateEventStatusWithId(String eventId) =>
'$eventsBase/$eventId/status';
/// Endpoint pour obtenir les événements après une date
static String get getEventsAfterDate => '$eventsBase/after-date';
/// Endpoint pour obtenir les événements entre deux dates
static String get getEventsBetweenDates => '$eventsBase/between-dates';
/// Retourne l'URL pour obtenir les événements par catégorie
///
/// [category] La catégorie des événements
static String getEventsByCategoryWithCategory(String category) =>
'$eventsBase/category/$category';
/// Retourne l'URL pour obtenir les événements par statut
///
/// [status] Le statut des événements (ouvert, fermé, etc.)
static String getEventsByStatusWithStatus(String status) =>
'$eventsBase/status/$status';
/// Retourne l'URL pour obtenir les événements d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getEventsByUserWithUserId(String userId) =>
'$eventsBase/user/$userId';
/// Endpoint pour rechercher des événements
///
/// **Note:** Utilisez des paramètres de requête pour le mot-clé
static String get searchEvents => '$eventsBase/search';
// ============================================================================
// PARTICIPANTS AUX ÉVÉNEMENTS
// ============================================================================
/// Retourne l'URL pour ajouter un participant à un événement
///
/// [eventId] L'ID de l'événement
static String addParticipantWithEventId(String eventId) =>
'$eventsBase/$eventId/participants';
/// Retourne l'URL pour retirer un participant d'un événement
///
/// [eventId] L'ID de l'événement
/// [userId] L'ID de l'utilisateur à retirer
static String removeParticipantWithIds(String eventId, String userId) =>
'$eventsBase/$eventId/participants/$userId';
/// Retourne l'URL pour obtenir le nombre de participants d'un événement
///
/// [eventId] L'ID de l'événement
static String getNumberOfParticipantsWithEventId(String eventId) =>
'$eventsBase/$eventId/participants/count';
/// Retourne l'URL pour réagir à un événement (utilise favorite)
///
/// [eventId] L'ID de l'événement
/// [userId] L'ID de l'utilisateur
static String reactToEventWithId(String eventId, String userId) =>
'$eventsBase/$eventId/favorite?userId=$userId';
/// Retourne l'URL pour participer à un événement (utilise participants)
///
/// [eventId] L'ID de l'événement
static String participateInEventWithId(String eventId) =>
'$eventsBase/$eventId/participants';
// ============================================================================
// AMIS ET RELATIONS SOCIALES
// ============================================================================
/// Endpoint de base pour les opérations sur les amis
static String get friendsBase => '$baseUrl/friends';
/// Retourne l'URL pour obtenir les amis d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getFriendsWithUserId(String userId) =>
'$friendsBase/user/$userId';
/// Retourne l'URL pour ajouter un ami
///
/// [userId] L'ID de l'utilisateur
/// [friendId] L'ID de l'ami à ajouter
static String addFriendWithIds(String userId, String friendId) =>
'$friendsBase/$userId/$friendId';
/// Retourne l'URL pour supprimer un ami
///
/// [userId] L'ID de l'utilisateur
/// [friendId] L'ID de l'ami à supprimer
static String removeFriendWithIds(String userId, String friendId) =>
'$friendsBase/$userId/$friendId';
/// Retourne l'URL pour récupérer les demandes d'amitié en attente
///
/// [userId] L'ID de l'utilisateur
/// [page] Le numéro de la page (optionnel, par défaut 0)
/// [size] La taille de la page (optionnel, par défaut 10)
static String getPendingFriendRequestsWithUserId(String userId, {int page = 0, int size = 10}) =>
'$friendsBase/pending/$userId?page=$page&size=$size';
/// Retourne l'URL pour récupérer les demandes d'amitié envoyées
///
/// [userId] L'ID de l'utilisateur
/// [page] Le numéro de la page (optionnel, par défaut 0)
/// [size] La taille de la page (optionnel, par défaut 10)
static String getSentFriendRequestsWithUserId(String userId, {int page = 0, int size = 10}) =>
'$friendsBase/sent/$userId?page=$page&size=$size';
/// Retourne l'URL pour récupérer les demandes d'amitié reçues
///
/// [userId] L'ID de l'utilisateur
/// [page] Le numéro de la page (optionnel, par défaut 0)
/// [size] La taille de la page (optionnel, par défaut 10)
static String getReceivedFriendRequestsWithUserId(String userId, {int page = 0, int size = 10}) =>
'$friendsBase/received/$userId?page=$page&size=$size';
/// Retourne l'URL pour accepter une demande d'amitié
///
/// [friendshipId] L'ID de la relation d'amitié
static String acceptFriendRequestWithId(String friendshipId) =>
'$friendsBase/$friendshipId/accept';
/// Retourne l'URL pour rejeter une demande d'amitié
///
/// [friendshipId] L'ID de la relation d'amitié
static String rejectFriendRequestWithId(String friendshipId) =>
'$friendsBase/$friendshipId/reject';
// ============================================================================
// NOTIFICATIONS
// ============================================================================
/// Endpoint de base pour les opérations sur les notifications
static String get notificationsBase => '$baseUrl/notifications';
/// Retourne l'URL pour obtenir les notifications d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getNotificationsWithUserId(String userId) =>
'$notificationsBase/user/$userId';
/// Retourne l'URL pour marquer une notification comme lue
///
/// [notificationId] L'ID de la notification
static String markNotificationAsReadWithId(String notificationId) =>
'$notificationsBase/$notificationId/read';
/// Retourne l'URL pour marquer toutes les notifications comme lues
///
/// [userId] L'ID de l'utilisateur
static String markAllNotificationsAsReadWithUserId(String userId) =>
'$notificationsBase/user/$userId/mark-all-read';
/// Retourne l'URL pour supprimer une notification
///
/// [notificationId] L'ID de la notification
static String deleteNotificationWithId(String notificationId) =>
'$notificationsBase/$notificationId';
// ============================================================================
// POSTS SOCIAUX
// ============================================================================
/// Endpoint de base pour les opérations sur les posts sociaux
static String get postsBase => '$baseUrl/posts';
/// Retourne l'URL pour obtenir tous les posts (avec pagination)
static String get getAllPosts => postsBase;
/// Retourne l'URL pour créer un nouveau post
static String get createSocialPost => postsBase;
/// Retourne l'URL pour obtenir un post par son ID
///
/// [postId] L'ID du post
static String getSocialPostByIdWithId(String postId) => '$postsBase/$postId';
/// Retourne l'URL pour mettre à jour un post
///
/// [postId] L'ID du post
static String updateSocialPostWithId(String postId) => '$postsBase/$postId';
/// Retourne l'URL pour supprimer un post
///
/// [postId] L'ID du post
static String deleteSocialPostWithId(String postId) => '$postsBase/$postId';
/// Retourne l'URL pour rechercher des posts
///
/// [query] Le terme de recherche
static String searchSocialPostsWithQuery(String query) =>
'$postsBase/search?q=${Uri.encodeComponent(query)}';
/// Retourne l'URL pour liker un post
///
/// [postId] L'ID du post
static String likeSocialPostWithId(String postId) => '$postsBase/$postId/like';
/// Retourne l'URL pour commenter un post
///
/// [postId] L'ID du post
static String commentSocialPostWithId(String postId) =>
'$postsBase/$postId/comment';
/// Retourne l'URL pour partager un post
///
/// [postId] L'ID du post
static String shareSocialPostWithId(String postId) => '$postsBase/$postId/share';
/// Retourne l'URL pour obtenir les posts d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getSocialPostsByUserId(String userId) =>
'$postsBase/user/$userId';
// ============================================================================
// MÉTHODES UTILITAIRES
// ============================================================================
/// Construit une URL avec des paramètres de requête
///
/// [baseUrl] L'URL de base
/// [params] Les paramètres de requête (clé-valeur)
///
/// **Exemple:**
/// ```dart
/// final url = Urls.buildUrlWithParams(
/// Urls.searchEvents,
/// {'keyword': 'concert', 'category': 'music'},
/// );
/// // Résultat: 'http://api.com/events/search?keyword=concert&category=music'
/// ```
static String buildUrlWithParams(String baseUrl, Map<String, String> params) {
if (params.isEmpty) return baseUrl;
final queryString = params.entries
.map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.join('&');
return '$baseUrl?$queryString';
}
/// Valide qu'une URL est bien formée
///
/// [url] L'URL à valider
///
/// Returns `true` si l'URL est valide, `false` sinon
static bool isValidUrl(String url) {
try {
final uri = Uri.parse(url);
return uri.hasScheme && uri.hasAuthority;
} catch (e) {
return false;
}
}
}