Modifs MVVM
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
|
import 'package:em2rp/providers/users_provider.dart';
|
||||||
import 'package:em2rp/utils/auth_guard_widget.dart';
|
import 'package:em2rp/utils/auth_guard_widget.dart';
|
||||||
import 'package:em2rp/view_model/user_management_view_model.dart';
|
|
||||||
import 'package:em2rp/views/calendar_page.dart';
|
import 'package:em2rp/views/calendar_page.dart';
|
||||||
import 'package:em2rp/views/login_page.dart';
|
import 'package:em2rp/views/login_page.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
@ -10,8 +10,7 @@ import 'utils/colors.dart';
|
|||||||
import 'views/my_account_page.dart';
|
import 'views/my_account_page.dart';
|
||||||
import 'views/user_management_page.dart';
|
import 'views/user_management_page.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'providers/user_provider.dart';
|
import 'providers/local_user_provider.dart';
|
||||||
import 'providers/local_auth_provider.dart'; // Ajout de l'AuthProvider
|
|
||||||
import 'services/user_service.dart';
|
import 'services/user_service.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
@ -27,18 +26,13 @@ void main() async {
|
|||||||
// Injection du service UserService
|
// Injection du service UserService
|
||||||
Provider<UserService>(create: (_) => UserService()),
|
Provider<UserService>(create: (_) => UserService()),
|
||||||
|
|
||||||
// AuthProvider pour la gestion de l'authentification
|
// LocalUserProvider pour la gestion de l'authentification
|
||||||
ChangeNotifierProvider<LocalAuthProvider>(
|
ChangeNotifierProvider<LocalUserProvider>(
|
||||||
create: (context) => LocalAuthProvider()),
|
create: (context) => LocalUserProvider()),
|
||||||
|
|
||||||
// UserProvider déjà existant
|
// // Injection des Providers en utilisant UserService
|
||||||
ChangeNotifierProvider<UserProvider>(
|
ChangeNotifierProvider<UsersProvider>(
|
||||||
create: (context) => UserProvider()),
|
create: (context) => UsersProvider(context.read<UserService>()),
|
||||||
|
|
||||||
// Injection des ViewModels en utilisant UserService et AuthProvider
|
|
||||||
ChangeNotifierProvider<UserManagementViewModel>(
|
|
||||||
create: (context) =>
|
|
||||||
UserManagementViewModel(context.read<UserService>()),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: const MyApp(),
|
child: const MyApp(),
|
||||||
|
@ -41,4 +41,23 @@ class UserModel {
|
|||||||
'phoneNumber': phoneNumber,
|
'phoneNumber': phoneNumber,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserModel copyWith({
|
||||||
|
String? firstName,
|
||||||
|
String? lastName,
|
||||||
|
String? role,
|
||||||
|
String? profilePhotoUrl,
|
||||||
|
String? email,
|
||||||
|
String? phoneNumber,
|
||||||
|
}) {
|
||||||
|
return UserModel(
|
||||||
|
uid: uid, // L'UID ne change pas
|
||||||
|
firstName: firstName ?? this.firstName,
|
||||||
|
lastName: lastName ?? this.lastName,
|
||||||
|
role: role ?? this.role,
|
||||||
|
profilePhotoUrl: profilePhotoUrl ?? this.profilePhotoUrl,
|
||||||
|
email: email ?? this.email,
|
||||||
|
phoneNumber: phoneNumber ?? this.phoneNumber,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import '../models/user_model.dart';
|
|
||||||
|
|
||||||
class LocalAuthProvider with ChangeNotifier {
|
|
||||||
UserModel? _currentUser;
|
|
||||||
|
|
||||||
UserModel? get currentUser => _currentUser;
|
|
||||||
String? get role => _currentUser?.role;
|
|
||||||
|
|
||||||
void setUser(UserModel user) {
|
|
||||||
_currentUser = user;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearUser() {
|
|
||||||
_currentUser = null;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<UserCredential> signInWithEmailAndPassword(
|
|
||||||
String email, String password) async {
|
|
||||||
try {
|
|
||||||
UserCredential userCredential = await FirebaseAuth.instance
|
|
||||||
.signInWithEmailAndPassword(email: email, password: password);
|
|
||||||
|
|
||||||
DocumentSnapshot userDoc = await FirebaseFirestore.instance
|
|
||||||
.collection('users')
|
|
||||||
.doc(userCredential.user!.uid)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
if (userDoc.exists) {
|
|
||||||
setUser(UserModel.fromMap(
|
|
||||||
userDoc.data() as Map<String, dynamic>, userDoc.id));
|
|
||||||
} else {
|
|
||||||
throw FirebaseAuthException(
|
|
||||||
code: 'user-not-found',
|
|
||||||
message: "Aucune donnée utilisateur trouvée.");
|
|
||||||
}
|
|
||||||
return userCredential;
|
|
||||||
} on FirebaseAuthException catch (e) {
|
|
||||||
throw FirebaseAuthException(code: e.code, message: e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
108
em2rp/lib/providers/local_user_provider.dart
Normal file
108
em2rp/lib/providers/local_user_provider.dart
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import '../models/user_model.dart';
|
||||||
|
import '../utils/firebase_storage_manager.dart';
|
||||||
|
|
||||||
|
class LocalUserProvider with ChangeNotifier {
|
||||||
|
UserModel? _currentUser;
|
||||||
|
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||||
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
||||||
|
final FirebaseStorageManager _storageManager = FirebaseStorageManager();
|
||||||
|
|
||||||
|
UserModel? get currentUser => _currentUser;
|
||||||
|
String? get uid => _currentUser?.uid;
|
||||||
|
String? get firstName => _currentUser?.firstName;
|
||||||
|
String? get lastName => _currentUser?.lastName;
|
||||||
|
String? get role => _currentUser?.role ?? 'USER';
|
||||||
|
String? get profilePhotoUrl => _currentUser?.profilePhotoUrl;
|
||||||
|
String? get email => _currentUser?.email;
|
||||||
|
String? get phoneNumber => _currentUser?.phoneNumber;
|
||||||
|
|
||||||
|
/// Charge les données de l'utilisateur actuel
|
||||||
|
Future<void> loadUserData() async {
|
||||||
|
if (_auth.currentUser == null) return;
|
||||||
|
DocumentSnapshot userDoc =
|
||||||
|
await _firestore.collection('users').doc(_auth.currentUser!.uid).get();
|
||||||
|
if (userDoc.exists) {
|
||||||
|
setUser(UserModel.fromMap(
|
||||||
|
userDoc.data() as Map<String, dynamic>, userDoc.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Met à jour l'utilisateur
|
||||||
|
void setUser(UserModel user) {
|
||||||
|
_currentUser = user;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Efface les données utilisateur
|
||||||
|
void clearUser() {
|
||||||
|
_currentUser = null;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mise à jour des informations utilisateur
|
||||||
|
Future<void> updateUserData(
|
||||||
|
{String? firstName, String? lastName, String? phoneNumber}) async {
|
||||||
|
if (_currentUser == null) return;
|
||||||
|
try {
|
||||||
|
await _firestore.collection('users').doc(_currentUser!.uid).set({
|
||||||
|
'firstName': firstName ?? _currentUser!.firstName,
|
||||||
|
'lastName': lastName ?? _currentUser!.lastName,
|
||||||
|
'phone': phoneNumber ?? _currentUser!.phoneNumber,
|
||||||
|
}, SetOptions(merge: true));
|
||||||
|
|
||||||
|
_currentUser = _currentUser!.copyWith(
|
||||||
|
firstName: firstName ?? _currentUser!.firstName,
|
||||||
|
lastName: lastName ?? _currentUser!.lastName,
|
||||||
|
phoneNumber: phoneNumber ?? _currentUser!.phoneNumber,
|
||||||
|
);
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Erreur mise à jour utilisateur : $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Changement de photo de profil
|
||||||
|
Future<void> changeProfilePicture(XFile image) async {
|
||||||
|
if (_currentUser == null) return;
|
||||||
|
try {
|
||||||
|
String? newProfilePhotoUrl = await _storageManager.sendProfilePicture(
|
||||||
|
imageFile: image,
|
||||||
|
uid: _currentUser!.uid,
|
||||||
|
);
|
||||||
|
if (newProfilePhotoUrl != null) {
|
||||||
|
_firestore
|
||||||
|
.collection('users')
|
||||||
|
.doc(_currentUser!.uid)
|
||||||
|
.update({'profilePhotoUrl': newProfilePhotoUrl});
|
||||||
|
_currentUser =
|
||||||
|
_currentUser!.copyWith(profilePhotoUrl: newProfilePhotoUrl);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Erreur mise à jour photo de profil : $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connexion
|
||||||
|
Future<UserCredential> signInWithEmailAndPassword(
|
||||||
|
String email, String password) async {
|
||||||
|
try {
|
||||||
|
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
|
||||||
|
email: email, password: password);
|
||||||
|
await loadUserData();
|
||||||
|
return userCredential;
|
||||||
|
} catch (e) {
|
||||||
|
throw FirebaseAuthException(code: 'login-failed', message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Déconnexion
|
||||||
|
Future<void> signOut() async {
|
||||||
|
await _auth.signOut();
|
||||||
|
clearUser();
|
||||||
|
}
|
||||||
|
}
|
@ -1,58 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class UserProvider extends ChangeNotifier {
|
|
||||||
String? _uid;
|
|
||||||
String? _firstName;
|
|
||||||
String? _lastName;
|
|
||||||
String? _role;
|
|
||||||
String? _profilePictureUrl;
|
|
||||||
String? _email;
|
|
||||||
String? _phoneNumber;
|
|
||||||
|
|
||||||
String? get uid => _uid;
|
|
||||||
String? get firstName => _firstName;
|
|
||||||
String? get lastName => _lastName;
|
|
||||||
String? get role => _role;
|
|
||||||
String? get profilePhotoUrl => _profilePictureUrl;
|
|
||||||
String? get email => _email;
|
|
||||||
String? get phoneNumber => _phoneNumber;
|
|
||||||
|
|
||||||
void setUserData(Map<String, dynamic> userData, String uid) {
|
|
||||||
_uid = uid;
|
|
||||||
_firstName = userData['firstName'];
|
|
||||||
_lastName = userData['lastName'];
|
|
||||||
_role = userData['role'] ?? 'USER';
|
|
||||||
if (userData['profilePhotoUrl'] != "") {
|
|
||||||
_profilePictureUrl = userData['profilePhotoUrl'];
|
|
||||||
}
|
|
||||||
_email = userData['email'];
|
|
||||||
_phoneNumber = userData['phoneNumber'];
|
|
||||||
notifyListeners(); // Notify listeners that state has changed
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearUserData() {
|
|
||||||
_uid = null;
|
|
||||||
_firstName = null;
|
|
||||||
_lastName = null;
|
|
||||||
_role = null;
|
|
||||||
_profilePictureUrl = null;
|
|
||||||
_email = null;
|
|
||||||
_phoneNumber = null;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUserFirstName(String text) {
|
|
||||||
_firstName = text;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUserLastName(String text) {
|
|
||||||
_lastName = text;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUserPhoneNumber(String text) {
|
|
||||||
_phoneNumber = text;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,9 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../models/user_model.dart';
|
import '../models/user_model.dart';
|
||||||
import '../services/user_service.dart';
|
import '../services/user_service.dart';
|
||||||
|
|
||||||
class UserManagementViewModel extends ChangeNotifier {
|
class UsersProvider with ChangeNotifier {
|
||||||
final UserService _userService;
|
final UserService _userService;
|
||||||
List<UserModel> _users = [];
|
List<UserModel> _users = [];
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
@ -10,28 +11,33 @@ class UserManagementViewModel extends ChangeNotifier {
|
|||||||
List<UserModel> get users => _users;
|
List<UserModel> get users => _users;
|
||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
|
|
||||||
UserManagementViewModel(this._userService);
|
UsersProvider(this._userService);
|
||||||
|
|
||||||
|
/// Récupération de tous les utilisateurs
|
||||||
Future<void> fetchUsers() async {
|
Future<void> fetchUsers() async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
try {
|
||||||
_users = await _userService.fetchUsers();
|
_users = await _userService.fetchUsers();
|
||||||
|
} finally {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mise à jour d'un utilisateur
|
||||||
Future<void> updateUser(UserModel user) async {
|
Future<void> updateUser(UserModel user) async {
|
||||||
await _userService.updateUser(user);
|
await _userService.updateUser(user);
|
||||||
fetchUsers();
|
await fetchUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Suppression d'un utilisateur
|
||||||
Future<void> deleteUser(String uid) async {
|
Future<void> deleteUser(String uid) async {
|
||||||
await _userService.deleteUser(uid);
|
await _userService.deleteUser(uid);
|
||||||
fetchUsers();
|
await fetchUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Réinitialisation du mot de passe
|
||||||
Future<void> resetPassword(String email) async {
|
Future<void> resetPassword(String email) async {
|
||||||
await _userService.resetPassword(email);
|
await _userService.resetPassword(email);
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:em2rp/providers/local_auth_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:em2rp/providers/user_provider.dart';
|
|
||||||
import 'package:em2rp/views/login_page.dart';
|
import 'package:em2rp/views/login_page.dart';
|
||||||
|
|
||||||
class AuthGuard extends StatelessWidget {
|
class AuthGuard extends StatelessWidget {
|
||||||
@ -17,7 +16,7 @@ class AuthGuard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localAuthProvider = Provider.of<LocalAuthProvider>(context);
|
final localAuthProvider = Provider.of<LocalUserProvider>(context);
|
||||||
|
|
||||||
// Si l'utilisateur n'est pas connecté
|
// Si l'utilisateur n'est pas connecté
|
||||||
if (localAuthProvider.currentUser == null) {
|
if (localAuthProvider.currentUser == null) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import '../providers/local_auth_provider.dart';
|
import '../providers/local_user_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class LoginViewModel extends ChangeNotifier {
|
class LoginViewModel extends ChangeNotifier {
|
||||||
@ -19,7 +19,7 @@ class LoginViewModel extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<void> signIn(BuildContext context) async {
|
Future<void> signIn(BuildContext context) async {
|
||||||
final localAuthProvider =
|
final localAuthProvider =
|
||||||
Provider.of<LocalAuthProvider>(context, listen: false);
|
Provider.of<LocalUserProvider>(context, listen: false);
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
errorMessage = '';
|
errorMessage = '';
|
||||||
highlightPasswordField = false;
|
highlightPasswordField = false;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import 'package:em2rp/providers/local_auth_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
||||||
import 'package:provider/provider.dart'; // Import Provider
|
import 'package:provider/provider.dart'; // Import Provider
|
||||||
import 'package:em2rp/providers/user_provider.dart'; // Import UserProvider
|
|
||||||
import 'package:em2rp/utils/colors.dart';
|
import 'package:em2rp/utils/colors.dart';
|
||||||
|
|
||||||
class CalendarPage extends StatelessWidget {
|
class CalendarPage extends StatelessWidget {
|
||||||
@ -10,7 +9,7 @@ class CalendarPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localAuthProvider = Provider.of<LocalAuthProvider>(context);
|
final localAuthProvider = Provider.of<LocalUserProvider>(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Calendrier')),
|
appBar: AppBar(title: const Text('Calendrier')),
|
||||||
|
@ -1,229 +1,93 @@
|
|||||||
import 'package:em2rp/providers/local_auth_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:em2rp/providers/user_provider.dart';
|
import 'package:em2rp/providers/users_provider.dart';
|
||||||
import 'package:em2rp/utils/firebase_storage_manager.dart';
|
|
||||||
import 'package:em2rp/views/widgets/image/profile_picture.dart';
|
import 'package:em2rp/views/widgets/image/profile_picture.dart';
|
||||||
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
|
||||||
import 'package:em2rp/views/widgets/inputs/styled_text_field.dart';
|
import 'package:em2rp/views/widgets/inputs/styled_text_field.dart';
|
||||||
|
|
||||||
class MyAccountPage extends StatefulWidget {
|
class MyAccountPage extends StatelessWidget {
|
||||||
const MyAccountPage({super.key});
|
const MyAccountPage({super.key});
|
||||||
@override
|
|
||||||
_MyAccountPageState createState() => _MyAccountPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyAccountPageState extends State<MyAccountPage> {
|
|
||||||
final User? user = FirebaseAuth.instance.currentUser;
|
|
||||||
final TextEditingController _firstNameController = TextEditingController();
|
|
||||||
final TextEditingController _lastNameController = TextEditingController();
|
|
||||||
final TextEditingController _phoneController = TextEditingController();
|
|
||||||
String? profilePhotoUrl;
|
|
||||||
bool _isHoveringProfilePic = false;
|
|
||||||
final FirebaseStorageManager _storageManager =
|
|
||||||
FirebaseStorageManager(); // Instance of FirebaseStorageManager
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_loadUserData();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _loadUserData() async {
|
|
||||||
if (user != null) {
|
|
||||||
DocumentSnapshot userData = await FirebaseFirestore.instance
|
|
||||||
.collection('users')
|
|
||||||
.doc(user!.uid)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
if (userData.exists) {
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
_firstNameController.text = userData['firstName'] ?? '';
|
|
||||||
_lastNameController.text = userData['lastName'] ?? '';
|
|
||||||
_phoneController.text = userData['phone'] ?? '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _updateUserData() async {
|
|
||||||
if (user != null) {
|
|
||||||
try {
|
|
||||||
await FirebaseFirestore.instance.collection('users').doc(user!.uid).set(
|
|
||||||
{
|
|
||||||
'firstName': _firstNameController.text,
|
|
||||||
'lastName': _lastNameController.text,
|
|
||||||
'phone': _phoneController.text,
|
|
||||||
},
|
|
||||||
SetOptions(merge: true),
|
|
||||||
);
|
|
||||||
|
|
||||||
// **MISE À JOUR DU USERPROVIDER APRÈS SUCCÈS**
|
|
||||||
final userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
||||||
userProvider.setUserFirstName(_firstNameController.text);
|
|
||||||
userProvider.setUserLastName(_lastNameController.text);
|
|
||||||
userProvider.setUserPhoneNumber(_phoneController.text);
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content:
|
|
||||||
Text('Informations personnelles mises à jour avec succès!'),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'Erreur lors de la mise à jour des informations personnelles: ${e.toString()}',
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
print(
|
|
||||||
'Erreur lors de la mise à jour des informations utilisateur: ${e.toString()}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _changeProfilePicture() async {
|
|
||||||
final ImagePicker picker = ImagePicker();
|
|
||||||
final XFile? image = await picker.pickImage(
|
|
||||||
source: ImageSource.gallery,
|
|
||||||
); // You can also use ImageSource.camera
|
|
||||||
|
|
||||||
if (image != null) {
|
|
||||||
// Call FirebaseStorageManager to send the profile picture
|
|
||||||
String? newProfilePhotoUrl = await _storageManager.sendProfilePicture(
|
|
||||||
imageFile: image,
|
|
||||||
uid: user!.uid,
|
|
||||||
);
|
|
||||||
if (newProfilePhotoUrl != null) {
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
profilePhotoUrl =
|
|
||||||
newProfilePhotoUrl; // Update the profilePhotoUrl to refresh the UI
|
|
||||||
});
|
|
||||||
// Optionally, update the UserProvider if you are using it to manage user data globally
|
|
||||||
// Provider.of<UserProvider>(context, listen: false).setUserProfilePhotoUrl(newProfilePhotoUrl);
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Photo de profil mise à jour avec succès!'),
|
|
||||||
backgroundColor: Colors.green, // Optional: Style for success
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'Erreur lors de la mise à jour de la photo de profil.',
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.red, // Optional: Style for error
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// User cancelled image picking
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Sélection de photo annulée.')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localAuthProvider = Provider.of<LocalAuthProvider>(
|
|
||||||
context,
|
|
||||||
); // Get UserProvider instance
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar:
|
appBar: AppBar(title: const Text('Mon Compte')),
|
||||||
AppBar(title: const Text('Mon Compte')), // More user-friendly title
|
drawer: MainDrawer(currentPage: '/my_account'),
|
||||||
drawer: MainDrawer(
|
body: Consumer<LocalUserProvider>(
|
||||||
currentPage: '/my_account'), // Pass UserProvider to MainDrawer
|
builder: (context, userProvider, child) {
|
||||||
body: SingleChildScrollView(
|
final user = userProvider.currentUser;
|
||||||
// Added SingleChildScrollView for better responsiveness
|
final usersProvider = context.read<UsersProvider>();
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
|
final firstNameController =
|
||||||
|
TextEditingController(text: user.firstName);
|
||||||
|
final lastNameController = TextEditingController(text: user.lastName);
|
||||||
|
final phoneController = TextEditingController(text: user.phoneNumber);
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(
|
padding: const EdgeInsets.all(24.0),
|
||||||
24.0), // Increased padding around the main content
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
MouseRegion(
|
GestureDetector(
|
||||||
onEnter: (_) => setState(() => _isHoveringProfilePic = true),
|
//onTap: () => userProvider.changeProfilePicture(); TODO
|
||||||
onExit: (_) => setState(() => _isHoveringProfilePic = false),
|
|
||||||
cursor: SystemMouseCursors.click,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap:
|
|
||||||
_changeProfilePicture, // Call _changeProfilePicture on tap
|
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
ProfilePictureWidget(
|
ProfilePictureWidget(
|
||||||
userId: user!.uid,
|
userId: user.uid,
|
||||||
radius:
|
radius: 80,
|
||||||
80), // Increased radius for larger profile picture
|
|
||||||
if (_isHoveringProfilePic)
|
|
||||||
Container(
|
|
||||||
width: 160, // Slightly larger hover overlay
|
|
||||||
height: 160,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black54,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: const Center(
|
|
||||||
child: Icon(
|
|
||||||
Icons.edit,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 36, // Slightly larger edit icon
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Center(
|
Center(
|
||||||
child: Card(
|
child: Card(
|
||||||
elevation: 4.0, // Ajouter un léger relief
|
elevation: 4.0,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius:
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
BorderRadius.circular(12.0)), // Bords arrondis
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(
|
padding: const EdgeInsets.all(24.0),
|
||||||
24.0), // Padding intérieur de la carte
|
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
// Limiter la largeur des inputs dans la carte
|
constraints: const BoxConstraints(maxWidth: 500),
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxWidth:
|
|
||||||
500), // Ajustez la largeur maximale souhaitée
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
StyledTextField(
|
StyledTextField(
|
||||||
labelText: 'Prénom',
|
labelText: 'Prénom',
|
||||||
controller: _firstNameController),
|
controller: firstNameController,
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
StyledTextField(
|
StyledTextField(
|
||||||
labelText: 'Nom',
|
labelText: 'Nom',
|
||||||
controller: _lastNameController),
|
controller: lastNameController,
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
StyledTextField(
|
StyledTextField(
|
||||||
labelText: 'Numéro de téléphone',
|
labelText: 'Numéro de téléphone',
|
||||||
controller: _phoneController),
|
controller: phoneController,
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
StyledTextField(
|
StyledTextField(
|
||||||
labelText: 'Email',
|
labelText: 'Email',
|
||||||
controller:
|
controller:
|
||||||
TextEditingController(text: user?.email ?? ''),
|
TextEditingController(text: user.email),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: _updateUserData,
|
onPressed: () {
|
||||||
|
userProvider.updateUserData(
|
||||||
|
firstName: firstNameController.text,
|
||||||
|
lastName: lastNameController.text,
|
||||||
|
phoneNumber: phoneController.text,
|
||||||
|
);
|
||||||
|
},
|
||||||
child: const Text('Enregistrer'),
|
child: const Text('Enregistrer'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -235,6 +99,8 @@ class _MyAccountPageState extends State<MyAccountPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import 'package:em2rp/providers/local_auth_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../view_model/user_management_view_model.dart';
|
|
||||||
|
|
||||||
class UserManagementPage extends StatelessWidget {
|
class UserManagementPage extends StatelessWidget {
|
||||||
const UserManagementPage({super.key});
|
const UserManagementPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final userViewModel = Provider.of<UserManagementViewModel>(context);
|
// final userViewModel = Provider.of<UserManagementViewModel>(context);
|
||||||
final authProvider = Provider.of<LocalAuthProvider>(context);
|
final authProvider = Provider.of<LocalUserProvider>(context);
|
||||||
|
|
||||||
if (authProvider.role != 'ADMIN') {
|
if (authProvider.role != 'ADMIN') {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -22,46 +21,46 @@ class UserManagementPage extends StatelessWidget {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Gestion des Utilisateurs')),
|
appBar: AppBar(title: const Text('Gestion des Utilisateurs')),
|
||||||
body: userViewModel.isLoading
|
// body: userViewModel.isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
// ? const Center(child: CircularProgressIndicator())
|
||||||
: ListView.builder(
|
// : ListView.builder(
|
||||||
itemCount: userViewModel.users.length,
|
// itemCount: userViewModel.users.length,
|
||||||
itemBuilder: (context, index) {
|
// itemBuilder: (context, index) {
|
||||||
final user = userViewModel.users[index];
|
// final user = userViewModel.users[index];
|
||||||
return ListTile(
|
// return ListTile(
|
||||||
leading: CircleAvatar(
|
// leading: CircleAvatar(
|
||||||
backgroundImage: NetworkImage(user.profilePhotoUrl)),
|
// backgroundImage: NetworkImage(user.profilePhotoUrl)),
|
||||||
title: Text('${user.firstName} ${user.lastName}'),
|
// title: Text('${user.firstName} ${user.lastName}'),
|
||||||
subtitle: Text(user.email),
|
// subtitle: Text(user.email),
|
||||||
trailing: Row(
|
// trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
// mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
// children: [
|
||||||
IconButton(
|
// IconButton(
|
||||||
icon: const Icon(Icons.edit),
|
// icon: const Icon(Icons.edit),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
// Afficher la pop-up d'édition
|
// // Afficher la pop-up d'édition
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
IconButton(
|
// IconButton(
|
||||||
icon: const Icon(Icons.lock_reset),
|
// icon: const Icon(Icons.lock_reset),
|
||||||
onPressed: () =>
|
// onPressed: () =>
|
||||||
userViewModel.resetPassword(user.email),
|
// userViewModel.resetPassword(user.email),
|
||||||
),
|
// ),
|
||||||
IconButton(
|
// IconButton(
|
||||||
icon: const Icon(Icons.delete, color: Colors.red),
|
// icon: const Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () => userViewModel.deleteUser(user.uid),
|
// onPressed: () => userViewModel.deleteUser(user.uid),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
floatingActionButton: FloatingActionButton(
|
// floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
// Ajouter un utilisateur
|
// // Ajouter un utilisateur
|
||||||
},
|
// },
|
||||||
child: const Icon(Icons.add),
|
// child: const Icon(Icons.add),
|
||||||
),
|
// ),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:em2rp/providers/local_auth_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:em2rp/utils/colors.dart';
|
import 'package:em2rp/utils/colors.dart';
|
||||||
import 'package:em2rp/views/calendar_page.dart';
|
import 'package:em2rp/views/calendar_page.dart';
|
||||||
import 'package:em2rp/views/my_account_page.dart';
|
import 'package:em2rp/views/my_account_page.dart';
|
||||||
@ -14,7 +14,7 @@ class MainDrawer extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<LocalAuthProvider>(
|
return Consumer<LocalUserProvider>(
|
||||||
builder: (context, userProvider, child) {
|
builder: (context, userProvider, child) {
|
||||||
final hasUser = userProvider.currentUser != null;
|
final hasUser = userProvider.currentUser != null;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user