import 'package:flutter/material.dart'; import 'package:geosector_app/presentation/widgets/dashboard_app_bar.dart'; import 'package:geosector_app/presentation/widgets/responsive_navigation.dart'; import 'package:geosector_app/app.dart'; // Pour accéder à userRepository import 'package:geosector_app/core/theme/app_theme.dart'; // Pour les couleurs du thème import 'dart:math' as math; /// Layout commun pour les tableaux de bord utilisateur et administrateur /// Combine DashboardAppBar et ResponsiveNavigation class DashboardLayout extends StatelessWidget { /// Le contenu principal à afficher final Widget body; /// Le titre de la page final String title; /// L'index de la page sélectionnée final int selectedIndex; /// Callback appelé lorsqu'un élément de navigation est sélectionné final Function(int) onDestinationSelected; /// Liste des destinations de navigation final List destinations; /// Actions supplémentaires à afficher dans l'AppBar final List? additionalActions; /// Widgets à afficher en bas de la sidebar final List? sidebarBottomItems; /// Indique si l'utilisateur est un administrateur final bool isAdmin; /// Callback appelé lorsque le bouton de déconnexion est pressé final VoidCallback? onLogoutPressed; const DashboardLayout({ super.key, required this.body, required this.title, required this.selectedIndex, required this.onDestinationSelected, required this.destinations, this.additionalActions, this.sidebarBottomItems, this.isAdmin = false, this.onLogoutPressed, }); @override Widget build(BuildContext context) { try { debugPrint('Building DashboardLayout'); // Vérifier que les destinations ne sont pas vides if (destinations.isEmpty) { debugPrint('ERREUR: destinations est vide dans DashboardLayout'); return const Scaffold( body: Center( child: Text('Erreur: Aucune destination de navigation disponible'), ), ); } // Vérifier que selectedIndex est valide if (selectedIndex < 0 || selectedIndex >= destinations.length) { debugPrint('ERREUR: selectedIndex invalide dans DashboardLayout'); return Scaffold( body: Center( child: Text('Erreur: Index de navigation invalide ($selectedIndex)'), ), ); } // Déterminer le rôle de l'utilisateur final currentUser = userRepository.getCurrentUser(); final userRole = currentUser?.role ?? 1; // Définir les couleurs du gradient selon le rôle final gradientColors = userRole > 1 ? [Colors.white, Colors.red.shade300] // Admin : fond rouge : [ Colors.white, AppTheme.accentColor.withValues(alpha: 0.3) ]; // User : fond vert return Stack( children: [ // Fond dégradé avec points Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: gradientColors, ), ), child: CustomPaint( painter: DotsPainter(), child: const SizedBox.expand(), ), ), // Scaffold avec fond transparent Scaffold( backgroundColor: Colors.transparent, appBar: DashboardAppBar( title: title, pageTitle: destinations[selectedIndex].label, isAdmin: isAdmin, onLogoutPressed: onLogoutPressed, ), body: ResponsiveNavigation( title: title, // Même si le titre n'est pas affiché dans la navigation, il est utilisé pour la cohérence body: body, selectedIndex: selectedIndex, onDestinationSelected: onDestinationSelected, destinations: destinations, // Ne pas afficher le bouton "Nouveau passage" dans la navigation showNewPassageButton: false, onNewPassagePressed: null, sidebarBottomItems: sidebarBottomItems, isAdmin: isAdmin, // Ne pas afficher l'AppBar dans la navigation car nous utilisons DashboardAppBar showAppBar: false, ), ), ], ); } catch (e) { debugPrint('ERREUR CRITIQUE dans DashboardLayout.build: $e'); // Afficher une interface de secours en cas d'erreur return Scaffold( appBar: AppBar( title: Text('Erreur - $title'), backgroundColor: Colors.red, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, color: Colors.red, size: 64), const SizedBox(height: 16), Text( 'Une erreur est survenue', style: TextStyle( fontSize: AppTheme.r(context, 20), fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text('Détails: $e'), const SizedBox(height: 24), ElevatedButton( onPressed: () { Navigator.of(context) .pushNamedAndRemoveUntil('/', (route) => false); }, child: const Text('Retour à l\'accueil'), ), ], ), ), ); } } } /// CustomPainter pour dessiner les petits points blancs sur le fond class DotsPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white.withValues(alpha: 0.5) ..style = PaintingStyle.fill; final random = math.Random(42); // Seed fixe pour consistance final numberOfDots = (size.width * size.height) ~/ 1500; for (int i = 0; i < numberOfDots; i++) { final x = random.nextDouble() * size.width; final y = random.nextDouble() * size.height; final radius = 1.0 + random.nextDouble() * 2.0; canvas.drawCircle(Offset(x, y), radius, paint); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }