import 'dart:async'; import 'package:flutter/material.dart'; import 'package:afterwork/data/datasources/user_remote_data_source.dart'; import 'package:afterwork/data/models/user_model.dart'; import 'package:afterwork/presentation/screens/home/home_screen.dart'; import 'package:http/http.dart' as http; import 'package:afterwork/data/services/hash_password.dart'; import 'package:afterwork/data/services/secure_storage.dart'; import 'package:afterwork/data/services/preferences_helper.dart'; import '../../../data/datasources/event_remote_data_source.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override _LoginScreenState createState() => _LoginScreenState(); } class _LoginScreenState extends State with SingleTickerProviderStateMixin { final _formKey = GlobalKey(); String _userId = ''; String _email = ''; String _password = ''; bool _isPasswordVisible = false; bool _isSubmitting = false; final UserRemoteDataSource _userRemoteDataSource = UserRemoteDataSource(http.Client()); final SecureStorage _secureStorage = SecureStorage(); final PreferencesHelper _preferencesHelper = PreferencesHelper(); late AnimationController _controller; late Animation _buttonScaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 300), ); _buttonScaleAnimation = Tween(begin: 1.0, end: 1.1).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } /// Afficher/Masquer le mot de passe void _togglePasswordVisibility() { setState(() { _isPasswordVisible = !_isPasswordVisible; }); } /// Soumission du formulaire d'authentification void _submit() async { if (_formKey.currentState!.validate()) { setState(() { _isSubmitting = true; }); _formKey.currentState!.save(); print("===== DEBUT DE LA SOUMISSION DU FORMULAIRE ====="); print("Email: $_email"); print("Mot de passe: $_password"); try { print('Début de l\'authentification'); // Débogage // Hachage du mot de passe avec SHA-256 String hashedPassword = hashPassword(_password); print("Mot de passe haché: $hashedPassword"); // Authentification via l'API avec un timeout UserModel user = await _userRemoteDataSource .authenticateUser(_email, hashedPassword, "unique_user_id") .timeout( Duration(seconds: 10), onTimeout: () { throw TimeoutException('Le temps de connexion a expiré. Veuillez réessayer.'); }, ); print('Connexion réussie : ${user.userId} - ${user.email}'); // Sauvegarde des données de l'utilisateur après authentification await _secureStorage.saveUserId(user.userId); await _preferencesHelper.saveUserName(user.nom); await _preferencesHelper.saveUserLastName(user.prenoms); print("===== SAUVEGARDE DES DONNÉES UTILISATEUR ====="); print("User ID: ${user.userId}"); print("User Name: ${user.nom}"); print("User Last Name: ${user.prenoms}"); // Navigation vers l'écran d'accueil Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => HomeScreen( eventRemoteDataSource: EventRemoteDataSource(http.Client()), userId: user.userId, userName: user.nom, userLastName: user.prenoms, ), ), ); print("===== NAVIGATION VERS HOME SCREEN ====="); } catch (e) { print('Erreur lors de la connexion: $e'); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Erreur : ${e.toString()}')), ); } finally { print('Fin du processus d\'authentification'); // Débogage setState(() { _isSubmitting = false; }); } } else { print("===== FORMULAIRE NON VALIDE ====="); } } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; return Scaffold( body: Stack( children: [ // Arrière-plan avec dégradé Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF4A90E2), Color(0xFF9013FE)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ), // Contenu de la page Center( child: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Logo animé AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.scale( scale: _buttonScaleAnimation.value, child: child, ); }, child: GestureDetector( onTapDown: (_) => _controller.forward(), onTapUp: (_) => _controller.reverse(), child: Image.asset( 'lib/assets/images/logo.png', height: size.height * 0.2, ), ), ), const SizedBox(height: 20), const Text( 'Bienvenue sur AfterWork', style: TextStyle( fontSize: 26, fontWeight: FontWeight.bold, color: Colors.white, shadows: [ Shadow( offset: Offset(0, 2), blurRadius: 6, color: Colors.black26, ), ], ), ), const SizedBox(height: 40), // Champ Email TextFormField( decoration: InputDecoration( labelText: 'Email', filled: true, fillColor: Colors.white.withOpacity(0.1), labelStyle: const TextStyle(color: Colors.white), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), borderSide: BorderSide.none, ), prefixIcon: const Icon(Icons.email, color: Colors.white), ), keyboardType: TextInputType.emailAddress, style: const TextStyle(color: Colors.white), validator: (value) { if (value == null || value.isEmpty) { print("Erreur: Le champ email est vide"); return 'Veuillez entrer votre email'; } if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) { print("Erreur: Le format de l'email est invalide"); return 'Veuillez entrer un email valide'; } return null; }, onSaved: (value) { _email = value ?? ''; // Utiliser une chaîne vide si value est null print("Email sauvegardé: $_email"); }, ), const SizedBox(height: 20), // Champ Mot de passe TextFormField( decoration: InputDecoration( labelText: 'Mot de passe', filled: true, fillColor: Colors.white.withOpacity(0.1), labelStyle: const TextStyle(color: Colors.white), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), borderSide: BorderSide.none, ), prefixIcon: const Icon(Icons.lock, color: Colors.white), suffixIcon: IconButton( icon: Icon( _isPasswordVisible ? Icons.visibility : Icons.visibility_off, color: Colors.white), onPressed: _togglePasswordVisibility, ), ), obscureText: !_isPasswordVisible, style: const TextStyle(color: Colors.white), validator: (value) { if (value == null || value.isEmpty) { print("Erreur: Le champ mot de passe est vide"); return 'Veuillez entrer votre mot de passe'; } if (value.length < 6) { print("Erreur: Le mot de passe est trop court"); return 'Le mot de passe doit comporter au moins 6 caractères'; } return null; }, onSaved: (value) { _password = value ?? ''; // Utiliser une chaîne vide si value est null print("Mot de passe sauvegardé: $_password"); }, ), const SizedBox(height: 20), // Bouton de connexion avec animation de soumission SizedBox( width: double.infinity, child: ElevatedButton( style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16.0), textStyle: const TextStyle(fontSize: 18), backgroundColor: _isSubmitting ? Colors.grey : Colors.blueAccent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), onPressed: _isSubmitting ? null : _submit, child: _isSubmitting ? const CircularProgressIndicator(color: Colors.white) : const Text('Connexion'), ), ), const SizedBox(height: 20), // Lien pour s'inscrire TextButton( onPressed: () { // Naviguer vers la page d'inscription print("Redirection vers la page d'inscription"); }, child: const Text( 'Pas encore de compte ? Inscrivez-vous', style: TextStyle(color: Colors.white), ), ), ], ), ), ), ), ], ), ); } }