Début refacto en MVVM (Login, drawer OK
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:em2rp/providers/user_provider.dart';
|
||||
import 'package:em2rp/view_model/login_view_model.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';
|
||||
@ -8,117 +7,25 @@ import 'package:em2rp/views/widgets/auth/login_button.dart';
|
||||
import 'package:em2rp/views/widgets/image/em2_logo_n_sur_b.dart';
|
||||
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:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
class LoginPage extends StatelessWidget {
|
||||
const LoginPage({super.key});
|
||||
|
||||
@override
|
||||
State<LoginPage> createState() => _LoginPageState();
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
String _errorMessage = '';
|
||||
bool _isLoading = false;
|
||||
bool _obscurePassword = true;
|
||||
bool _highlightPasswordField = false;
|
||||
bool _highlightEmailField = false;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_emailController.dispose();
|
||||
_passwordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _signInWithEmailAndPassword() async {
|
||||
// Pas de vérification mounted ici, le widget reste monté pendant toute l'opération
|
||||
setState(() {
|
||||
_errorMessage = '';
|
||||
_isLoading = true;
|
||||
_highlightPasswordField = false;
|
||||
_highlightEmailField = false;
|
||||
});
|
||||
|
||||
try {
|
||||
final UserCredential userCredential =
|
||||
await FirebaseAuth.instance.signInWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text,
|
||||
);
|
||||
final uid = userCredential.user!.uid;
|
||||
|
||||
final DocumentSnapshot userDoc =
|
||||
await FirebaseFirestore.instance.collection('users').doc(uid).get();
|
||||
|
||||
if (userDoc.exists) {
|
||||
print("User document found: ${userDoc.data()}");
|
||||
Provider.of<UserProvider>(context, listen: false)
|
||||
.setUserData(userDoc.data() as Map<String, dynamic>, uid);
|
||||
|
||||
// Maintenant que toutes les données sont chargées, naviguer vers CalendarPage.
|
||||
Navigator.of(context).pushReplacementNamed('/calendar');
|
||||
} else {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_errorMessage = "Aucune donnée utilisateur trouvée.";
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
} on FirebaseAuthException catch (e) {
|
||||
if (!mounted) return;
|
||||
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) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_errorMessage =
|
||||
"Erreur lors de la récupération des données utilisateur.";
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _togglePasswordVisibility() {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_obscurePassword = !_obscurePassword;
|
||||
});
|
||||
}
|
||||
|
||||
void _forgotPassword() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return const ForgotPasswordDialogWidget();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
if (constraints.maxWidth > 900) {
|
||||
return _buildLargeScreenLayout(context);
|
||||
} else {
|
||||
return _buildSmallScreenLayout(context);
|
||||
}
|
||||
},
|
||||
return ChangeNotifierProvider(
|
||||
create: (_) => LoginViewModel(),
|
||||
child: Scaffold(
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return constraints.maxWidth > 900
|
||||
? _buildLargeScreenLayout(context)
|
||||
: _buildSmallScreenLayout(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -126,10 +33,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
Widget _buildLargeScreenLayout(BuildContext context) {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: const BigLeftImageWidget(),
|
||||
),
|
||||
const Expanded(flex: 6, child: BigLeftImageWidget()),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Padding(
|
||||
@ -152,34 +56,45 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
Widget _buildLoginForm(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
const LogoWidget(),
|
||||
const SizedBox(height: 30),
|
||||
const WelcomeTextWidget(),
|
||||
const SizedBox(height: 40),
|
||||
EmailTextFieldWidget(
|
||||
emailController: _emailController,
|
||||
highlightEmailField: _highlightEmailField,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
PasswordTextFieldWidget(
|
||||
passwordController: _passwordController,
|
||||
obscurePassword: _obscurePassword,
|
||||
highlightPasswordField: _highlightPasswordField,
|
||||
onTogglePasswordVisibility: _togglePasswordVisibility,
|
||||
),
|
||||
ForgotPasswordButtonWidget(onPressed: _forgotPassword),
|
||||
const SizedBox(height: 30),
|
||||
LoginButtonWidget(
|
||||
isLoading: _isLoading,
|
||||
onPressed: _signInWithEmailAndPassword,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ErrorMessageWidget(errorMessage: _errorMessage),
|
||||
],
|
||||
return Consumer<LoginViewModel>(
|
||||
builder: (context, loginViewModel, child) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
const LogoWidget(),
|
||||
const SizedBox(height: 30),
|
||||
const WelcomeTextWidget(),
|
||||
const SizedBox(height: 40),
|
||||
EmailTextFieldWidget(
|
||||
emailController: loginViewModel.emailController,
|
||||
highlightEmailField: loginViewModel.highlightEmailField,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
PasswordTextFieldWidget(
|
||||
passwordController: loginViewModel.passwordController,
|
||||
obscurePassword: loginViewModel.obscurePassword,
|
||||
highlightPasswordField: loginViewModel.highlightPasswordField,
|
||||
onTogglePasswordVisibility:
|
||||
loginViewModel.togglePasswordVisibility,
|
||||
),
|
||||
ForgotPasswordButtonWidget(
|
||||
onPressed: () => showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
const ForgotPasswordDialogWidget(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
LoginButtonWidget(
|
||||
isLoading: loginViewModel.isLoading,
|
||||
onPressed: () => loginViewModel.signIn(context),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ErrorMessageWidget(errorMessage: loginViewModel.errorMessage),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user