dev #67
@ -20,6 +20,11 @@ public final class GeneratedPluginRegistrant {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Error registering plugin flutter_plugin_android_lifecycle, io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin", 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 {
|
try {
|
||||||
flutterEngine.getPlugins().add(new io.flutter.plugins.imagepicker.ImagePickerPlugin());
|
flutterEngine.getPlugins().add(new io.flutter.plugins.imagepicker.ImagePickerPlugin());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -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'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
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:url_launcher/url_launcher.dart';
|
||||||
import 'package:p_tits_pas/services/bug_report_service.dart';
|
import 'package:p_tits_pas/services/bug_report_service.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@ -19,6 +20,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final _emailController = TextEditingController();
|
final _emailController = TextEditingController();
|
||||||
final _passwordController = TextEditingController();
|
final _passwordController = TextEditingController();
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -47,6 +49,46 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -144,11 +186,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
text: 'Se connecter',
|
text: 'Se connecter',
|
||||||
textColor: const Color(0xFF2D6A4F),
|
textColor: const Color(0xFF2D6A4F),
|
||||||
onPressed: () {
|
onPressed: _handleLogin,
|
||||||
if (_formKey.currentState?.validate() ?? false) {
|
|
||||||
// TODO: Implémenter la logique de connexion
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
|||||||
21
frontend/lib/services/api/api_config.dart
Normal file
21
frontend/lib/services/api/api_config.dart
Normal file
@ -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';
|
||||||
|
}
|
||||||
@ -1,9 +1,78 @@
|
|||||||
import 'dart:convert';
|
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 '../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<String, dynamic> json) {
|
||||||
|
return AuthResponse(
|
||||||
|
acessToken: json['acessToken'],
|
||||||
|
role: json['role'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AuthService {
|
class AuthService {
|
||||||
static const String _usersKey = 'users';
|
ApiConfig apiConfig = ApiConfig();
|
||||||
|
String baseUrl = ApiConfig.baseUrl;
|
||||||
|
final storage = const FlutterSecureStorage();
|
||||||
|
|
||||||
|
//login
|
||||||
|
Future<AuthResponse> 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<AppUser> 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 _parentsKey = 'parents';
|
||||||
static const String _childrenKey = 'children';
|
static const String _childrenKey = 'children';
|
||||||
|
|
||||||
@ -38,5 +107,5 @@ class AuthService {
|
|||||||
// Méthode pour récupérer l'utilisateur connecté (mode démonstration)
|
// Méthode pour récupérer l'utilisateur connecté (mode démonstration)
|
||||||
static Future<AppUser?> getCurrentUser() async {
|
static Future<AppUser?> getCurrentUser() async {
|
||||||
return null; // Aucun utilisateur en mode démonstration
|
return null; // Aucun utilisateur en mode démonstration
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
20
frontend/lib/services/login_navigation_service.dart
Normal file
20
frontend/lib/services/login_navigation_service.dart
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -139,6 +139,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.28"
|
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:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -169,10 +217,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.5.0"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -626,6 +674,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.13.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -18,7 +18,8 @@ dependencies:
|
|||||||
image_picker: ^1.0.7
|
image_picker: ^1.0.7
|
||||||
js: ^0.6.7
|
js: ^0.6.7
|
||||||
url_launcher: ^6.2.4
|
url_launcher: ^6.2.4
|
||||||
http: ^1.2.0
|
http: ^1.5.0
|
||||||
|
flutter_secure_storage: ^9.2.4
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@ -7,11 +7,14 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <file_selector_windows/file_selector_windows.h>
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
|
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||||
#include <url_launcher_windows/url_launcher_windows.h>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
FileSelectorWindowsRegisterWithRegistrar(
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
|
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||||
UrlLauncherWindowsRegisterWithRegistrar(
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
file_selector_windows
|
file_selector_windows
|
||||||
|
flutter_secure_storage_windows
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user