Files
afterwork/lib/data/models/user_model.dart
dahoud 06031b01f2 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
2026-01-07 16:33:27 +00:00

224 lines
6.7 KiB
Dart

import '../../core/constants/env_config.dart';
import '../../domain/entities/user.dart';
/// Modèle de données pour les utilisateurs (Data Transfer Object).
///
/// Cette classe est responsable de la sérialisation/désérialisation
/// avec l'API backend et convertit vers/depuis l'entité de domaine [User].
///
/// **Usage:**
/// ```dart
/// // Depuis JSON
/// final user = UserModel.fromJson(jsonData);
///
/// // Vers JSON
/// final json = user.toJson();
///
/// // Vers entité de domaine
/// final entity = user.toEntity();
/// ```
class UserModel extends User {
/// Crée une nouvelle instance de [UserModel].
///
/// [userId] L'identifiant unique de l'utilisateur
/// [userLastName] Le nom de famille de l'utilisateur
/// [userFirstName] Le prénom de l'utilisateur
/// [email] L'adresse email de l'utilisateur
/// [motDePasse] Le mot de passe (hashé côté serveur)
/// [profileImageUrl] L'URL de l'image de profil
/// [eventsCount] Le nombre d'événements créés (optionnel)
/// [friendsCount] Le nombre d'amis (optionnel)
/// [postsCount] Le nombre de posts (optionnel)
/// [visitedPlacesCount] Le nombre de lieux visités (optionnel)
const UserModel({
required super.userId,
required super.userLastName,
required super.userFirstName,
required super.email,
required super.motDePasse,
required super.profileImageUrl,
super.eventsCount,
super.friendsCount,
super.postsCount,
super.visitedPlacesCount,
});
/// Crée un [UserModel] à partir d'un JSON reçu depuis l'API.
///
/// [json] Les données JSON à parser
///
/// Returns un [UserModel] avec les données parsées
///
/// **Note:** Les valeurs par défaut sont utilisées si des champs sont manquants.
///
/// **Exemple:**
/// ```dart
/// final json = {
/// 'userId': '123',
/// 'nom': 'Doe',
/// 'prenoms': 'John',
/// 'email': 'john@example.com',
/// };
/// final user = UserModel.fromJson(json);
/// ```
factory UserModel.fromJson(Map<String, dynamic> json) {
try {
// Le backend peut renvoyer 'uuid' ou 'userId', on accepte les deux
final userId = _parseString(json, 'userId', '') != ''
? _parseString(json, 'userId', '')
: _parseString(json, 'uuid', '');
return UserModel(
userId: userId.isNotEmpty ? userId : (json['uuid']?.toString() ?? json['userId']?.toString() ?? ''),
userLastName: _parseString(json, 'nom', 'Inconnu'),
userFirstName: _parseString(json, 'prenoms', 'Inconnu'),
email: _parseString(json, 'email', ''),
motDePasse: _parseString(json, 'motDePasse', ''),
profileImageUrl: _parseString(json, 'profileImageUrl', ''),
eventsCount: _parseInt(json, 'eventsCount') ?? 0,
friendsCount: _parseInt(json, 'friendsCount') ?? 0,
postsCount: _parseInt(json, 'postsCount') ?? 0,
visitedPlacesCount: _parseInt(json, 'visitedPlacesCount') ?? 0,
);
} catch (e) {
if (EnvConfig.enableDetailedLogs) {
print('[UserModel] Erreur lors du parsing JSON: $e');
}
rethrow;
}
}
/// Parse une valeur string depuis le JSON avec valeur par défaut.
static String _parseString(
Map<String, dynamic> json,
String key,
String defaultValue,
) {
final value = json[key];
if (value == null) return defaultValue;
return value.toString();
}
/// Parse une valeur int depuis le JSON (optionnel).
static int? _parseInt(Map<String, dynamic> json, String key) {
final value = json[key];
if (value == null) return null;
if (value is int) return value;
if (value is String) {
return int.tryParse(value);
}
return null;
}
/// Convertit ce [UserModel] en JSON pour l'envoi vers l'API.
///
/// Returns une [Map] contenant les données de l'utilisateur
///
/// **Note:** Le mot de passe est envoyé en clair (hashé côté serveur).
///
/// **Exemple:**
/// ```dart
/// final user = UserModel(...);
/// final json = user.toJson();
/// // Envoyer json à l'API
/// ```
@override
Map<String, dynamic> toJson() {
final json = <String, dynamic>{
if (userId.isNotEmpty) 'id': userId,
'nom': userLastName,
'prenoms': userFirstName,
'email': email,
if (motDePasse.isNotEmpty) 'motDePasse': motDePasse,
if (profileImageUrl.isNotEmpty) 'profileImageUrl': profileImageUrl,
};
// Ajouter les compteurs optionnels s'ils sont présents
if (eventsCount != null) {
json['eventsCount'] = eventsCount;
}
if (friendsCount != null) {
json['friendsCount'] = friendsCount;
}
if (postsCount != null) {
json['postsCount'] = postsCount;
}
if (visitedPlacesCount != null) {
json['visitedPlacesCount'] = visitedPlacesCount;
}
return json;
}
/// Convertit ce modèle vers une entité de domaine [User].
///
/// Returns une instance de [User] avec les mêmes données
///
/// **Exemple:**
/// ```dart
/// final model = UserModel.fromJson(json);
/// final entity = model.toEntity();
/// ```
User toEntity() {
return User(
userId: userId,
userLastName: userLastName,
userFirstName: userFirstName,
email: email,
motDePasse: motDePasse,
profileImageUrl: profileImageUrl,
eventsCount: eventsCount,
friendsCount: friendsCount,
postsCount: postsCount,
visitedPlacesCount: visitedPlacesCount,
);
}
/// Crée une copie de ce [UserModel] avec des valeurs modifiées.
///
/// Tous les paramètres sont optionnels. Seuls les paramètres fournis
/// seront modifiés dans la nouvelle instance.
///
/// **Exemple:**
/// ```dart
/// final updated = user.copyWith(
/// userFirstName: 'Jane',
/// profileImageUrl: 'https://example.com/new-image.jpg',
/// );
/// ```
UserModel copyWith({
String? userId,
String? userLastName,
String? userFirstName,
String? email,
String? motDePasse,
String? profileImageUrl,
int? eventsCount,
int? friendsCount,
int? postsCount,
int? visitedPlacesCount,
}) {
return UserModel(
userId: userId ?? this.userId,
userLastName: userLastName ?? this.userLastName,
userFirstName: userFirstName ?? this.userFirstName,
email: email ?? this.email,
motDePasse: motDePasse ?? this.motDePasse,
profileImageUrl: profileImageUrl ?? this.profileImageUrl,
eventsCount: eventsCount ?? this.eventsCount,
friendsCount: friendsCount ?? this.friendsCount,
postsCount: postsCount ?? this.postsCount,
visitedPlacesCount: visitedPlacesCount ?? this.visitedPlacesCount,
);
}
@override
String toString() {
return 'UserModel('
'userId: $userId, '
'name: $userFirstName $userLastName, '
'email: $email'
')';
}
}