Amélioration de la splash_page et du login

This commit is contained in:
d6soft
2025-06-04 16:51:40 +02:00
parent 8c9e9a21c4
commit 41f1db1169
228 changed files with 366459 additions and 6183 deletions

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:geosector_app/core/theme/app_theme.dart';
import 'package:go_router/go_router.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/repositories/user_repository.dart';
import 'package:geosector_app/core/repositories/operation_repository.dart';
@@ -13,7 +13,6 @@ import 'package:geosector_app/core/services/sync_service.dart';
import 'package:geosector_app/core/services/connectivity_service.dart';
import 'package:geosector_app/presentation/auth/splash_page.dart';
import 'package:geosector_app/presentation/auth/login_page.dart';
import 'package:geosector_app/presentation/auth/register_page.dart';
import 'package:geosector_app/presentation/admin/admin_dashboard_page.dart';
import 'package:geosector_app/presentation/user/user_dashboard_page.dart';
@@ -28,239 +27,202 @@ final amicaleRepository = AmicaleRepository(apiService);
final syncService = SyncService(userRepository: userRepository);
final connectivityService = ConnectivityService();
class GeoSectorApp extends StatelessWidget {
const GeoSectorApp({super.key});
class GeosectorApp extends StatelessWidget {
const GeosectorApp({super.key});
@override
Widget build(BuildContext context) {
// Utiliser directement le router sans provider
final router = GoRouter(
return MaterialApp.router(
title: 'GeoSector',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.system,
routerConfig: _createRouter(),
debugShowCheckedModeBanner: false,
);
}
/// Création du routeur avec configuration pour URLs propres
GoRouter _createRouter() {
return GoRouter(
initialLocation: '/',
debugLogDiagnostics: true,
refreshListenable:
userRepository, // Écouter les changements d'état d'authentification
// Gestionnaire de redirection global - intercepte toutes les navigations
redirect: (context, state) {
// Détection manuelle des paramètres d'URL pour le Web
if (kIsWeb && state.uri.path == '/login') {
try {
// Obtenir le paramètre 'type' de l'URL actuelle
final typeParam = state.uri.queryParameters['type'];
// Obtenir l'URL brute du navigateur pour comparer
final rawUri = Uri.parse(Uri.base.toString());
final rawTypeParam = rawUri.queryParameters['type'];
print('APP ROUTER: state.uri = ${state.uri}, type = $typeParam');
print('APP ROUTER: rawUri = $rawUri, type = $rawTypeParam');
// Pas de redirection si on a déjà le paramètre type
if (typeParam != null) {
print('APP ROUTER: Param type déjà présent, pas de redirection');
return null; // Pas de redirection
}
// Si un paramètre type=user est présent dans l'URL brute mais pas dans l'état
if (rawTypeParam == 'user' && typeParam == null) {
print(
'APP ROUTER: Paramètre détecté dans l\'URL brute, redirection vers /login?type=user');
return '/login?type=user';
}
} catch (e) {
print('Erreur lors de la récupération des paramètres d\'URL: $e');
}
}
// Sauvegarder le chemin actuel pour l'utilisateur connecté, sauf pour la page de splash
if (state.uri.toString() != '/' && userRepository.isLoggedIn) {
// Ne pas sauvegarder les chemins de login/register
if (!state.uri.toString().startsWith('/login') &&
!state.uri.toString().startsWith('/register')) {
userRepository.updateLastPath(state.uri.toString());
}
}
// Vérifier si l'utilisateur est sur la page de splash
if (state.uri.toString() == '/') {
// Laisser l'utilisateur sur la page de splash, la redirection sera gérée par SplashPage
return null;
}
// Vérifier si l'utilisateur est sur une page d'authentification
final isLoggedIn = userRepository.isLoggedIn;
final isOnLoginPage = state.uri.toString().startsWith('/login');
final isOnRegisterPage = state.uri.toString() == '/register';
final isOnAdminRegisterPage = state.uri.toString() == '/admin-register';
// Si l'utilisateur n'est pas connecté et n'est pas sur une page d'authentification, rediriger vers la page de connexion
if (!isLoggedIn &&
!isOnLoginPage &&
!isOnRegisterPage &&
!isOnAdminRegisterPage) {
return '/login';
}
// Si l'utilisateur est connecté et se trouve sur une page d'authentification, rediriger vers le tableau de bord approprié
if (isLoggedIn &&
(isOnLoginPage || isOnRegisterPage || isOnAdminRegisterPage)) {
// Récupérer le rôle de l'utilisateur directement
final user = userRepository.getCurrentUser();
if (user != null) {
// Convertir le rôle en int si nécessaire
int roleValue;
if (user.role is String) {
roleValue = int.tryParse(user.role as String) ?? 1;
} else {
roleValue = user.role as int;
}
// Redirection simple basée sur le rôle
if (roleValue > 1) {
debugPrint(
'Router: Redirection vers /admin (rôle $roleValue > 1)');
return '/admin';
} else {
debugPrint(
'Router: Redirection vers /user (rôle $roleValue = 1)');
return '/user';
}
}
}
// Si l'utilisateur est connecté mais essaie d'accéder à la mauvaise page selon son rôle
if (isLoggedIn) {
final user = userRepository.getCurrentUser();
if (user != null) {
// Convertir le rôle en int si nécessaire
int roleValue;
if (user.role is String) {
roleValue = int.tryParse(user.role as String) ?? 1;
} else {
roleValue = user.role as int;
}
// Vérifier si l'utilisateur est sur la bonne page en fonction de son rôle
final isOnUserPage = state.uri.toString().startsWith('/user');
final isOnAdminPage = state.uri.toString().startsWith('/admin');
// Admin (rôle > 1) essayant d'accéder à une page utilisateur
if (roleValue > 1 && isOnUserPage) {
debugPrint(
'Router: Redirection d\'admin (rôle $roleValue) vers /admin');
return '/admin';
}
// Utilisateur standard (rôle = 1) essayant d'accéder à une page admin
if (roleValue == 1 && isOnAdminPage) {
debugPrint(
'Router: Redirection d\'utilisateur (rôle $roleValue) vers /user');
return '/user';
}
}
}
return null;
},
routes: [
// Splash screen
GoRoute(
path: '/',
builder: (context, state) => const SplashPage(),
),
// Page de connexion utilisateur dédiée
GoRoute(
path: '/login/user',
name: 'splash',
builder: (context, state) {
print('ROUTER: Accès direct à la route login user');
return const LoginPage(
key: Key('login_page_user'),
loginType: 'user',
);
debugPrint('GoRoute: Affichage de SplashPage');
return const SplashPage();
},
),
// Pages d'authentification standard
GoRoute(
path: '/login',
name: 'login',
builder: (context, state) {
// Ajouter des logs de débogage détaillés pour comprendre les paramètres
print('ROUTER DEBUG: Uri complète = ${state.uri}');
print('ROUTER DEBUG: Path = ${state.uri.path}');
print('ROUTER DEBUG: Query params = ${state.uri.queryParameters}');
print(
'ROUTER DEBUG: Has type? ${state.uri.queryParameters.containsKey("type")}');
// Récupérer le type depuis les query parameters ou extra data
final type = state.uri.queryParameters['type'] ??
(state.extra as Map<String, dynamic>?)?['type'] as String?;
// Donner la priorité aux paramètres d'URL puis aux extras
String? loginType;
// 1. Essayer d'abord les paramètres d'URL (pour les liens externes)
final queryParams = state.uri.queryParameters;
loginType = queryParams['type'];
print('ROUTER DEBUG: Type from query params = $loginType');
// 2. Si aucun type dans les paramètres d'URL, vérifier les extras (pour la navigation interne)
if (loginType == null &&
state.extra != null &&
state.extra is Map<String, dynamic>) {
final extras = state.extra as Map<String, dynamic>;
loginType = extras['type']?.toString();
print('ROUTER DEBUG: Type from extras = $loginType');
}
// 3. Normaliser et valider le type
if (loginType != null) {
loginType = loginType.trim().toLowerCase();
// Vérifier explicitement que c'est 'user', sinon mettre 'admin'
if (loginType != 'user') {
loginType = 'admin';
}
} else {
// Si aucun type n'est spécifié, retourner la page de splash
print(
'ROUTER: Aucun type spécifié, utilisation de la page splash');
return const SplashPage();
}
print('ROUTER: Type de connexion final: $loginType');
return LoginPage(
key: Key('login_page_${loginType}'),
loginType: loginType,
);
debugPrint('GoRoute: Affichage de LoginPage avec type: $type');
return LoginPage(loginType: type);
},
),
// Routes spécifiques pour chaque type de login
GoRoute(
path: '/login/user',
name: 'login-user',
builder: (context, state) {
debugPrint('GoRoute: Affichage de LoginPage pour utilisateur');
return const LoginPage(loginType: 'user');
},
),
GoRoute(
path: '/login/admin',
name: 'login-admin',
builder: (context, state) {
debugPrint('GoRoute: Affichage de LoginPage pour admin');
return const LoginPage(loginType: 'admin');
},
),
GoRoute(
path: '/register',
builder: (context, state) => const RegisterPage(),
name: 'register',
builder: (context, state) {
debugPrint('GoRoute: Affichage de RegisterPage');
// Retournez votre page d'inscription ici
return const Scaffold(
body: Center(
child: Text('Page d\'inscription - À implémenter'),
),
);
},
),
// Pages administrateur
GoRoute(
path: '/admin',
builder: (context, state) => const AdminDashboardPage(),
routes: [
// Ajouter d'autres routes admin ici
],
),
// Pages utilisateur
GoRoute(
path: '/user',
builder: (context, state) => const UserDashboardPage(),
routes: [
// Ajouter d'autres routes utilisateur ici
],
name: 'user',
builder: (context, state) {
debugPrint('GoRoute: Affichage de UserDashboardPage');
return const UserDashboardPage();
},
),
GoRoute(
path: '/admin',
name: 'admin',
builder: (context, state) {
debugPrint('GoRoute: Affichage de AdminDashboardPage');
return const AdminDashboardPage();
},
),
],
);
redirect: (context, state) {
final currentPath = state.uri.path;
debugPrint('GoRouter.redirect: currentPath = $currentPath');
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'GEOSECTOR',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.system,
routerConfig: router,
// Pour la page racine, toujours autoriser l'affichage de la splash page
if (currentPath == '/') {
debugPrint('GoRouter.redirect: Autorisation splash page');
return null;
}
// Pages publiques qui ne nécessitent pas d'authentification
final publicPaths = [
'/login',
'/login/user',
'/login/admin',
'/register'
];
if (publicPaths.any((path) => currentPath.startsWith(path))) {
debugPrint(
'GoRouter.redirect: Page publique autorisée: $currentPath');
return null;
}
// Vérifier l'authentification pour les pages protégées
try {
final isAuthenticated = userRepository.isLoggedIn;
final currentUser = userRepository.currentUser;
debugPrint('GoRouter.redirect: isAuthenticated = $isAuthenticated');
debugPrint('GoRouter.redirect: currentUser = ${currentUser?.email}');
// Si pas authentifié, rediriger vers la splash page
if (!isAuthenticated) {
debugPrint(
'GoRouter.redirect: Non authentifié, redirection vers /');
return '/';
}
// Vérifier les permissions pour les pages admin
if (currentPath.startsWith('/admin')) {
final userRole = userRepository.getUserRole();
final isAdmin = userRole > 1; // Admin = rôle 2 ou plus
debugPrint(
'GoRouter.redirect: userRole = $userRole, isAdmin = $isAdmin');
if (!isAdmin) {
debugPrint(
'GoRouter.redirect: Pas admin, redirection vers /user');
return '/user';
}
}
// Si on arrive ici, l'utilisateur a les permissions nécessaires
debugPrint('GoRouter.redirect: Accès autorisé à $currentPath');
return null;
} catch (e) {
debugPrint(
'GoRouter.redirect: Erreur lors de la vérification auth: $e');
// En cas d'erreur, rediriger vers la splash page pour sécurité
return '/';
}
},
// Listener pour déboguer les changements de route
refreshListenable:
userRepository, // Écouter les changements dans userRepository
debugLogDiagnostics: true, // Activer les logs de débogage
errorBuilder: (context, state) {
debugPrint('GoRouter.errorBuilder: Erreur pour ${state.uri.path}');
return Scaffold(
appBar: AppBar(
title: const Text('Erreur de navigation'),
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 64, color: Colors.red),
const SizedBox(height: 16),
Text(
'Page non trouvée',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 8),
Text(
'Chemin: ${state.uri.path}',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.grey[600],
),
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: () {
debugPrint('GoRouter.errorBuilder: Retour vers /');
context.go('/');
},
icon: const Icon(Icons.home),
label: const Text('Retour à l\'accueil'),
),
],
),
),
),
);
},
);
}
}