import 'dart:async'; import 'package:em2rp/providers/users_provider.dart'; import 'package:em2rp/providers/event_provider.dart'; import 'package:em2rp/providers/equipment_provider.dart'; import 'package:em2rp/providers/container_provider.dart'; import 'package:em2rp/providers/maintenance_provider.dart'; import 'package:em2rp/providers/alert_provider.dart'; import 'package:em2rp/utils/auth_guard_widget.dart'; import 'package:em2rp/utils/performance_monitor.dart'; import 'package:em2rp/views/alerts_page.dart'; import 'package:em2rp/views/calendar_page.dart'; import 'package:em2rp/views/login_page.dart'; import 'package:em2rp/views/equipment_management_page.dart'; import 'package:em2rp/views/container_management_page.dart'; import 'package:em2rp/views/maintenance_management_page.dart'; import 'package:em2rp/views/container_form_page.dart'; import 'package:em2rp/views/container_detail_page.dart'; import 'package:em2rp/views/event_preparation_page.dart'; import 'package:em2rp/views/event_statistics_page.dart'; import 'package:em2rp/models/container_model.dart'; import 'package:em2rp/models/event_model.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:em2rp/services/app_initializer.dart'; import 'utils/colors.dart'; import 'views/my_account_page.dart'; import 'views/user_management_page.dart'; import 'package:provider/provider.dart'; import 'providers/local_user_provider.dart'; import 'views/reset_password_page.dart'; import 'config/env.dart'; import 'utils/app_start_gate.dart'; import 'views/widgets/common/startup_splash_screen.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; void main() { // Ne pas effectuer d'initialisations asynchrones lourdes ici. WidgetsFlutterBinding.ensureInitialized(); runApp( MultiProvider( providers: [ // Fournisseur d'initialisation de l'application (initialise Firebase et cache en tâche de fond) ChangeNotifierProvider( create: (_) => AppInitializer(), ), // LocalUserProvider pour la gestion de l'authentification ChangeNotifierProvider( create: (context) => LocalUserProvider()), // UsersProvider migré vers l'API ChangeNotifierProvider( create: (context) => UsersProvider(), ), // EventProvider migré vers l'API ChangeNotifierProvider( create: (context) => EventProvider(), ), // EquipmentProvider migré vers l'API ChangeNotifierProvider( create: (context) => EquipmentProvider(), ), // ContainerProvider migré vers l'API ChangeNotifierProvider( create: (context) => ContainerProvider(), ), // MaintenanceProvider migré vers l'API ChangeNotifierProvider( create: (context) => MaintenanceProvider(), ), ChangeNotifierProvider( create: (context) => AlertProvider(), ), ], child: const MyApp(), ), ); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { late final Future _startupFuture; @override void initState() { super.initState(); _startupFuture = _bootstrapApp(); } Future _bootstrapApp() async { final initializer = context.read(); final localAuthProvider = context.read(); await initializer.initialize(); // Attendre la première valeur d'authentification avant toute décision // de navigation, afin d'éviter un flash de la page login. await FirebaseAuth.instance.authStateChanges().first; if (FirebaseAuth.instance.currentUser != null) { unawaited( localAuthProvider.loadUserData().catchError((e) { print('User data bootstrap failed: $e'); }), ); return; } // En développement, on garde la connexion automatique existante. if (Env.isDevelopment) { await localAuthProvider.signInWithEmailAndPassword( Env.devAdminEmail, Env.devAdminPassword, ); unawaited( localAuthProvider.loadUserData().catchError((e) { print('Dev user bootstrap failed: $e'); }), ); } } @override Widget build(BuildContext context) { return FutureBuilder( future: _startupFuture, builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.done) { return const MaterialApp( debugShowCheckedModeBanner: false, home: StartupSplashScreen(), ); } return MaterialApp( title: 'EM2 Hub', theme: ThemeData( primarySwatch: Colors.red, primaryColor: AppColors.noir, colorScheme: ColorScheme.fromSwatch().copyWith(secondary: AppColors.rouge), textTheme: const TextTheme( bodyMedium: TextStyle(color: AppColors.noir), ), inputDecorationTheme: const InputDecorationTheme( focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: AppColors.noir), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: AppColors.gris), ), labelStyle: TextStyle(color: AppColors.noir), hintStyle: TextStyle(color: AppColors.gris), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( foregroundColor: AppColors.blanc, backgroundColor: AppColors.noir, ), ), ), locale: const Locale('fr', 'FR'), supportedLocales: const [ Locale('fr', 'FR'), ], localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], routes: { '/login': (context) => const LoginPage(), '/alerts': (context) => const AuthGuard(child: AlertsPage()), '/calendar': (context) => const AuthGuard( allowWhileLoading: true, child: CalendarPage()), '/my_account': (context) => const AuthGuard(child: MyAccountPage()), '/user_management': (context) => const AuthGuard( requiredPermission: "view_all_users", child: UserManagementPage()), '/reset_password': (context) { final args = ModalRoute.of(context)!.settings.arguments as Map; return ResetPasswordPage( email: args['email'] as String, actionCode: args['actionCode'] as String, ); }, '/equipment_management': (context) => const AuthGuard( requiredPermission: "view_equipment", child: EquipmentManagementPage()), '/container_management': (context) => const AuthGuard( requiredPermission: "view_equipment", child: ContainerManagementPage()), '/maintenance_management': (context) => const AuthGuard( requiredPermission: "manage_maintenances", child: MaintenanceManagementPage()), '/container_form': (context) { final args = ModalRoute.of(context)?.settings.arguments; return AuthGuard( requiredPermission: "manage_equipment", child: ContainerFormPage( container: args as ContainerModel?, ), ); }, '/container_detail': (context) { final container = ModalRoute.of(context)!.settings.arguments as ContainerModel; return AuthGuard( requiredPermission: "view_equipment", child: ContainerDetailPage(container: container), ); }, '/event_preparation': (context) { final args = ModalRoute.of(context)!.settings.arguments as Map; final event = args['event'] as EventModel; return AuthGuard( child: EventPreparationPage( initialEvent: event, ), ); }, '/event_statistics': (context) => const AuthGuard( requiredPermission: 'generate_reports', child: EventStatisticsPage()), }, home: const AppStartGate(), ); }, ); } }