Auth réparée
This commit is contained in:
parent
3c5d3b4c5a
commit
d3813bfcdb
17
em2rp/.vscode/launch.json
vendored
17
em2rp/.vscode/launch.json
vendored
@ -4,7 +4,22 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "Attach to Chrome",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "chrome",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"preLaunchTask": "npm: vite",
|
||||
|
||||
},
|
||||
{
|
||||
"name": "Launch Chrome",
|
||||
"request": "launch",
|
||||
"type": "chrome",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Launch Edge",
|
||||
"request": "launch",
|
||||
|
@ -31,68 +31,50 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
print("test");
|
||||
return MaterialApp(
|
||||
title: 'EM2 ERP',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.red,
|
||||
primaryColor: AppColors.noir,
|
||||
colorScheme:
|
||||
ColorScheme.fromSwatch().copyWith(secondary: AppColors.rouge),
|
||||
textTheme: const TextTheme(
|
||||
bodyMedium: TextStyle(color: AppColors.noir),
|
||||
),
|
||||
// Personnalisation de l'InputDecorationTheme pour les text fields
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
// Bordure lorsqu'il est focus
|
||||
borderSide:
|
||||
BorderSide(color: AppColors.noir), // Couleur rouge quand focus
|
||||
title: 'EM2 ERP',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.red,
|
||||
primaryColor: AppColors.noir,
|
||||
colorScheme:
|
||||
ColorScheme.fromSwatch().copyWith(secondary: AppColors.rouge),
|
||||
textTheme: const TextTheme(
|
||||
bodyMedium: TextStyle(color: AppColors.noir),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
// Bordure par défaut (non focus)
|
||||
borderSide:
|
||||
BorderSide(color: AppColors.gris), // Couleur grise par défaut
|
||||
),
|
||||
labelStyle: TextStyle(color: AppColors.noir), // Couleur du label
|
||||
hintStyle: TextStyle(color: AppColors.gris), // Couleur du hint text
|
||||
// Tu peux personnaliser d'autres propriétés ici :
|
||||
// fillColor, filled, iconColor, prefixStyle, suffixStyle, etc.
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor:
|
||||
AppColors.blanc, // Couleur du texte du bouton (ici blanc)
|
||||
backgroundColor: AppColors
|
||||
.noir, // Couleur de fond du bouton (si tu veux aussi changer le fond)
|
||||
// Autres styles possibles pour les boutons :
|
||||
// textStyle, padding, shape, elevation, etc.
|
||||
),
|
||||
),
|
||||
),
|
||||
routes: {
|
||||
'/login': (context) => const LoginPage(),
|
||||
'/calendar': (context) => const CalendarPage(),
|
||||
'/my_account': (context) => const MyAccountPage(),
|
||||
'/user_management': (context) => const UserManagementPage(),
|
||||
},
|
||||
// Conditionally set home based on authentication state
|
||||
home: StreamBuilder<User?>(
|
||||
stream: FirebaseAuth.instance.authStateChanges(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.active) {
|
||||
User? user = snapshot.data;
|
||||
if (user == null) {
|
||||
return const LoginPage(); // User not logged in, show LoginPage
|
||||
}
|
||||
return const CalendarPage(); // User logged in, show CalendarPage
|
||||
}
|
||||
// Checking auth state, show loading indicator
|
||||
return const Scaffold(
|
||||
body: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
// Personnalisation de l'InputDecorationTheme pour les text fields
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
// Bordure lorsqu'il est focus
|
||||
borderSide: BorderSide(
|
||||
color: AppColors.noir), // Couleur rouge quand focus
|
||||
),
|
||||
);
|
||||
enabledBorder: OutlineInputBorder(
|
||||
// Bordure par défaut (non focus)
|
||||
borderSide:
|
||||
BorderSide(color: AppColors.gris), // Couleur grise par défaut
|
||||
),
|
||||
labelStyle: TextStyle(color: AppColors.noir), // Couleur du label
|
||||
hintStyle: TextStyle(color: AppColors.gris), // Couleur du hint text
|
||||
// Tu peux personnaliser d'autres propriétés ici :
|
||||
// fillColor, filled, iconColor, prefixStyle, suffixStyle, etc.
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor:
|
||||
AppColors.blanc, // Couleur du texte du bouton (ici blanc)
|
||||
backgroundColor: AppColors
|
||||
.noir, // Couleur de fond du bouton (si tu veux aussi changer le fond)
|
||||
// Autres styles possibles pour les boutons :
|
||||
// textStyle, padding, shape, elevation, etc.
|
||||
),
|
||||
),
|
||||
),
|
||||
routes: {
|
||||
'/login': (context) => const LoginPage(),
|
||||
'/calendar': (context) => const CalendarPage(),
|
||||
'/my_account': (context) => const MyAccountPage(),
|
||||
'/user_management': (context) => const UserManagementPage(),
|
||||
},
|
||||
),
|
||||
);
|
||||
// Conditionally set home based on authentication state
|
||||
home: LoginPage());
|
||||
}
|
||||
}
|
||||
|
@ -5,27 +5,38 @@ class UserProvider extends ChangeNotifier {
|
||||
String? _firstName;
|
||||
String? _lastName;
|
||||
String? _role;
|
||||
String? _profilePictureUrl;
|
||||
// String? _profilePictureUrl;
|
||||
String? _email;
|
||||
String? _phoneNumber;
|
||||
// String? _phoneNumber;
|
||||
|
||||
String? get uid => _uid;
|
||||
String? get firstName => _firstName;
|
||||
String? get lastName => _lastName;
|
||||
String? get role => _role;
|
||||
String? get profilePhotoUrl => _profilePictureUrl;
|
||||
// String? get profilePhotoUrl => _profilePictureUrl;
|
||||
String? get email => _email;
|
||||
String? get phoneNumber => _phoneNumber;
|
||||
// String? get phoneNumber => _phoneNumber;
|
||||
|
||||
// void setUserData(Map<String, dynamic> userData, String uid) {
|
||||
// _uid = uid;
|
||||
// _firstName = userData['firstName'];
|
||||
// _lastName = userData['lastName'];
|
||||
// _role = userData['role'] ?? 'USER'; // Default role if not provided
|
||||
// // _profilePictureUrl = userData['profilePhotoUrl'];
|
||||
// _email = userData['email'];
|
||||
// // _phoneNumber = userData['phoneNumber'];
|
||||
// notifyListeners(); // Notify listeners that state has changed
|
||||
// }
|
||||
void setUserData(Map<String, dynamic> userData, String uid) {
|
||||
_uid = uid;
|
||||
_firstName = userData['firstName'];
|
||||
_lastName = userData['lastName'];
|
||||
_role = userData['role'] ?? 'USER'; // Default role if not provided
|
||||
_profilePictureUrl = userData['profilePhotoUrl'];
|
||||
_email = userData['email'];
|
||||
_phoneNumber = userData['phoneNumber'];
|
||||
notifyListeners(); // Notify listeners that state has changed
|
||||
|
||||
print("User data set: $_firstName $_lastName ($_email)");
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void clearUserData() {
|
||||
@ -33,9 +44,9 @@ class UserProvider extends ChangeNotifier {
|
||||
_firstName = null;
|
||||
_lastName = null;
|
||||
_role = null;
|
||||
_profilePictureUrl = null;
|
||||
// _profilePictureUrl = null;
|
||||
_email = null;
|
||||
_phoneNumber = null;
|
||||
// _phoneNumber = null;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
||||
import 'package:provider/provider.dart'; // Import Provider
|
||||
import 'package:em2rp/providers/user_provider.dart'; // Import UserProvider
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:em2rp/providers/user_provider.dart';
|
||||
import 'package:em2rp/views/widgets/auth/forgot_password_dialog.dart';
|
||||
import 'package:em2rp/views/widgets/auth/mail_textfield.dart';
|
||||
import 'package:em2rp/views/widgets/error_message.dart';
|
||||
import 'package:em2rp/views/widgets/auth/forgot_password_button.dart';
|
||||
@ -11,6 +10,7 @@ import 'package:em2rp/views/widgets/auth/password_textfield.dart';
|
||||
import 'package:em2rp/views/widgets/auth/welcome_text.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:em2rp/views/widgets/auth/forgot_password_dialog.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
@ -33,13 +33,11 @@ class _LoginPageState extends State<LoginPage> {
|
||||
void dispose() {
|
||||
_emailController.dispose();
|
||||
_passwordController.dispose();
|
||||
print("LoginPage DISPOSED");
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loginUser() async {
|
||||
if (!mounted) return; // Early exit if widget is unmounted
|
||||
|
||||
Future<void> _signInWithEmailAndPassword() async {
|
||||
// Pas de vérification mounted ici, le widget reste monté pendant toute l'opération
|
||||
setState(() {
|
||||
_errorMessage = '';
|
||||
_isLoading = true;
|
||||
@ -47,95 +45,54 @@ class _LoginPageState extends State<LoginPage> {
|
||||
_highlightEmailField = false;
|
||||
});
|
||||
|
||||
String email = _emailController.text.trim();
|
||||
String password = _passwordController.text;
|
||||
|
||||
try {
|
||||
// 1. Sign in with Firebase Authentication
|
||||
UserCredential userCredential = await FirebaseAuth.instance
|
||||
.signInWithEmailAndPassword(email: email, password: password);
|
||||
User? user = userCredential.user;
|
||||
final UserCredential userCredential =
|
||||
await FirebaseAuth.instance.signInWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text,
|
||||
);
|
||||
final uid = userCredential.user!.uid;
|
||||
|
||||
if (user != null) {
|
||||
// 2. Fetch user data from Firestore
|
||||
print(
|
||||
"Fetching user data from Firestore..."); // Log before Firestore fetch
|
||||
DocumentSnapshot userDoc = await FirebaseFirestore.instance
|
||||
.collection('users')
|
||||
.doc(user.uid)
|
||||
.get();
|
||||
print("Firestore DocumentSnapshot retrieved."); // Log after fetch
|
||||
final DocumentSnapshot userDoc =
|
||||
await FirebaseFirestore.instance.collection('users').doc(uid).get();
|
||||
|
||||
if (userDoc.exists) {
|
||||
print("Firestore Document Exists: true"); // Log doc exists check
|
||||
print("Document ID: ${userDoc.id}"); // Log document ID
|
||||
print(
|
||||
"Before data cast - userDoc.data(): ${userDoc.data()}"); // Log raw data before cast
|
||||
if (userDoc.exists) {
|
||||
print("User document found: ${userDoc.data()}");
|
||||
Provider.of<UserProvider>(context, listen: false)
|
||||
.setUserData(userDoc.data() as Map<String, dynamic>, uid);
|
||||
|
||||
Map<String, dynamic> userData =
|
||||
userDoc.data() as Map<String, dynamic>;
|
||||
|
||||
print(
|
||||
"After data cast - userData: $userData"); // Log userData after cast
|
||||
|
||||
// 3. Store user data in UserProvider
|
||||
final userProvider =
|
||||
Provider.of<UserProvider>(context, listen: false);
|
||||
print(
|
||||
"Before setUserData call - userProvider: $userProvider"); // Log userProvider instance
|
||||
userProvider.setUserData(
|
||||
userData, user.uid); // Store user data in provider
|
||||
print("After setUserData call"); // Log after setUserData is called
|
||||
|
||||
print(
|
||||
'Login successful! Role: ${userProvider.role}'); // Log success and role
|
||||
if (mounted) {
|
||||
Navigator.of(context).pushReplacementNamed(
|
||||
'/calendar'); // 4. Navigate to CalendarPage
|
||||
}
|
||||
} else {
|
||||
// User document not found in Firestore
|
||||
print(
|
||||
"Firestore Document Exists: false"); // Log doc exists check - false
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_errorMessage =
|
||||
"Erreur: Utilisateur non trouvé dans la base de données.";
|
||||
});
|
||||
}
|
||||
print('Login Error: Firestore user document not found');
|
||||
}
|
||||
// Maintenant que toutes les données sont chargées, naviguer vers CalendarPage.
|
||||
Navigator.of(context).pushReplacementNamed('/calendar');
|
||||
} else {
|
||||
setState(() {
|
||||
_errorMessage = "Aucune donnée utilisateur trouvée.";
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
} on FirebaseAuthException catch (e) {
|
||||
// Firebase Authentication error
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
if (e.code == 'user-not-found' || e.code == 'wrong-password') {
|
||||
_errorMessage = "Email ou mot de passe incorrect.";
|
||||
_highlightPasswordField = true;
|
||||
_highlightEmailField = true;
|
||||
} else if (e.code == 'invalid-email') {
|
||||
_errorMessage = "Adresse email invalide.";
|
||||
_highlightEmailField = true;
|
||||
} else {
|
||||
_errorMessage = "Erreur de connexion. Veuillez réessayer.";
|
||||
}
|
||||
});
|
||||
}
|
||||
print('Login Error (FirebaseAuth): ${e.code} - ${e.message}');
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
if (e.code == 'user-not-found' || e.code == 'wrong-password') {
|
||||
_errorMessage = "Email ou mot de passe incorrect.";
|
||||
_highlightPasswordField = true;
|
||||
_highlightEmailField = true;
|
||||
} else {
|
||||
_errorMessage = "Erreur de connexion. Veuillez réessayer.";
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_errorMessage =
|
||||
"Erreur lors de la récupération des données utilisateur.";
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _togglePasswordVisibility() {
|
||||
if (mounted) setState(() => _obscurePassword = !_obscurePassword);
|
||||
setState(() {
|
||||
_obscurePassword = !_obscurePassword;
|
||||
});
|
||||
}
|
||||
|
||||
void _forgotPassword() {
|
||||
@ -151,9 +108,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) => constraints.maxWidth > 900
|
||||
? _buildLargeScreenLayout(context)
|
||||
: _buildSmallScreenLayout(context),
|
||||
builder: (context, constraints) {
|
||||
if (constraints.maxWidth > 900) {
|
||||
return _buildLargeScreenLayout(context);
|
||||
} else {
|
||||
return _buildSmallScreenLayout(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -161,11 +122,15 @@ class _LoginPageState extends State<LoginPage> {
|
||||
Widget _buildLargeScreenLayout(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
const Expanded(flex: 6, child: ImageSectionWidget()),
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: const ImageSectionWidget(), // Affiche l'image de gauche
|
||||
),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 30),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 50.0, vertical: 30.0),
|
||||
child: _buildLoginForm(context),
|
||||
),
|
||||
),
|
||||
@ -200,26 +165,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
passwordController: _passwordController,
|
||||
obscurePassword: _obscurePassword,
|
||||
highlightPasswordField: _highlightPasswordField,
|
||||
onTogglePasswordVisibility: () {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_obscurePassword = !_obscurePassword;
|
||||
});
|
||||
},
|
||||
onTogglePasswordVisibility: _togglePasswordVisibility,
|
||||
),
|
||||
ForgotPasswordButtonWidget(onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return const ForgotPasswordDialogWidget();
|
||||
},
|
||||
);
|
||||
}),
|
||||
ForgotPasswordButtonWidget(onPressed: _forgotPassword),
|
||||
const SizedBox(height: 30),
|
||||
LoginButtonWidget(
|
||||
isLoading: _isLoading,
|
||||
onPressed: () => Navigator.of(context).pushNamed(
|
||||
'/calendar'), //Ici, remplacer par une fonction de connexion avec firebase Auth
|
||||
onPressed: _signInWithEmailAndPassword,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ErrorMessageWidget(errorMessage: _errorMessage),
|
||||
|
@ -4,7 +4,7 @@ import 'package:em2rp/views/calendar_page.dart';
|
||||
import 'package:em2rp/views/my_account_page.dart';
|
||||
import 'package:em2rp/views/user_management_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart'; // Import Provider
|
||||
// Import Provider
|
||||
|
||||
class MainDrawer extends StatelessWidget {
|
||||
final String currentPage;
|
||||
|
Loading…
x
Reference in New Issue
Block a user