Merge remote-tracking branch 'origin/master' into master
Résolution conflit: Suppression de frontend/lib/navigation/app_router.dart (fichier obsolète remplacé par frontend/lib/config/app_router.dart) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,9 +4,10 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:p_tits_pas/services/bug_report_service.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../widgets/image_button.dart';
|
||||
import '../../widgets/custom_app_text_field.dart';
|
||||
import '../../services/auth_service.dart';
|
||||
import '../../widgets/auth/change_password_dialog.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
@@ -19,6 +20,9 @@ class _LoginPageState extends State<LoginScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
|
||||
bool _isLoading = false;
|
||||
String? _errorMessage;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -41,12 +45,80 @@ class _LoginPageState extends State<LoginScreen> {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Veuillez entrer votre mot de passe';
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Le mot de passe doit contenir au moins 6 caractères';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Gère la connexion de l'utilisateur
|
||||
Future<void> _handleLogin() async {
|
||||
// Réinitialiser le message d'erreur
|
||||
setState(() {
|
||||
_errorMessage = null;
|
||||
});
|
||||
|
||||
if (!(_formKey.currentState?.validate() ?? false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
// Appeler le service d'authentification
|
||||
final user = await AuthService.login(
|
||||
_emailController.text.trim(),
|
||||
_passwordController.text,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
// Vérifier si l'utilisateur doit changer son mot de passe
|
||||
if (user.changementMdpObligatoire) {
|
||||
if (!mounted) return;
|
||||
|
||||
// Afficher la modale de changement de mot de passe (non-dismissible)
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => const ChangePasswordDialog(),
|
||||
);
|
||||
|
||||
// Si le changement de mot de passe a réussi, rafraîchir l'utilisateur
|
||||
if (result == true && mounted) {
|
||||
await AuthService.refreshCurrentUser();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
// Rediriger selon le rôle de l'utilisateur
|
||||
_redirectUserByRole(user.role);
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_errorMessage = e.toString().replaceAll('Exception: ', '');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Redirige l'utilisateur selon son rôle
|
||||
void _redirectUserByRole(String role) {
|
||||
switch (role.toLowerCase()) {
|
||||
case 'super_admin':
|
||||
case 'gestionnaire':
|
||||
Navigator.pushReplacementNamed(context, '/admin-dashboard');
|
||||
break;
|
||||
case 'parent':
|
||||
Navigator.pushReplacementNamed(context, '/parent-dashboard');
|
||||
break;
|
||||
case 'assistante_maternelle':
|
||||
Navigator.pushReplacementNamed(context, '/am-dashboard');
|
||||
break;
|
||||
default:
|
||||
Navigator.pushReplacementNamed(context, '/home');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -136,20 +208,46 @@ class _LoginPageState extends State<LoginScreen> {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Message d'erreur
|
||||
if (_errorMessage != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
margin: const EdgeInsets.only(bottom: 15),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red[50],
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: Colors.red[300]!),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.error_outline, color: Colors.red[700], size: 20),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_errorMessage!,
|
||||
style: GoogleFonts.merienda(
|
||||
fontSize: 12,
|
||||
color: Colors.red[700],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Bouton centré
|
||||
Center(
|
||||
child: ImageButton(
|
||||
bg: 'assets/images/btn_green.png',
|
||||
width: 300,
|
||||
height: 40,
|
||||
text: 'Se connecter',
|
||||
textColor: const Color(0xFF2D6A4F),
|
||||
onPressed: () {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
// TODO: Implémenter la logique de connexion
|
||||
}
|
||||
},
|
||||
),
|
||||
child: _isLoading
|
||||
? const CircularProgressIndicator()
|
||||
: ImageButton(
|
||||
bg: 'assets/images/btn_green.png',
|
||||
width: 300,
|
||||
height: 40,
|
||||
text: 'Se connecter',
|
||||
textColor: const Color(0xFF2D6A4F),
|
||||
onPressed: _handleLogin,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// Lien mot de passe oublié
|
||||
|
||||
Reference in New Issue
Block a user