refactor: Simplifier DashboardLayout/AppScaffold (tâche #74)

Centralisation et simplification de l'architecture de navigation :

CRÉATIONS :
- navigation_config.dart : Configuration centralisée de la navigation
  * Toutes les destinations (admin/user)
  * Logique de navigation (index → route)
  * Résolution inverse (route → index)
  * Titres et utilitaires

- backgrounds/dots_painter.dart : Painter de points décoratifs
  * Extrait depuis AppScaffold et AdminScaffold
  * Paramétrable (opacité, densité, seed)
  * Réutilisable

- backgrounds/gradient_background.dart : Fond dégradé
  * Gère les couleurs admin (rouge) / user (vert)
  * Option pour afficher/masquer les points
  * Widget indépendant

SIMPLIFICATIONS :
- app_scaffold.dart : 426 → 192 lignes (-55%)
  * Utilise NavigationConfig au lieu de NavigationHelper
  * Utilise GradientBackground au lieu de code dupliqué
  * Suppression de DotsPainter local

- dashboard_layout.dart : 140 → 77 lignes (-45%)
  * Suppression validations excessives (try/catch, vérifications)
  * Code épuré et plus lisible

SUPPRESSIONS :
- admin_scaffold.dart : Supprimé (207 lignes)
  * Obsolète depuis unification avec AppScaffold
  * Code dupliqué avec AppScaffold
  * AdminNavigationHelper fusionné dans NavigationConfig

RÉSULTATS :
- Avant : 773 lignes (AppScaffold + AdminScaffold + DashboardLayout)
- Après : 623 lignes (tout inclus)
- Réduction nette : -150 lignes (-19%)
- Architecture plus claire et maintenable
- Aucune duplication de code
- Navigation centralisée en un seul endroit

Résout tâche #74 du PLANNING-2026-Q1.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-26 15:27:54 +01:00
parent 7345cf805e
commit 1cdb4ec58c
6 changed files with 395 additions and 543 deletions

View File

@@ -48,92 +48,30 @@ class DashboardLayout extends StatelessWidget {
@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)'),
),
);
}
// Scaffold avec fond transparent (le fond est géré par AppScaffold)
return Scaffold(
key: ValueKey('dashboard_scaffold_$selectedIndex'),
backgroundColor: Colors.transparent,
appBar: DashboardAppBar(
key: ValueKey('dashboard_appbar_$selectedIndex'),
title: title,
pageTitle: destinations[selectedIndex].label,
isAdmin: isAdmin,
onLogoutPressed: onLogoutPressed,
),
body: ResponsiveNavigation(
key: ValueKey('responsive_nav_$selectedIndex'),
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'),
),
],
),
),
);
}
// Scaffold avec fond transparent (le fond est géré par AppScaffold)
return Scaffold(
key: ValueKey('dashboard_scaffold_$selectedIndex'),
backgroundColor: Colors.transparent,
appBar: DashboardAppBar(
key: ValueKey('dashboard_appbar_$selectedIndex'),
title: title,
pageTitle: destinations[selectedIndex].label,
isAdmin: isAdmin,
onLogoutPressed: onLogoutPressed,
),
body: ResponsiveNavigation(
key: ValueKey('responsive_nav_$selectedIndex'),
title: title,
body: body,
selectedIndex: selectedIndex,
onDestinationSelected: onDestinationSelected,
destinations: destinations,
showNewPassageButton: false,
onNewPassagePressed: null,
sidebarBottomItems: sidebarBottomItems,
isAdmin: isAdmin,
showAppBar: false,
),
);
}
}