diff --git a/frontend/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/frontend/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index 2ecdf29..86acc23 100644 --- a/frontend/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/frontend/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -20,6 +20,11 @@ public final class GeneratedPluginRegistrant { } catch (Exception e) { Log.e(TAG, "Error registering plugin flutter_plugin_android_lifecycle, io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin", e); } + try { + flutterEngine.getPlugins().add(new com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin flutter_secure_storage, com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin", e); + } try { flutterEngine.getPlugins().add(new io.flutter.plugins.imagepicker.ImagePickerPlugin()); } catch (Exception e) { diff --git a/frontend/lib/screens/administrateurs/creation/gestionnaires_create.dart b/frontend/lib/screens/administrateurs/creation/gestionnaires_create.dart new file mode 100644 index 0000000..de00a86 --- /dev/null +++ b/frontend/lib/screens/administrateurs/creation/gestionnaires_create.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class GestionnairesCreate extends StatelessWidget { + const GestionnairesCreate({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Créer un gestionnaire'), + ), + body: const Center( + child: Text('Formulaire de création de gestionnaire'), + ), + ); + } +} \ No newline at end of file diff --git a/frontend/lib/screens/auth/login_screen.dart b/frontend/lib/screens/auth/login_screen.dart index f6c8a8f..17dbc69 100644 --- a/frontend/lib/screens/auth/login_screen.dart +++ b/frontend/lib/screens/auth/login_screen.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:p_tits_pas/services/auth_service.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:p_tits_pas/services/bug_report_service.dart'; import 'package:go_router/go_router.dart'; @@ -19,6 +20,7 @@ class _LoginPageState extends State { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); + final AuthService _authService = AuthService(); @override void dispose() { @@ -47,6 +49,46 @@ class _LoginPageState extends State { return null; } + Future _handleLogin() async { + if (_formKey.currentState?.validate() ?? false) { + try { + final response = await _authService.login( + _emailController.text, + _passwordController.text, + ); + + if (!mounted) return; + + // Navigation selon le rôle + switch (response.role.toLowerCase()) { + case 'parent': + Navigator.pushReplacementNamed(context, '/parent-dashboard'); + break; + case 'assistante_maternelle': + Navigator.pushReplacementNamed(context, '/assistante_maternelle_dashboard'); + break; + case 'admin': + Navigator.pushReplacementNamed(context, '/admin_dashboard'); + break; + case 'gestionnaire': + Navigator.pushReplacementNamed(context, '/gestionnaire_dashboard'); + break; + default: + Navigator.pushReplacementNamed(context, '/home'); + } + } catch (e) { + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Échec de la connexion. Vérifiez vos identifiants.'), + backgroundColor: Colors.red, + ), + ); + } + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -144,11 +186,7 @@ class _LoginPageState extends State { height: 40, text: 'Se connecter', textColor: const Color(0xFF2D6A4F), - onPressed: () { - if (_formKey.currentState?.validate() ?? false) { - // TODO: Implémenter la logique de connexion - } - }, + onPressed: _handleLogin, ), ), const SizedBox(height: 10), diff --git a/frontend/lib/services/api/api_config.dart b/frontend/lib/services/api/api_config.dart new file mode 100644 index 0000000..f6be021 --- /dev/null +++ b/frontend/lib/services/api/api_config.dart @@ -0,0 +1,21 @@ +class ApiConfig { + // static const String baseUrl = 'https://ynov.ptits-pas.fr/api/v1'; + static const String baseUrl = 'http://localhost:3000/api/v1'; + + // Auth endpoints + static const String login = '/auth/login'; + static const String register = '/auth/register'; + static const String refreshToken = '/auth/refresh'; + + // Users endpoints + static const String users = '/users'; + static const String userProfile = '/users/profile'; + static const String userChildren = '/users/children'; + + // Dashboard endpoints + static const String dashboard = '/dashboard'; + static const String events = '/events'; + static const String contracts = '/contracts'; + static const String conversations = '/conversations'; + static const String notifications = '/notifications'; +} \ No newline at end of file diff --git a/frontend/lib/services/auth_service.dart b/frontend/lib/services/auth_service.dart index 5234c8e..bbfb1ec 100644 --- a/frontend/lib/services/auth_service.dart +++ b/frontend/lib/services/auth_service.dart @@ -1,9 +1,78 @@ import 'dart:convert'; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:p_tits_pas/services/api/api_config.dart'; import '../models/user.dart'; +import 'package:http/http.dart' as http; + + +class AuthResponse { + final String acessToken; + final String role; + + AuthResponse({required this.acessToken, required this.role}); + + factory AuthResponse.fromJson(Map json) { + return AuthResponse( + acessToken: json['acessToken'], + role: json['role'], + ); + } +} class AuthService { - static const String _usersKey = 'users'; + ApiConfig apiConfig = ApiConfig(); + String baseUrl = ApiConfig.baseUrl; + final storage = const FlutterSecureStorage(); + + //login + Future login(String email, String password) async { + final response = await http.post( + Uri.parse('$baseUrl${ApiConfig.login}'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'email': email, 'password': password}), + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + final authResponse = AuthResponse.fromJson(data); + + await storage.write(key: 'access_token', value: authResponse.acessToken); + await storage.write(key: 'role', value: authResponse.role); + return authResponse; + } else { + throw Exception('Failed to login'); + } + } + + //register + Future register({ + required String email, + required String password, + required String firstName, + required String lastName, + required String role, + }) async { + final response = await http.post( + Uri.parse('$baseUrl${ApiConfig.register}'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'email': email, + 'password': password, + 'firstName': firstName, + 'lastName': lastName, + 'role': role, + }), + ); + + if (response.statusCode == 201) { + final data = jsonDecode(response.body); + return AppUser.fromJson(data['user']); + } else { + throw Exception('Failed to register'); + } + } + + /*static const String _usersKey = 'users'; static const String _parentsKey = 'parents'; static const String _childrenKey = 'children'; @@ -38,5 +107,5 @@ class AuthService { // Méthode pour récupérer l'utilisateur connecté (mode démonstration) static Future getCurrentUser() async { return null; // Aucun utilisateur en mode démonstration - } + }*/ } \ No newline at end of file diff --git a/frontend/lib/services/login_navigation_service.dart b/frontend/lib/services/login_navigation_service.dart new file mode 100644 index 0000000..6b6ca24 --- /dev/null +++ b/frontend/lib/services/login_navigation_service.dart @@ -0,0 +1,20 @@ +import 'package:flutter/cupertino.dart'; + +class NavigationService { + static void handleLoginSuccess(BuildContext context, String role) { + switch (role) { + case 'admin': + Navigator.pushReplacementNamed(context, '/admin_dashboard'); + break; + case 'gestionnaire': + Navigator.pushReplacementNamed(context, '/gestionnaire_dashboard'); + break; + case 'parent': + Navigator.pushReplacementNamed(context, '/parent-dashboard'); + break; + case 'assistante_maternelle': + Navigator.pushReplacementNamed(context, '/assistante_maternelle_dashboard'); + break; + } + } +} \ No newline at end of file diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index 9d0bbd5..81bd6a6 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -139,6 +139,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.28" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + url: "https://pub.dev" + source: hosted + version: "9.2.4" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + url: "https://pub.dev" + source: hosted + version: "3.1.2" flutter_test: dependency: "direct dev" description: flutter @@ -169,10 +217,10 @@ packages: dependency: "direct main" description: name: http - sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f + sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.5.0" http_parser: dependency: transitive description: @@ -626,6 +674,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba" + url: "https://pub.dev" + source: hosted + version: "5.13.0" xdg_directories: dependency: transitive description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index 1a73bb5..d0533dc 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -18,7 +18,8 @@ dependencies: image_picker: ^1.0.7 js: ^0.6.7 url_launcher: ^6.2.4 - http: ^1.2.0 + http: ^1.5.0 + flutter_secure_storage: ^9.2.4 dev_dependencies: flutter_test: diff --git a/frontend/windows/flutter/generated_plugin_registrant.cc b/frontend/windows/flutter/generated_plugin_registrant.cc index 043a96f..602b168 100644 --- a/frontend/windows/flutter/generated_plugin_registrant.cc +++ b/frontend/windows/flutter/generated_plugin_registrant.cc @@ -7,11 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/frontend/windows/flutter/generated_plugins.cmake b/frontend/windows/flutter/generated_plugins.cmake index a95e267..b918cf8 100644 --- a/frontend/windows/flutter/generated_plugins.cmake +++ b/frontend/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_windows + flutter_secure_storage_windows url_launcher_windows )