Bon checkpoint + refactoring
This commit is contained in:
@@ -13,22 +13,22 @@ import '../presentation/reservations/reservations_screen.dart';
|
|||||||
class AppRouter {
|
class AppRouter {
|
||||||
final EventRemoteDataSource eventRemoteDataSource;
|
final EventRemoteDataSource eventRemoteDataSource;
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
|
|
||||||
/// Constructeur de [AppRouter] initialisant les informations utilisateur
|
/// Constructeur de [AppRouter] initialisant les informations utilisateur
|
||||||
/// et la source de données pour les événements.
|
/// et la source de données pour les événements.
|
||||||
///
|
///
|
||||||
/// [eventRemoteDataSource] : Source de données pour les événements.
|
/// [eventRemoteDataSource] : Source de données pour les événements.
|
||||||
/// [userId], [userName], [userLastName] : Informations de l'utilisateur.
|
/// [userId], [userFirstName], [userLastName] : Informations de l'utilisateur.
|
||||||
AppRouter({
|
AppRouter({
|
||||||
required this.eventRemoteDataSource,
|
required this.eventRemoteDataSource,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
}) {
|
}) {
|
||||||
// Log d'initialisation avec les informations utilisateur
|
// Log d'initialisation avec les informations utilisateur
|
||||||
debugPrint("[LOG] AppRouter initialisé avec les infos utilisateur : $userId, $userName, $userLastName");
|
debugPrint("[LOG] AppRouter initialisé avec les infos utilisateur : $userId, $userFirstName, $userLastName");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Génère une route en fonction du [RouteSettings] fourni.
|
/// Génère une route en fonction du [RouteSettings] fourni.
|
||||||
@@ -49,7 +49,7 @@ class AppRouter {
|
|||||||
builder: (_) => HomeScreen(
|
builder: (_) => HomeScreen(
|
||||||
eventRemoteDataSource: eventRemoteDataSource,
|
eventRemoteDataSource: eventRemoteDataSource,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
userName: userName,
|
userFirstName: userFirstName,
|
||||||
userLastName: userLastName,
|
userLastName: userLastName,
|
||||||
userProfileImage: 'lib/assets/images/profile_picture.png',
|
userProfileImage: 'lib/assets/images/profile_picture.png',
|
||||||
),
|
),
|
||||||
@@ -60,7 +60,7 @@ class AppRouter {
|
|||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => EventScreen(
|
builder: (_) => EventScreen(
|
||||||
userId: userId,
|
userId: userId,
|
||||||
userName: userName,
|
userFirstName: userFirstName,
|
||||||
userLastName: userLastName,
|
userLastName: userLastName,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ class CreatorModel extends UserModel {
|
|||||||
|
|
||||||
}) : super(
|
}) : super(
|
||||||
userId: id,
|
userId: id,
|
||||||
nom: nom,
|
userLastName: nom,
|
||||||
prenoms: prenoms,
|
userFirstName: prenoms,
|
||||||
email: '', // Valeur par défaut vide
|
email: '', // Valeur par défaut vide
|
||||||
motDePasse: '', // Valeur par défaut vide
|
motDePasse: '', // Valeur par défaut vide
|
||||||
|
profileImageUrl: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
factory CreatorModel.fromJson(Map<String, dynamic> json) {
|
factory CreatorModel.fromJson(Map<String, dynamic> json) {
|
||||||
@@ -27,8 +28,8 @@ class CreatorModel extends UserModel {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'id': userId,
|
'id': userId,
|
||||||
'nom': nom,
|
'nom': userLastName,
|
||||||
'prenoms': prenoms,
|
'prenoms': userFirstName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ class ParticipantModel extends UserModel {
|
|||||||
required String prenoms,
|
required String prenoms,
|
||||||
}) : super(
|
}) : super(
|
||||||
userId: id,
|
userId: id,
|
||||||
nom: nom,
|
userLastName: nom,
|
||||||
prenoms: prenoms,
|
userFirstName: prenoms,
|
||||||
email: '', // Valeur par défaut vide
|
email: '', // Valeur par défaut vide
|
||||||
motDePasse: '', // Valeur par défaut vide
|
motDePasse: '', // Valeur par défaut vide
|
||||||
|
profileImageUrl: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
factory ParticipantModel.fromJson(Map<String, dynamic> json) {
|
factory ParticipantModel.fromJson(Map<String, dynamic> json) {
|
||||||
@@ -27,8 +28,8 @@ class ParticipantModel extends UserModel {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'id': userId,
|
'id': userId,
|
||||||
'nom': nom,
|
'nom': userLastName,
|
||||||
'prenoms': prenoms,
|
'prenoms': userFirstName,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,26 +5,29 @@ import '../../domain/entities/user.dart';
|
|||||||
class UserModel extends User {
|
class UserModel extends User {
|
||||||
UserModel({
|
UserModel({
|
||||||
required String userId,
|
required String userId,
|
||||||
required String nom,
|
required String userLastName,
|
||||||
required String prenoms,
|
required String userFirstName,
|
||||||
required String email,
|
required String email,
|
||||||
required String motDePasse,
|
required String motDePasse,
|
||||||
|
required String profileImageUrl,
|
||||||
}) : super(
|
}) : super(
|
||||||
userId: userId,
|
userId: userId,
|
||||||
nom: nom,
|
userLastName: userLastName,
|
||||||
prenoms: prenoms,
|
userFirstName: userFirstName,
|
||||||
email: email,
|
email: email,
|
||||||
motDePasse: motDePasse,
|
motDePasse: motDePasse,
|
||||||
|
profileImageUrl: profileImageUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Factory pour créer un `UserModel` à partir d'un JSON reçu depuis l'API.
|
/// Factory pour créer un `UserModel` à partir d'un JSON reçu depuis l'API.
|
||||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||||
return UserModel(
|
return UserModel(
|
||||||
userId: json['userId'] ?? '',
|
userId: json['userId'] ?? '',
|
||||||
nom: json['nom'] ?? 'Inconnu',
|
userLastName: json['nom'] ?? 'Inconnu',
|
||||||
prenoms: json['prenoms'] ?? 'Inconnu',
|
userFirstName: json['prenoms'] ?? 'Inconnu',
|
||||||
email: json['email'] ?? 'inconnu@example.com',
|
email: json['email'] ?? 'inconnu@example.com',
|
||||||
motDePasse: json['motDePasse'] ?? '',
|
motDePasse: json['motDePasse'] ?? '',
|
||||||
|
profileImageUrl: json['profileImageUrl'] ?? '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,10 +35,11 @@ class UserModel extends User {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'id': userId,
|
'id': userId,
|
||||||
'nom': nom,
|
'nom': userLastName,
|
||||||
'prenoms': prenoms,
|
'prenoms': userFirstName,
|
||||||
'email': email,
|
'email': email,
|
||||||
'motDePasse': motDePasse, // Mot de passe en clair (comme demandé temporairement)
|
'motDePasse': motDePasse, // Mot de passe en clair (comme demandé temporairement)
|
||||||
|
'profileImageUrl':profileImageUrl,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,65 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../domain/entities/user.dart';
|
||||||
|
|
||||||
/// [UserProvider] est un `ChangeNotifier` qui gère les informations de l'utilisateur.
|
/// [UserProvider] est un `ChangeNotifier` qui gère les informations complètes de l'utilisateur.
|
||||||
/// Toutes les modifications et actions sont loguées pour assurer une traçabilité complète dans le terminal.
|
/// Toutes les modifications et actions sont loguées pour assurer une traçabilité complète dans le terminal.
|
||||||
class UserProvider with ChangeNotifier {
|
class UserProvider with ChangeNotifier {
|
||||||
String _userId = '';
|
User _user = const User(
|
||||||
String _userName = '';
|
userId: '',
|
||||||
String _userLastName = '';
|
userLastName: '',
|
||||||
|
userFirstName: '',
|
||||||
|
email: '',
|
||||||
|
motDePasse: '',
|
||||||
|
profileImageUrl: '',
|
||||||
|
eventsCount: 0,
|
||||||
|
friendsCount: 0,
|
||||||
|
postsCount: 0,
|
||||||
|
visitedPlacesCount: 0,
|
||||||
|
);
|
||||||
|
|
||||||
/// Getter pour l'ID de l'utilisateur
|
/// Getter pour l'objet utilisateur.
|
||||||
String get userId => _userId;
|
User get user => _user;
|
||||||
|
|
||||||
/// Getter pour le nom de l'utilisateur
|
|
||||||
String get userName => _userName;
|
|
||||||
|
|
||||||
/// Getter pour le prénom de l'utilisateur
|
|
||||||
String get userLastName => _userLastName;
|
|
||||||
|
|
||||||
/// Méthode pour définir les informations de l'utilisateur.
|
/// Méthode pour définir les informations de l'utilisateur.
|
||||||
/// Logue les informations fournies et notifie les listeners des changements.
|
/// Logue les informations fournies et notifie les listeners des changements.
|
||||||
///
|
///
|
||||||
/// [id] : L'ID de l'utilisateur.
|
/// [user] : L'objet utilisateur contenant toutes les informations.
|
||||||
/// [name] : Le nom de l'utilisateur.
|
void setUser(User user) {
|
||||||
/// [lastName] : Le prénom de l'utilisateur.
|
debugPrint("[LOG] Tentative de définition des informations de l'utilisateur : ${user.toString()}");
|
||||||
void setUser(String id, String name, String lastName) {
|
|
||||||
debugPrint("[LOG] Tentative de définition des informations de l'utilisateur : ID = $id, Nom = $name, Prénom = $lastName");
|
|
||||||
|
|
||||||
_userId = id;
|
_user = user;
|
||||||
_userName = name;
|
|
||||||
_userLastName = lastName;
|
|
||||||
|
|
||||||
debugPrint("[LOG] Informations utilisateur définies : ID = $_userId, Nom = $_userName, Prénom = $_userLastName");
|
debugPrint("[LOG] Informations utilisateur définies : ${_user.toString()}");
|
||||||
|
|
||||||
|
// Notifie les widgets écoutant ce provider qu'une modification a eu lieu.
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Méthode pour mettre à jour des statistiques de l'utilisateur.
|
||||||
|
/// Cette méthode met à jour individuellement des attributs spécifiques comme le nombre d'amis ou d'événements.
|
||||||
|
void updateStatistics({
|
||||||
|
int? eventsCount,
|
||||||
|
int? friendsCount,
|
||||||
|
int? postsCount,
|
||||||
|
int? visitedPlacesCount,
|
||||||
|
}) {
|
||||||
|
debugPrint("[LOG] Mise à jour des statistiques utilisateur");
|
||||||
|
|
||||||
|
_user = User(
|
||||||
|
userId: _user.userId,
|
||||||
|
userLastName: _user.userLastName,
|
||||||
|
userFirstName: _user.userFirstName,
|
||||||
|
email: _user.email,
|
||||||
|
motDePasse: _user.motDePasse,
|
||||||
|
profileImageUrl: _user.profileImageUrl,
|
||||||
|
eventsCount: eventsCount ?? _user.eventsCount,
|
||||||
|
friendsCount: friendsCount ?? _user.friendsCount,
|
||||||
|
postsCount: postsCount ?? _user.postsCount,
|
||||||
|
visitedPlacesCount: visitedPlacesCount ?? _user.visitedPlacesCount,
|
||||||
|
);
|
||||||
|
|
||||||
|
debugPrint("[LOG] Nouvelles statistiques utilisateur : ${_user.toString()}");
|
||||||
|
|
||||||
// Notifie les widgets écoutant ce provider qu'une modification a eu lieu
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,15 +67,23 @@ class UserProvider with ChangeNotifier {
|
|||||||
/// Les valeurs sont loguées avant et après la réinitialisation.
|
/// Les valeurs sont loguées avant et après la réinitialisation.
|
||||||
void resetUser() {
|
void resetUser() {
|
||||||
debugPrint("[LOG] Réinitialisation des informations de l'utilisateur.");
|
debugPrint("[LOG] Réinitialisation des informations de l'utilisateur.");
|
||||||
debugPrint("[LOG] Valeurs avant réinitialisation : ID = $_userId, Nom = $_userName, Prénom = $_userLastName");
|
debugPrint("[LOG] Valeurs avant réinitialisation : ${_user.toString()}");
|
||||||
|
|
||||||
_userId = '';
|
_user = const User(
|
||||||
_userName = '';
|
userId: '',
|
||||||
_userLastName = '';
|
userLastName: '',
|
||||||
|
userFirstName: '',
|
||||||
|
email: '',
|
||||||
|
motDePasse: '',
|
||||||
|
profileImageUrl: '',
|
||||||
|
eventsCount: 0,
|
||||||
|
friendsCount: 0,
|
||||||
|
postsCount: 0,
|
||||||
|
visitedPlacesCount: 0,
|
||||||
|
);
|
||||||
|
|
||||||
debugPrint("[LOG] Informations utilisateur réinitialisées : ID = $_userId, Nom = $_userName, Prénom = $_userLastName");
|
debugPrint("[LOG] Informations utilisateur réinitialisées : ${_user.toString()}");
|
||||||
|
|
||||||
// Notifie les widgets écoutant ce provider que l'utilisateur a été réinitialisé
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,15 +60,15 @@ class PreferencesHelper {
|
|||||||
|
|
||||||
/// Sauvegarde le nom d'utilisateur dans les préférences.
|
/// Sauvegarde le nom d'utilisateur dans les préférences.
|
||||||
/// Logue l'opération pour assurer un suivi complet.
|
/// Logue l'opération pour assurer un suivi complet.
|
||||||
Future<void> saveUserName(String userName) async {
|
Future<void> saveUserName(String userFirstName) async {
|
||||||
print("[LOG] Sauvegarde du userName dans les préférences : $userName");
|
print("[LOG] Sauvegarde du userFirstName dans les préférences : $userFirstName");
|
||||||
await setString('user_name', userName);
|
await setString('user_name', userFirstName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Récupère le nom d'utilisateur depuis les préférences.
|
/// Récupère le nom d'utilisateur depuis les préférences.
|
||||||
/// Retourne le nom ou null en cas d'échec.
|
/// Retourne le nom ou null en cas d'échec.
|
||||||
Future<String?> getUserName() async {
|
Future<String?> getUseFirstrName() async {
|
||||||
print("[LOG] Récupération du userName depuis les préférences.");
|
print("[LOG] Récupération du userFirstName depuis les préférences.");
|
||||||
return await getString('user_name');
|
return await getString('user_name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ class PreferencesHelper {
|
|||||||
/// Supprime toutes les informations utilisateur dans les préférences.
|
/// Supprime toutes les informations utilisateur dans les préférences.
|
||||||
/// Logue chaque étape de la suppression.
|
/// Logue chaque étape de la suppression.
|
||||||
Future<void> clearUserInfo() async {
|
Future<void> clearUserInfo() async {
|
||||||
print("[LOG] Suppression des informations utilisateur (userId, userName, userLastName) des préférences.");
|
print("[LOG] Suppression des informations utilisateur (userId, userFirstName, userLastName) des préférences.");
|
||||||
await remove('user_id');
|
await remove('user_id');
|
||||||
await remove('user_name');
|
await remove('user_name');
|
||||||
await remove('user_last_name');
|
await remove('user_last_name');
|
||||||
|
|||||||
@@ -2,19 +2,40 @@ import 'package:equatable/equatable.dart';
|
|||||||
|
|
||||||
class User extends Equatable {
|
class User extends Equatable {
|
||||||
final String userId;
|
final String userId;
|
||||||
final String nom;
|
final String userLastName;
|
||||||
final String prenoms;
|
final String userFirstName;
|
||||||
final String email;
|
final String email;
|
||||||
final String motDePasse;
|
final String motDePasse;
|
||||||
|
final String profileImageUrl;
|
||||||
|
final int eventsCount;
|
||||||
|
final int friendsCount;
|
||||||
|
final int postsCount;
|
||||||
|
final int visitedPlacesCount;
|
||||||
|
|
||||||
const User({
|
const User({
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.nom,
|
required this.userLastName,
|
||||||
required this.prenoms,
|
required this.userFirstName,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.motDePasse,
|
required this.motDePasse,
|
||||||
|
required this.profileImageUrl,
|
||||||
|
this.eventsCount = 0,
|
||||||
|
this.friendsCount = 0,
|
||||||
|
this.postsCount = 0,
|
||||||
|
this.visitedPlacesCount = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [userId, nom, prenoms, email, motDePasse];
|
List<Object?> get props => [
|
||||||
|
userId,
|
||||||
|
userLastName,
|
||||||
|
userFirstName,
|
||||||
|
email,
|
||||||
|
motDePasse,
|
||||||
|
profileImageUrl,
|
||||||
|
eventsCount,
|
||||||
|
friendsCount,
|
||||||
|
postsCount,
|
||||||
|
visitedPlacesCount,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:afterwork/config/router.dart';
|
import 'package:afterwork/config/router.dart';
|
||||||
import 'package:afterwork/data/datasources/event_remote_data_source.dart';
|
import 'package:afterwork/data/datasources/event_remote_data_source.dart';
|
||||||
import 'package:afterwork/data/providers/user_provider.dart';
|
import 'package:afterwork/data/providers/user_provider.dart';
|
||||||
@@ -6,12 +5,15 @@ import 'package:afterwork/data/repositories/friends_repository_impl.dart';
|
|||||||
import 'package:afterwork/data/services/preferences_helper.dart';
|
import 'package:afterwork/data/services/preferences_helper.dart';
|
||||||
import 'package:afterwork/data/services/secure_storage.dart';
|
import 'package:afterwork/data/services/secure_storage.dart';
|
||||||
import 'package:afterwork/presentation/state_management/event_bloc.dart';
|
import 'package:afterwork/presentation/state_management/event_bloc.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'core/theme/theme_provider.dart';
|
import 'core/theme/theme_provider.dart';
|
||||||
import 'data/providers/friends_provider.dart';
|
import 'data/providers/friends_provider.dart';
|
||||||
|
import 'domain/entities/user.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -23,60 +25,68 @@ void main() async {
|
|||||||
final eventRemoteDataSource = EventRemoteDataSource(http.Client());
|
final eventRemoteDataSource = EventRemoteDataSource(http.Client());
|
||||||
final SecureStorage secureStorage = SecureStorage();
|
final SecureStorage secureStorage = SecureStorage();
|
||||||
final PreferencesHelper preferencesHelper = PreferencesHelper();
|
final PreferencesHelper preferencesHelper = PreferencesHelper();
|
||||||
final http.Client httpClient = http.Client(); // Nouvelle instance http.Client
|
final http.Client httpClient = http.Client();
|
||||||
|
|
||||||
// Récupération des informations stockées avec logs détaillés
|
// Récupération des informations stockées avec logs détaillés
|
||||||
String? userId = await secureStorage.getUserId();
|
String? userId = await secureStorage.getUserId();
|
||||||
String? userName = await preferencesHelper.getUserName();
|
String? userFirstName = await preferencesHelper.getUseFirstrName();
|
||||||
String? userLastName = await preferencesHelper.getUserLastName();
|
String? userLastName = await preferencesHelper.getUserLastName();
|
||||||
|
|
||||||
// Log de la récupération des informations
|
// Log de la récupération des informations
|
||||||
print("[LOG] Récupération des informations utilisateur : userId = $userId, userName = $userName, userLastName = $userLastName");
|
print("[LOG] Récupération des informations utilisateur : userId = $userId, userFirstName = $userFirstName, userLastName = $userLastName");
|
||||||
|
|
||||||
// Gestion des valeurs par défaut si les informations ne sont pas trouvées
|
// Gestion des valeurs par défaut si les informations ne sont pas trouvées
|
||||||
userId ??= 'default_user_id';
|
userId ??= 'default_user_id';
|
||||||
userName ??= 'Default';
|
userFirstName ??= 'Default';
|
||||||
userLastName ??= 'User';
|
userLastName ??= 'User';
|
||||||
|
|
||||||
// Log des valeurs par défaut appliquées
|
// Log des valeurs par défaut appliquées
|
||||||
print("[LOG] Valeurs par défaut appliquées : userId = $userId, userName = $userName, userLastName = $userLastName");
|
print("[LOG] Valeurs par défaut appliquées : userId = $userId, userFirstName = $userFirstName, userLastName = $userLastName");
|
||||||
|
|
||||||
|
// Création de l'objet User
|
||||||
|
final User user = User(
|
||||||
|
userId: userId,
|
||||||
|
userLastName: userLastName,
|
||||||
|
userFirstName: userFirstName,
|
||||||
|
email: 'user@example.com',
|
||||||
|
motDePasse: 'motDePasseHashé',
|
||||||
|
profileImageUrl: 'lib/assets/images/profile_picture.png',
|
||||||
|
eventsCount: 0,
|
||||||
|
friendsCount: 0,
|
||||||
|
postsCount: 0,
|
||||||
|
visitedPlacesCount: 0,
|
||||||
|
);
|
||||||
|
|
||||||
runApp(MyApp(
|
runApp(MyApp(
|
||||||
eventRemoteDataSource: eventRemoteDataSource,
|
eventRemoteDataSource: eventRemoteDataSource,
|
||||||
userId: userId,
|
user: user,
|
||||||
userName: userName,
|
httpClient: httpClient,
|
||||||
userLastName: userLastName,
|
|
||||||
httpClient: httpClient, // Passe l'instance client ici
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
final EventRemoteDataSource eventRemoteDataSource;
|
final EventRemoteDataSource eventRemoteDataSource;
|
||||||
final String userId;
|
final User user;
|
||||||
final String userName;
|
final http.Client httpClient;
|
||||||
final String userLastName;
|
|
||||||
final http.Client httpClient; // Ajout de ce paramètre
|
|
||||||
|
|
||||||
const MyApp({
|
const MyApp({
|
||||||
super.key,
|
super.key,
|
||||||
required this.eventRemoteDataSource,
|
required this.eventRemoteDataSource,
|
||||||
required this.userId,
|
required this.user,
|
||||||
required this.userName,
|
required this.httpClient,
|
||||||
required this.userLastName,
|
|
||||||
required this.httpClient, // Spécifier l'argument
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final friendsRepository = FriendsRepositoryImpl(client: httpClient); // Utilisation du client ici
|
final friendsRepository = FriendsRepositoryImpl(client: httpClient);
|
||||||
|
|
||||||
// Log lors de la construction de l'application
|
// Log lors de la construction de l'application
|
||||||
print("[LOG] Construction de l'application avec userId : $userId, userName : $userName, userLastName : $userLastName");
|
print("[LOG] Construction de l'application avec user : ${user.toString()}");
|
||||||
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider(
|
ChangeNotifierProvider(
|
||||||
create: (_) => UserProvider()..setUser(userId, userName, userLastName),
|
create: (_) => UserProvider()..setUser(user),
|
||||||
),
|
),
|
||||||
ChangeNotifierProvider(
|
ChangeNotifierProvider(
|
||||||
create: (_) => FriendsProvider(friendsRepository: friendsRepository),
|
create: (_) => FriendsProvider(friendsRepository: friendsRepository),
|
||||||
@@ -95,9 +105,9 @@ class MyApp extends StatelessWidget {
|
|||||||
theme: themeProvider.currentTheme,
|
theme: themeProvider.currentTheme,
|
||||||
onGenerateRoute: AppRouter(
|
onGenerateRoute: AppRouter(
|
||||||
eventRemoteDataSource: eventRemoteDataSource,
|
eventRemoteDataSource: eventRemoteDataSource,
|
||||||
userId: userId,
|
userId: user.userId,
|
||||||
userName: userName,
|
userFirstName: user.userFirstName,
|
||||||
userLastName: userLastName,
|
userLastName: user.userLastName,
|
||||||
).generateRoute,
|
).generateRoute,
|
||||||
initialRoute: '/',
|
initialRoute: '/',
|
||||||
);
|
);
|
||||||
@@ -106,3 +116,4 @@ class MyApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ import '../../widgets/image_preview_picker.dart';
|
|||||||
|
|
||||||
class AddEventPage extends StatefulWidget {
|
class AddEventPage extends StatefulWidget {
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
|
|
||||||
const AddEventPage({
|
const AddEventPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import '../../widgets/swipe_background.dart';
|
|||||||
class EventCard extends StatelessWidget {
|
class EventCard extends StatelessWidget {
|
||||||
final EventModel event;
|
final EventModel event;
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
final String status;
|
final String status;
|
||||||
final VoidCallback onReact;
|
final VoidCallback onReact;
|
||||||
@@ -25,7 +25,7 @@ class EventCard extends StatelessWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
required this.event,
|
required this.event,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
required this.status,
|
required this.status,
|
||||||
required this.onReact,
|
required this.onReact,
|
||||||
@@ -70,7 +70,7 @@ class EventCard extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
EventHeader(
|
EventHeader(
|
||||||
userName: userName,
|
userFirstName: userFirstName,
|
||||||
userLastName: userLastName,
|
userLastName: userLastName,
|
||||||
eventDate: event.startDate,
|
eventDate: event.startDate,
|
||||||
imageUrl: event.imageUrl,
|
imageUrl: event.imageUrl,
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import '../dialogs/add_event_dialog.dart';
|
|||||||
|
|
||||||
class EventScreen extends StatefulWidget {
|
class EventScreen extends StatefulWidget {
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
|
|
||||||
const EventScreen({
|
const EventScreen({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ class _EventScreenState extends State<EventScreen> {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => AddEventPage(
|
builder: (context) => AddEventPage(
|
||||||
userId: widget.userId,
|
userId: widget.userId,
|
||||||
userName: widget.userName,
|
userFirstName: widget.userFirstName,
|
||||||
userLastName: widget.userLastName,
|
userLastName: widget.userLastName,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -78,7 +78,7 @@ class _EventScreenState extends State<EventScreen> {
|
|||||||
key: ValueKey(event.id),
|
key: ValueKey(event.id),
|
||||||
event: event,
|
event: event,
|
||||||
userId: widget.userId,
|
userId: widget.userId,
|
||||||
userName: widget.userName,
|
userFirstName: widget.userFirstName,
|
||||||
userLastName: widget.userLastName,
|
userLastName: widget.userLastName,
|
||||||
onReact: () => _onReact(event.id),
|
onReact: () => _onReact(event.id),
|
||||||
onComment: () => _onComment(event.id),
|
onComment: () => _onComment(event.id),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import '../friends/friends_screen.dart'; // Écran des amis
|
|||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
final EventRemoteDataSource eventRemoteDataSource;
|
final EventRemoteDataSource eventRemoteDataSource;
|
||||||
final String userId;
|
final String userId;
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
final String userProfileImage; // Image de profil de l'utilisateur
|
final String userProfileImage; // Image de profil de l'utilisateur
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ class HomeScreen extends StatefulWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
required this.eventRemoteDataSource,
|
required this.eventRemoteDataSource,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
required this.userProfileImage, // Passer l'image de profil ici
|
required this.userProfileImage, // Passer l'image de profil ici
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@@ -127,7 +127,7 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
|
|||||||
const HomeContentScreen(),
|
const HomeContentScreen(),
|
||||||
EventScreen(
|
EventScreen(
|
||||||
userId: widget.userId,
|
userId: widget.userId,
|
||||||
userName: widget.userName,
|
userFirstName: widget.userFirstName,
|
||||||
userLastName: widget.userLastName,
|
userLastName: widget.userLastName,
|
||||||
),
|
),
|
||||||
const EstablishmentsScreen(),
|
const EstablishmentsScreen(),
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import 'package:provider/provider.dart';
|
|||||||
import '../../../core/errors/exceptions.dart';
|
import '../../../core/errors/exceptions.dart';
|
||||||
import '../../../core/theme/theme_provider.dart';
|
import '../../../core/theme/theme_provider.dart';
|
||||||
import '../../../data/datasources/event_remote_data_source.dart';
|
import '../../../data/datasources/event_remote_data_source.dart';
|
||||||
|
import '../../../data/providers/user_provider.dart';
|
||||||
|
import '../../../domain/entities/user.dart';
|
||||||
import '../signup/SignUpScreen.dart';
|
import '../signup/SignUpScreen.dart';
|
||||||
|
|
||||||
/// L'écran de connexion où les utilisateurs peuvent s'authentifier.
|
/// L'écran de connexion où les utilisateurs peuvent s'authentifier.
|
||||||
@@ -102,30 +104,41 @@ class _LoginScreenState extends State<LoginScreen>
|
|||||||
_formKey.currentState!.save(); // Sauvegarde des données saisies
|
_formKey.currentState!.save(); // Sauvegarde des données saisies
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_btnController.start(); // Démarre l'animation de chargement du bouton
|
_btnController.start();
|
||||||
debugPrint("[LOG] Appel à l'API pour authentifier l'utilisateur.");
|
debugPrint("[LOG] Appel à l'API pour authentifier l'utilisateur.");
|
||||||
|
|
||||||
// Appel à l'API pour authentifier l'utilisateur
|
|
||||||
final UserModel user = await _userRemoteDataSource.authenticateUser(_email, _password);
|
final UserModel user = await _userRemoteDataSource.authenticateUser(_email, _password);
|
||||||
|
|
||||||
// Validation de l'ID utilisateur
|
|
||||||
if (user.userId.isNotEmpty) {
|
if (user.userId.isNotEmpty) {
|
||||||
debugPrint("[LOG] Utilisateur authentifié avec succès. ID: ${user.userId}");
|
debugPrint("[LOG] Utilisateur authentifié avec succès. ID: ${user.userId}");
|
||||||
|
|
||||||
// Sauvegarde des informations utilisateur
|
|
||||||
await _secureStorage.saveUserId(user.userId);
|
await _secureStorage.saveUserId(user.userId);
|
||||||
await _preferencesHelper.saveUserName(user.nom);
|
await _preferencesHelper.saveUserName(user.userLastName);
|
||||||
await _preferencesHelper.saveUserLastName(user.prenoms);
|
await _preferencesHelper.saveUserLastName(user.userFirstName);
|
||||||
|
|
||||||
|
// Met à jour le `UserProvider` avec les informations utilisateur authentifiées
|
||||||
|
final userProvider = Provider.of<UserProvider>(context, listen: false);
|
||||||
|
userProvider.setUser(User(
|
||||||
|
userId: user.userId,
|
||||||
|
userLastName: user.userLastName,
|
||||||
|
userFirstName: user.userFirstName,
|
||||||
|
email: user.email,
|
||||||
|
motDePasse: 'motDePasseHashé',
|
||||||
|
profileImageUrl: 'lib/assets/images/profile_picture.png',
|
||||||
|
eventsCount: user.eventsCount ?? 0,
|
||||||
|
friendsCount: user.friendsCount ?? 0,
|
||||||
|
postsCount: user.postsCount ?? 0,
|
||||||
|
visitedPlacesCount: user.visitedPlacesCount ?? 0,
|
||||||
|
));
|
||||||
|
|
||||||
_showToast("Connexion réussie !");
|
_showToast("Connexion réussie !");
|
||||||
// Redirection vers l'écran d'accueil
|
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => HomeScreen(
|
builder: (context) => HomeScreen(
|
||||||
userId: user.userId,
|
userId: user.userId,
|
||||||
userName: user.nom,
|
userFirstName: user.userFirstName,
|
||||||
userLastName: user.prenoms,
|
userLastName: user.userLastName,
|
||||||
userProfileImage: 'lib/assets/images/profile_picture.png',
|
userProfileImage: 'lib/assets/images/profile_picture.png',
|
||||||
eventRemoteDataSource: EventRemoteDataSource(http.Client()),
|
eventRemoteDataSource: EventRemoteDataSource(http.Client()),
|
||||||
),
|
),
|
||||||
@@ -136,25 +149,17 @@ class _LoginScreenState extends State<LoginScreen>
|
|||||||
_showToast("Erreur : ID utilisateur manquant.");
|
_showToast("Erreur : ID utilisateur manquant.");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Gestion des erreurs spécifiques et log de chaque type d'erreur
|
// Gestion des erreurs
|
||||||
if (e is ServerExceptionWithMessage) {
|
|
||||||
debugPrint("[ERROR] Erreur serveur : ${e.message}");
|
|
||||||
_showToast("Erreur serveur : ${e.message}");
|
|
||||||
} else if (e is UnauthorizedException) {
|
|
||||||
debugPrint("[ERROR] Erreur d'authentification : ${e.message}");
|
|
||||||
_showToast("Erreur : ${e.message}");
|
|
||||||
} else {
|
|
||||||
debugPrint("[ERROR] Erreur lors de la connexion : $e");
|
debugPrint("[ERROR] Erreur lors de la connexion : $e");
|
||||||
_showToast("Erreur lors de la connexion : ${e.toString()}");
|
_showToast("Erreur lors de la connexion : ${e.toString()}");
|
||||||
}
|
_btnController.error();
|
||||||
_btnController.error(); // Affiche une erreur sur le bouton
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_showErrorMessage = true;
|
_showErrorMessage = true;
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
_btnController.reset(); // Réinitialise l'état du bouton
|
_btnController.reset();
|
||||||
setState(() {
|
setState(() {
|
||||||
_isSubmitting = false; // Réinitialise l'état de chargement
|
_isSubmitting = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,129 +1,92 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import '../../../core/constants/colors.dart';
|
import '../../../core/constants/colors.dart';
|
||||||
|
import '../../../data/providers/user_provider.dart';
|
||||||
|
import '../../widgets/account_deletion_card.dart';
|
||||||
|
import '../../widgets/custom_list_tile.dart';
|
||||||
|
import '../../widgets/edit_options_card.dart';
|
||||||
|
import '../../widgets/expandable_section_card.dart';
|
||||||
|
import '../../widgets/profile_header.dart';
|
||||||
|
import '../../widgets/statistics_section_card.dart';
|
||||||
|
import '../../widgets/support_section_card.dart';
|
||||||
|
import '../../widgets/user_info_card.dart';
|
||||||
|
|
||||||
|
|
||||||
class ProfileScreen extends StatelessWidget {
|
class ProfileScreen extends StatelessWidget {
|
||||||
const ProfileScreen({super.key});
|
const ProfileScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print("Affichage de l'écran de profil.");
|
final userProvider = Provider.of<UserProvider>(context);
|
||||||
|
final user = userProvider.user;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColors.backgroundColor,
|
backgroundColor: AppColors.backgroundColor,
|
||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverAppBar(
|
ProfileHeader(user: user),
|
||||||
expandedHeight: 200.0,
|
|
||||||
floating: false,
|
|
||||||
pinned: true,
|
|
||||||
backgroundColor: AppColors.darkPrimary,
|
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
|
||||||
title: Text(
|
|
||||||
'Profil',
|
|
||||||
style: TextStyle(
|
|
||||||
color: AppColors.accentColor,
|
|
||||||
fontSize: 20.0,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
background: Image.asset(
|
|
||||||
'lib/assets/images/profile_picture.png',
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.settings, color: Colors.white),
|
|
||||||
onPressed: () {
|
|
||||||
print("Bouton des paramètres cliqué.");
|
|
||||||
// Logique de navigation vers les paramètres
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SliverList(
|
SliverList(
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate(
|
||||||
[
|
[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildUserInfoCard(),
|
UserInfoCard(user: user),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildEditOptionsCard(),
|
const EditOptionsCard(),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildStatisticsSectionCard(),
|
StatisticsSectionCard(user: user),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildExpandableSectionCard(
|
ExpandableSectionCard(
|
||||||
title: 'Historique',
|
title: 'Historique',
|
||||||
icon: Icons.history,
|
icon: Icons.history,
|
||||||
children: [
|
children: [
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.event_note,
|
icon: Icons.event_note,
|
||||||
label: 'Historique des Événements',
|
label: 'Historique des Événements',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès à l'historique des événements."),
|
||||||
print("Accès à l'historique des événements.");
|
|
||||||
// Logique de navigation vers l'historique des événements
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.history,
|
icon: Icons.history,
|
||||||
label: 'Historique des Publications',
|
label: 'Historique des Publications',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès à l'historique des publications."),
|
||||||
print("Accès à l'historique des publications.");
|
|
||||||
// Logique de navigation vers l'historique des publications
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.bookmark,
|
icon: Icons.bookmark,
|
||||||
label: 'Historique de Réservations',
|
label: 'Historique de Réservations',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès à l'historique des réservations."),
|
||||||
print("Accès à l'historique des réservations.");
|
|
||||||
// Logique de navigation vers l'historique des réservations
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildExpandableSectionCard(
|
ExpandableSectionCard(
|
||||||
title: 'Préférences et Paramètres',
|
title: 'Préférences et Paramètres',
|
||||||
icon: Icons.settings,
|
icon: Icons.settings,
|
||||||
children: [
|
children: [
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.privacy_tip,
|
icon: Icons.privacy_tip,
|
||||||
label: 'Paramètres de confidentialité',
|
label: 'Paramètres de confidentialité',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès aux paramètres de confidentialité."),
|
||||||
print("Accès aux paramètres de confidentialité.");
|
|
||||||
// Logique de navigation vers les paramètres de confidentialité
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.notifications,
|
icon: Icons.notifications,
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès aux paramètres de notifications."),
|
||||||
print("Accès aux paramètres de notifications.");
|
|
||||||
// Logique de navigation vers les notifications
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.language,
|
icon: Icons.language,
|
||||||
label: 'Langue de l\'application',
|
label: 'Langue de l\'application',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès aux paramètres de langue."),
|
||||||
print("Accès aux paramètres de langue.");
|
|
||||||
// Logique de navigation vers les paramètres de langue
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildAnimatedListTile(
|
CustomListTile(
|
||||||
icon: Icons.format_paint,
|
icon: Icons.format_paint,
|
||||||
label: 'Thème de l\'application',
|
label: 'Thème de l\'application',
|
||||||
onTap: () {
|
onTap: () => print("[LOG] Accès aux paramètres de thème."),
|
||||||
print("Accès aux paramètres de thème.");
|
|
||||||
// Logique de navigation vers les paramètres de thème
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildSupportSectionCard(),
|
const SupportSectionCard(),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
_buildAccountDeletionCard(context),
|
AccountDeletionCard(context: context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -131,302 +94,4 @@ class ProfileScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUserInfoCard() {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
CircleAvatar(
|
|
||||||
radius: 50,
|
|
||||||
backgroundImage: AssetImage('lib/assets/images/profile_picture.png'),
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
const Text(
|
|
||||||
'GBANE Dahoud',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
letterSpacing: 1.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
Text(
|
|
||||||
'pseudo',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.grey[400],
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
Text(
|
|
||||||
'gbanedahoud@lions.dev',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey[600],
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildEditOptionsCard() {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.edit,
|
|
||||||
label: 'Éditer le profil',
|
|
||||||
onTap: () {
|
|
||||||
print("Édition du profil.");
|
|
||||||
// Logique de navigation vers l'édition du profil
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.camera_alt,
|
|
||||||
label: 'Changer la photo de profil',
|
|
||||||
onTap: () {
|
|
||||||
print("Changement de la photo de profil.");
|
|
||||||
// Logique de changement de la photo de profil
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.lock,
|
|
||||||
label: 'Changer le mot de passe',
|
|
||||||
onTap: () {
|
|
||||||
print("Changement du mot de passe.");
|
|
||||||
// Logique de changement de mot de passe
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildStatisticsSectionCard() {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'Statistiques Personnelles',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
_buildStatTile(
|
|
||||||
icon: Icons.event,
|
|
||||||
label: 'Événements Participés',
|
|
||||||
value: '12',
|
|
||||||
),
|
|
||||||
_buildStatTile(
|
|
||||||
icon: Icons.place,
|
|
||||||
label: 'Établissements Visités',
|
|
||||||
value: '8',
|
|
||||||
),
|
|
||||||
_buildStatTile(
|
|
||||||
icon: Icons.post_add,
|
|
||||||
label: 'Publications',
|
|
||||||
value: '24',
|
|
||||||
),
|
|
||||||
_buildStatTile(
|
|
||||||
icon: Icons.group,
|
|
||||||
label: 'Amis/Followers',
|
|
||||||
value: '150',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildExpandableSectionCard({
|
|
||||||
required String title,
|
|
||||||
required IconData icon,
|
|
||||||
required List<Widget> children,
|
|
||||||
}) {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: ExpansionTile(
|
|
||||||
title: Text(
|
|
||||||
title,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
leading: Icon(icon, color: AppColors.accentColor),
|
|
||||||
iconColor: AppColors.accentColor,
|
|
||||||
collapsedIconColor: AppColors.accentColor,
|
|
||||||
children: children,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildSupportSectionCard() {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.all(16.0),
|
|
||||||
child: Text(
|
|
||||||
'Support et Assistance',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.help,
|
|
||||||
label: 'Support et Assistance',
|
|
||||||
onTap: () {
|
|
||||||
print("Accès au Support et Assistance.");
|
|
||||||
// Logique de navigation vers le support
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.article,
|
|
||||||
label: 'Conditions d\'utilisation',
|
|
||||||
onTap: () {
|
|
||||||
print("Accès aux conditions d'utilisation.");
|
|
||||||
// Logique de navigation vers les conditions d'utilisation
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_buildAnimatedListTile(
|
|
||||||
icon: Icons.privacy_tip,
|
|
||||||
label: 'Politique de confidentialité',
|
|
||||||
onTap: () {
|
|
||||||
print("Accès à la politique de confidentialité.");
|
|
||||||
// Logique de navigation vers la politique de confidentialité
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAccountDeletionCard(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
color: AppColors.cardColor,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
||||||
elevation: 2,
|
|
||||||
child: ListTile(
|
|
||||||
leading: const Icon(Icons.delete, color: Colors.redAccent),
|
|
||||||
title: const Text(
|
|
||||||
'Supprimer le compte',
|
|
||||||
style: TextStyle(color: Colors.redAccent, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
_showDeleteConfirmationDialog(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showDeleteConfirmationDialog(BuildContext context) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
backgroundColor: AppColors.backgroundColor,
|
|
||||||
title: const Text(
|
|
||||||
'Confirmer la suppression',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
content: const Text(
|
|
||||||
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.',
|
|
||||||
style: TextStyle(color: Colors.white70),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Annuler',
|
|
||||||
style: TextStyle(color: AppColors.accentColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
print("Suppression du compte confirmée.");
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: const Text(
|
|
||||||
'Supprimer',
|
|
||||||
style: TextStyle(color: Colors.redAccent),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAnimatedListTile({
|
|
||||||
required IconData icon,
|
|
||||||
required String label,
|
|
||||||
required VoidCallback onTap,
|
|
||||||
}) {
|
|
||||||
return InkWell(
|
|
||||||
onTap: onTap,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
splashColor: Colors.blueAccent.withOpacity(0.2),
|
|
||||||
child: ListTile(
|
|
||||||
leading: Icon(icon, color: AppColors.accentColor),
|
|
||||||
title: Text(
|
|
||||||
label,
|
|
||||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildStatTile({
|
|
||||||
required IconData icon,
|
|
||||||
required String label,
|
|
||||||
required String value,
|
|
||||||
}) {
|
|
||||||
return ListTile(
|
|
||||||
leading: Icon(icon, color: AppColors.accentColor),
|
|
||||||
title: Text(label, style: const TextStyle(color: Colors.white)),
|
|
||||||
trailing: Text(
|
|
||||||
value,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,10 +81,11 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
|||||||
// Créer l'utilisateur avec les informations fournies
|
// Créer l'utilisateur avec les informations fournies
|
||||||
final UserModel user = UserModel(
|
final UserModel user = UserModel(
|
||||||
userId: '', // L'ID sera généré côté serveur
|
userId: '', // L'ID sera généré côté serveur
|
||||||
nom: _nom,
|
userLastName: _nom,
|
||||||
prenoms: _prenoms,
|
userFirstName: _prenoms,
|
||||||
email: _email,
|
email: _email,
|
||||||
motDePasse: _password, // Le mot de passe sera envoyé en clair pour l'instant
|
motDePasse: _password, // Le mot de passe sera envoyé en clair pour l'instant
|
||||||
|
profileImageUrl: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Envoi des informations pour créer un nouvel utilisateur
|
// Envoi des informations pour créer un nouvel utilisateur
|
||||||
@@ -94,8 +95,8 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
|||||||
|
|
||||||
// Sauvegarder les informations de l'utilisateur
|
// Sauvegarder les informations de l'utilisateur
|
||||||
await _secureStorage.saveUserId(createdUser.userId);
|
await _secureStorage.saveUserId(createdUser.userId);
|
||||||
await _preferencesHelper.saveUserName(createdUser.nom);
|
await _preferencesHelper.saveUserName(createdUser.userLastName);
|
||||||
await _preferencesHelper.saveUserLastName(createdUser.prenoms);
|
await _preferencesHelper.saveUserLastName(createdUser.userFirstName);
|
||||||
|
|
||||||
// Rediriger vers la page d'accueil ou une page de confirmation
|
// Rediriger vers la page d'accueil ou une page de confirmation
|
||||||
Navigator.pushReplacementNamed(context, '/home');
|
Navigator.pushReplacementNamed(context, '/home');
|
||||||
|
|||||||
61
lib/presentation/widgets/account_deletion_card.dart
Normal file
61
lib/presentation/widgets/account_deletion_card.dart
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
|
||||||
|
class AccountDeletionCard extends StatelessWidget {
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
const AccountDeletionCard({Key? key, required this.context}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: ListTile(
|
||||||
|
leading: const Icon(Icons.delete, color: Colors.redAccent),
|
||||||
|
title: const Text(
|
||||||
|
'Supprimer le compte',
|
||||||
|
style: TextStyle(color: Colors.redAccent, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
onTap: () => _showDeleteConfirmationDialog(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showDeleteConfirmationDialog() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: AppColors.backgroundColor,
|
||||||
|
title: const Text(
|
||||||
|
'Confirmer la suppression',
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
content: const Text(
|
||||||
|
'Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible.',
|
||||||
|
style: TextStyle(color: Colors.white70),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('Annuler', style: TextStyle(color: AppColors.accentColor)),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
print("[LOG] Suppression du compte confirmée.");
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
// Logique de suppression du compte
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
'Supprimer',
|
||||||
|
style: TextStyle(color: Colors.redAccent),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
lib/presentation/widgets/custom_list_tile.dart
Normal file
31
lib/presentation/widgets/custom_list_tile.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
|
||||||
|
class CustomListTile extends StatelessWidget {
|
||||||
|
final IconData icon;
|
||||||
|
final String label;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
const CustomListTile({
|
||||||
|
Key? key,
|
||||||
|
required this.icon,
|
||||||
|
required this.label,
|
||||||
|
required this.onTap,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
splashColor: Colors.blueAccent.withOpacity(0.2),
|
||||||
|
child: ListTile(
|
||||||
|
leading: Icon(icon, color: AppColors.accentColor),
|
||||||
|
title: Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
lib/presentation/widgets/edit_options_card.dart
Normal file
35
lib/presentation/widgets/edit_options_card.dart
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'custom_list_tile.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
|
||||||
|
class EditOptionsCard extends StatelessWidget {
|
||||||
|
const EditOptionsCard({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.edit,
|
||||||
|
label: 'Éditer le profil',
|
||||||
|
onTap: () => print("[LOG] Édition du profil."),
|
||||||
|
),
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.camera_alt,
|
||||||
|
label: 'Changer la photo de profil',
|
||||||
|
onTap: () => print("[LOG] Changement de la photo de profil."),
|
||||||
|
),
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.lock,
|
||||||
|
label: 'Changer le mot de passe',
|
||||||
|
onTap: () => print("[LOG] Changement du mot de passe."),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import 'package:afterwork/core/utils/date_formatter.dart';
|
|||||||
import 'event_menu.dart';
|
import 'event_menu.dart';
|
||||||
|
|
||||||
class EventHeader extends StatelessWidget {
|
class EventHeader extends StatelessWidget {
|
||||||
final String userName;
|
final String userFirstName;
|
||||||
final String userLastName;
|
final String userLastName;
|
||||||
final String? eventDate;
|
final String? eventDate;
|
||||||
final String? imageUrl;
|
final String? imageUrl;
|
||||||
@@ -14,7 +14,7 @@ class EventHeader extends StatelessWidget {
|
|||||||
|
|
||||||
const EventHeader({
|
const EventHeader({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.userName,
|
required this.userFirstName,
|
||||||
required this.userLastName,
|
required this.userLastName,
|
||||||
this.eventDate,
|
this.eventDate,
|
||||||
this.imageUrl,
|
this.imageUrl,
|
||||||
@@ -51,7 +51,7 @@ class EventHeader extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'$userName $userLastName',
|
'$userFirstName $userLastName',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class EventList extends StatelessWidget {
|
|||||||
return EventCard(
|
return EventCard(
|
||||||
event: event,
|
event: event,
|
||||||
userId: 'user_id_here', // Vous pouvez passer l'ID réel de l'utilisateur connecté
|
userId: 'user_id_here', // Vous pouvez passer l'ID réel de l'utilisateur connecté
|
||||||
userName: 'John', // Vous pouvez passer le prénom réel de l'utilisateur
|
userFirstName: 'John', // Vous pouvez passer le prénom réel de l'utilisateur
|
||||||
userLastName: 'Doe', // Vous pouvez passer le nom réel de l'utilisateur
|
userLastName: 'Doe', // Vous pouvez passer le nom réel de l'utilisateur
|
||||||
onReact: () => _handleReact(event),
|
onReact: () => _handleReact(event),
|
||||||
onComment: () => _handleComment(event),
|
onComment: () => _handleComment(event),
|
||||||
|
|||||||
38
lib/presentation/widgets/expandable_section_card.dart
Normal file
38
lib/presentation/widgets/expandable_section_card.dart
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
|
||||||
|
class ExpandableSectionCard extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final IconData icon;
|
||||||
|
final List<Widget> children;
|
||||||
|
|
||||||
|
const ExpandableSectionCard({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.icon,
|
||||||
|
required this.children,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: ExpansionTile(
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: Icon(icon, color: AppColors.accentColor),
|
||||||
|
iconColor: AppColors.accentColor,
|
||||||
|
collapsedIconColor: AppColors.accentColor,
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ class FriendsCircle extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Combine firstName et lastName ou utilise "Ami inconnu" par défaut.
|
// Combine firstName et lastName ou utilise "Ami inconnu" par défaut.
|
||||||
String displayName = [friend.firstName, friend.lastName]
|
String displayName = [friend.firstName, friend.lastName]
|
||||||
.where((namePart) => namePart != null && namePart.isNotEmpty)
|
.where((namePart) => namePart.isNotEmpty)
|
||||||
.join(" ")
|
.join(" ")
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
|
|||||||
109
lib/presentation/widgets/profile_header.dart
Normal file
109
lib/presentation/widgets/profile_header.dart
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
import '../../../../data/providers/user_provider.dart';
|
||||||
|
import '../../../../domain/entities/user.dart';
|
||||||
|
|
||||||
|
/// [ProfileHeader] est un widget qui affiche l'en-tête du profil utilisateur.
|
||||||
|
/// Comprend le nom de l'utilisateur, une image de fond, et un bouton de déconnexion avec confirmation.
|
||||||
|
class ProfileHeader extends StatelessWidget {
|
||||||
|
final User user;
|
||||||
|
|
||||||
|
const ProfileHeader({Key? key, required this.user}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SliverAppBar(
|
||||||
|
expandedHeight: 200.0,
|
||||||
|
floating: false,
|
||||||
|
pinned: true,
|
||||||
|
backgroundColor: AppColors.darkPrimary,
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
'Profil de ${user.userFirstName}',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.accentColor,
|
||||||
|
fontSize: 20.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background: Image.network(
|
||||||
|
user.profileImageUrl,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
// Log en cas d'erreur de chargement de l'image
|
||||||
|
print("[ERROR] Erreur lors du chargement de l'image de profil : $error");
|
||||||
|
return Image.asset('lib/assets/images/default_avatar.png', fit: BoxFit.cover);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.logout, color: Colors.white),
|
||||||
|
onPressed: () {
|
||||||
|
print("[LOG] Bouton de déconnexion cliqué."); // Log du clic du bouton de déconnexion
|
||||||
|
_showLogoutConfirmationDialog(context); // Affiche le dialogue de confirmation
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Affiche une boîte de dialogue de confirmation pour la déconnexion.
|
||||||
|
/// Log chaque action et résultat dans le terminal.
|
||||||
|
void _showLogoutConfirmationDialog(BuildContext context) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
// Log affichage du dialogue
|
||||||
|
print("[LOG] Affichage de la boîte de dialogue de confirmation de déconnexion.");
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: AppColors.backgroundColor,
|
||||||
|
title: const Text(
|
||||||
|
'Confirmer la déconnexion',
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
content: const Text(
|
||||||
|
'Voulez-vous vraiment vous déconnecter ?',
|
||||||
|
style: TextStyle(color: Colors.white70),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// Bouton d'annulation de la déconnexion
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
print("[LOG] Déconnexion annulée par l'utilisateur.");
|
||||||
|
Navigator.of(context).pop(); // Ferme le dialogue sans déconnecter
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Annuler',
|
||||||
|
style: TextStyle(color: AppColors.accentColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Bouton de confirmation de la déconnexion
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
print("[LOG] Déconnexion confirmée."); // Log de la confirmation
|
||||||
|
Provider.of<UserProvider>(context, listen: false).resetUser(); // Réinitialise les infos utilisateur
|
||||||
|
print("[LOG] Informations utilisateur réinitialisées dans UserProvider.");
|
||||||
|
|
||||||
|
Navigator.of(context).pop(); // Ferme la boîte de dialogue
|
||||||
|
print("[LOG] Boîte de dialogue de confirmation fermée.");
|
||||||
|
|
||||||
|
Navigator.of(context).pushReplacementNamed('/'); // Redirige vers l'écran de connexion
|
||||||
|
print("[LOG] Redirection vers l'écran de connexion.");
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
'Déconnexion',
|
||||||
|
style: TextStyle(color: Colors.redAccent),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).then((_) {
|
||||||
|
// Log lorsque le dialogue est fermé pour toute raison (confirmation ou annulation)
|
||||||
|
print("[LOG] La boîte de dialogue de confirmation de déconnexion est fermée.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
31
lib/presentation/widgets/stat_tile.dart
Normal file
31
lib/presentation/widgets/stat_tile.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
|
||||||
|
class StatTile extends StatelessWidget {
|
||||||
|
final IconData icon;
|
||||||
|
final String label;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
const StatTile({
|
||||||
|
Key? key,
|
||||||
|
required this.icon,
|
||||||
|
required this.label,
|
||||||
|
required this.value,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(icon, color: AppColors.accentColor),
|
||||||
|
title: Text(label, style: const TextStyle(color: Colors.white)),
|
||||||
|
trailing: Text(
|
||||||
|
value,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
lib/presentation/widgets/statistics_section_card.dart
Normal file
40
lib/presentation/widgets/statistics_section_card.dart
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
import '../../../../domain/entities/user.dart';
|
||||||
|
import 'stat_tile.dart';
|
||||||
|
|
||||||
|
class StatisticsSectionCard extends StatelessWidget {
|
||||||
|
final User user;
|
||||||
|
|
||||||
|
const StatisticsSectionCard({Key? key, required this.user}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Statistiques Personnelles',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
StatTile(icon: Icons.event, label: 'Événements Participés', value: '${user.eventsCount}'),
|
||||||
|
StatTile(icon: Icons.place, label: 'Établissements Visités', value: '${user.visitedPlacesCount}'),
|
||||||
|
StatTile(icon: Icons.post_add, label: 'Publications', value: '${user.postsCount}'),
|
||||||
|
StatTile(icon: Icons.group, label: 'Amis/Followers', value: '${user.friendsCount}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
lib/presentation/widgets/support_section_card.dart
Normal file
46
lib/presentation/widgets/support_section_card.dart
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
import 'custom_list_tile.dart';
|
||||||
|
|
||||||
|
class SupportSectionCard extends StatelessWidget {
|
||||||
|
const SupportSectionCard({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(16.0),
|
||||||
|
child: Text(
|
||||||
|
'Support et Assistance',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.help,
|
||||||
|
label: 'Support et Assistance',
|
||||||
|
onTap: () => print("[LOG] Accès au Support et Assistance."),
|
||||||
|
),
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.article,
|
||||||
|
label: 'Conditions d\'utilisation',
|
||||||
|
onTap: () => print("[LOG] Accès aux conditions d'utilisation."),
|
||||||
|
),
|
||||||
|
CustomListTile(
|
||||||
|
icon: Icons.privacy_tip,
|
||||||
|
label: 'Politique de confidentialité',
|
||||||
|
onTap: () => print("[LOG] Accès à la politique de confidentialité."),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
lib/presentation/widgets/user_info_card.dart
Normal file
49
lib/presentation/widgets/user_info_card.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../../core/constants/colors.dart';
|
||||||
|
import '../../../../domain/entities/user.dart';
|
||||||
|
|
||||||
|
class UserInfoCard extends StatelessWidget {
|
||||||
|
final User user;
|
||||||
|
|
||||||
|
const UserInfoCard({Key? key, required this.user}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: AppColors.cardColor,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
|
elevation: 2,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
radius: 50,
|
||||||
|
backgroundImage: NetworkImage(user.profileImageUrl),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
'${user.userFirstName} ${user.userLastName}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
letterSpacing: 1.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Text(
|
||||||
|
user.email,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user