|
|
|
@ -47,10 +47,10 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
children: [ |
|
|
|
// Header utilisateur |
|
|
|
_buildUserHeader(controller), |
|
|
|
|
|
|
|
|
|
|
|
// ✅ CORRIGÉ: Construction avec gestion des valeurs null |
|
|
|
..._buildDrawerItemsFromSessionCache(), |
|
|
|
|
|
|
|
|
|
|
|
// Déconnexion |
|
|
|
const Divider(), |
|
|
|
_buildLogoutItem(), |
|
|
|
@ -64,7 +64,7 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
/// ✅ CORRIGÉ: Construction avec validation robuste des données |
|
|
|
List<Widget> _buildDrawerItemsFromSessionCache() { |
|
|
|
List<Widget> drawerItems = []; |
|
|
|
|
|
|
|
|
|
|
|
// Vérifier si le cache est prêt |
|
|
|
if (!userController.isCacheReady) { |
|
|
|
return [ |
|
|
|
@ -90,17 +90,17 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
|
|
|
|
// Récupérer les menus depuis le cache de session |
|
|
|
final rawUserMenus = userController.getUserMenus(); |
|
|
|
|
|
|
|
|
|
|
|
// 🛡️ VALIDATION: Filtrer les menus valides |
|
|
|
final validMenus = <Map<String, dynamic>>[]; |
|
|
|
final invalidMenus = <Map<String, dynamic>>[]; |
|
|
|
|
|
|
|
|
|
|
|
for (var menu in rawUserMenus) { |
|
|
|
// Vérifier que les champs essentiels ne sont pas null |
|
|
|
final name = menu['name']; |
|
|
|
final route = menu['route']; |
|
|
|
final id = menu['id']; |
|
|
|
|
|
|
|
|
|
|
|
if (name != null && route != null && route.toString().isNotEmpty) { |
|
|
|
validMenus.add({ |
|
|
|
'id': id, |
|
|
|
@ -109,33 +109,35 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
}); |
|
|
|
} else { |
|
|
|
invalidMenus.add(menu); |
|
|
|
print("⚠️ Menu invalide ignoré dans CustomDrawer: id=$id, name='$name', route='$route'"); |
|
|
|
// print("⚠️ Menu invalide ignoré dans CustomDrawer: id=$id, name='$name', route='$route'"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ✅ NOUVEAU: Ajouter le menu Demande Assignation pour Super Admin uniquement |
|
|
|
if (userController.role == 'Super Admin') { |
|
|
|
// Vérifier si le menu n'existe pas déjà |
|
|
|
final bool demandeAssignationExists = validMenus.any((menu) => menu['route'] == '/demande-assignation'); |
|
|
|
|
|
|
|
final bool demandeAssignationExists = |
|
|
|
validMenus.any((menu) => menu['route'] == '/demande-assignation'); |
|
|
|
|
|
|
|
if (!demandeAssignationExists) { |
|
|
|
validMenus.add({ |
|
|
|
'id': 'super_admin_demande_assignation', |
|
|
|
'name': 'Demande Assignation', |
|
|
|
'route': '/demande-assignation', |
|
|
|
}); |
|
|
|
print("✅ Menu 'Demande Assignation' ajouté pour Super Admin"); |
|
|
|
// print("✅ Menu 'Demande Assignation' ajouté pour Super Admin"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ✅ NOUVEAU: Ajouter les menus de sorties personnelles |
|
|
|
_addSortiesPersonnellesMenus(validMenus); |
|
|
|
|
|
|
|
|
|
|
|
// Afficher les statistiques de validation |
|
|
|
if (invalidMenus.isNotEmpty) { |
|
|
|
print("📊 CustomDrawer: ${validMenus.length} menus valides, ${invalidMenus.length} invalides"); |
|
|
|
// print( |
|
|
|
// "📊 CustomDrawer: ${validMenus.length} menus valides, ${invalidMenus.length} invalides"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (validMenus.isEmpty) { |
|
|
|
return [ |
|
|
|
const Padding( |
|
|
|
@ -156,9 +158,10 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
uniqueMenus[route] = menu; |
|
|
|
} |
|
|
|
final deduplicatedMenus = uniqueMenus.values.toList(); |
|
|
|
|
|
|
|
|
|
|
|
if (deduplicatedMenus.length != validMenus.length) { |
|
|
|
print("🔧 CustomDrawer: ${validMenus.length - deduplicatedMenus.length} doublons supprimés"); |
|
|
|
// print( |
|
|
|
// "🔧 CustomDrawer: ${validMenus.length - deduplicatedMenus.length} doublons supprimés"); |
|
|
|
} |
|
|
|
|
|
|
|
// Organiser les menus par catégories |
|
|
|
@ -173,7 +176,9 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
}; |
|
|
|
|
|
|
|
// Accueil toujours en premier |
|
|
|
final accueilMenu = deduplicatedMenus.where((menu) => menu['route'] == '/accueil').firstOrNull; |
|
|
|
final accueilMenu = deduplicatedMenus |
|
|
|
.where((menu) => menu['route'] == '/accueil') |
|
|
|
.firstOrNull; |
|
|
|
if (accueilMenu != null) { |
|
|
|
drawerItems.add(_buildDrawerItemFromMenu(accueilMenu)); |
|
|
|
} |
|
|
|
@ -181,13 +186,13 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
// Catégoriser les autres menus avec validation supplémentaire |
|
|
|
for (var menu in deduplicatedMenus) { |
|
|
|
final route = menu['route'] as String; |
|
|
|
|
|
|
|
|
|
|
|
// ✅ Validation supplémentaire avant categorisation |
|
|
|
if (route.isEmpty) { |
|
|
|
print("⚠️ Route vide ignorée: ${menu['name']}"); |
|
|
|
// print("⚠️ Route vide ignorée: ${menu['name']}"); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch (route) { |
|
|
|
case '/accueil': |
|
|
|
// Déjà traité |
|
|
|
@ -224,7 +229,7 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
break; |
|
|
|
default: |
|
|
|
// Menu non catégorisé |
|
|
|
print("⚠️ Menu non catégorisé: $route"); |
|
|
|
// print("⚠️ Menu non catégorisé: $route"); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -233,10 +238,11 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
categorizedMenus.forEach((categoryName, menus) { |
|
|
|
if (menus.isNotEmpty) { |
|
|
|
// ✅ Afficher la catégorie SUPER ADMIN seulement pour les Super Admin |
|
|
|
if (categoryName == 'SUPER ADMIN' && userController.role != 'Super Admin') { |
|
|
|
if (categoryName == 'SUPER ADMIN' && |
|
|
|
userController.role != 'Super Admin') { |
|
|
|
return; // Skip cette catégorie |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
drawerItems.add(_buildCategoryHeader(categoryName)); |
|
|
|
for (var menu in menus) { |
|
|
|
drawerItems.add(_buildDrawerItemFromMenu(menu)); |
|
|
|
@ -250,37 +256,42 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
/// ✅ NOUVEAU: Méthode pour ajouter les menus de sorties personnelles |
|
|
|
void _addSortiesPersonnellesMenus(List<Map<String, dynamic>> validMenus) { |
|
|
|
// Menu Demande Sortie Personnelle - Accessible à tous les utilisateurs connectés |
|
|
|
final bool demandeSortieExists = validMenus.any((menu) => menu['route'] == '/demande-sortie-personnelle'); |
|
|
|
final bool demandeSortieExists = validMenus |
|
|
|
.any((menu) => menu['route'] == '/demande-sortie-personnelle'); |
|
|
|
if (!demandeSortieExists) { |
|
|
|
validMenus.add({ |
|
|
|
'id': 'demande_sortie_personnelle', |
|
|
|
'name': 'Demande sortie personnelle', |
|
|
|
'route': '/demande-sortie-personnelle', |
|
|
|
}); |
|
|
|
print("✅ Menu 'Demande sortie personnelle' ajouté pour tous les utilisateurs"); |
|
|
|
// print( |
|
|
|
// "✅ Menu 'Demande sortie personnelle' ajouté pour tous les utilisateurs"); |
|
|
|
} |
|
|
|
|
|
|
|
// Menu Historique Sorties Personnelles - Accessible à tous les utilisateurs connectés |
|
|
|
final bool historiqueSortiesExists = validMenus.any((menu) => menu['route'] == '/historique-sorties-personnelles'); |
|
|
|
final bool historiqueSortiesExists = validMenus |
|
|
|
.any((menu) => menu['route'] == '/historique-sorties-personnelles'); |
|
|
|
if (!historiqueSortiesExists) { |
|
|
|
validMenus.add({ |
|
|
|
'id': 'historique_sorties_personnelles', |
|
|
|
'name': 'Historique sorties personnelles', |
|
|
|
'route': '/historique-sorties-personnelles', |
|
|
|
}); |
|
|
|
print("✅ Menu 'Historique sorties personnelles' ajouté pour tous les utilisateurs"); |
|
|
|
// print( |
|
|
|
// "✅ Menu 'Historique sorties personnelles' ajouté pour tous les utilisateurs"); |
|
|
|
} |
|
|
|
|
|
|
|
// Menu Approbation Sorties - Accessible SEULEMENT aux Super Admin |
|
|
|
if (userController.role == 'Super Admin') { |
|
|
|
final bool approbationSortiesExists = validMenus.any((menu) => menu['route'] == '/approbation-sorties'); |
|
|
|
final bool approbationSortiesExists = |
|
|
|
validMenus.any((menu) => menu['route'] == '/approbation-sorties'); |
|
|
|
if (!approbationSortiesExists) { |
|
|
|
validMenus.add({ |
|
|
|
'id': 'approbation_sorties', |
|
|
|
'name': 'Approuver sorties', |
|
|
|
'route': '/approbation-sorties', |
|
|
|
}); |
|
|
|
print("✅ Menu 'Approuver sorties' ajouté pour Super Admin"); |
|
|
|
// print("✅ Menu 'Approuver sorties' ajouté pour Super Admin"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -290,20 +301,21 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
// 🛡️ VALIDATION: Vérification des types avec gestion des null |
|
|
|
final nameObj = menu['name']; |
|
|
|
final routeObj = menu['route']; |
|
|
|
|
|
|
|
|
|
|
|
if (nameObj == null || routeObj == null) { |
|
|
|
print("⚠️ Menu invalide dans _buildDrawerItemFromMenu: name=$nameObj, route=$routeObj"); |
|
|
|
// print( |
|
|
|
// "⚠️ Menu invalide dans _buildDrawerItemFromMenu: name=$nameObj, route=$routeObj"); |
|
|
|
return const SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final String name = nameObj.toString(); |
|
|
|
final String route = routeObj.toString(); |
|
|
|
|
|
|
|
|
|
|
|
if (name.isEmpty || route.isEmpty) { |
|
|
|
print("⚠️ Menu avec valeurs vides: name='$name', route='$route'"); |
|
|
|
// print("⚠️ Menu avec valeurs vides: name='$name', route='$route'"); |
|
|
|
return const SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Mapping des routes vers les widgets et icônes |
|
|
|
final Map<String, Map<String, dynamic>> routeMapping = { |
|
|
|
'/accueil': { |
|
|
|
@ -391,11 +403,12 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
|
|
|
|
final routeData = routeMapping[route]; |
|
|
|
if (routeData == null) { |
|
|
|
print("⚠️ Route non reconnue: '$route' pour le menu '$name'"); |
|
|
|
// print("⚠️ Route non reconnue: '$route' pour le menu '$name'"); |
|
|
|
return ListTile( |
|
|
|
leading: const Icon(Icons.help_outline, color: Colors.grey), |
|
|
|
title: Text(name), |
|
|
|
subtitle: Text("Route: $route", style: const TextStyle(fontSize: 10, color: Colors.grey)), |
|
|
|
subtitle: Text("Route: $route", |
|
|
|
style: const TextStyle(fontSize: 10, color: Colors.grey)), |
|
|
|
onTap: () { |
|
|
|
Get.snackbar( |
|
|
|
"Route non configurée", |
|
|
|
@ -417,7 +430,8 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
// ✅ NOUVEAU: Badge Super Admin pour les menus réservés |
|
|
|
if ((route == '/demande-assignation' || route == '/approbation-sorties') && |
|
|
|
if ((route == '/demande-assignation' || |
|
|
|
route == '/approbation-sorties') && |
|
|
|
userController.role == 'Super Admin') ...[ |
|
|
|
Container( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), |
|
|
|
@ -437,7 +451,8 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
const SizedBox(width: 4), |
|
|
|
], |
|
|
|
// ✅ NOUVEAU: Badge "Tous" pour les menus accessibles à tous |
|
|
|
if (route == '/demande-sortie-personnelle' || route == '/historique-sorties-personnelles') ...[ |
|
|
|
if (route == '/demande-sortie-personnelle' || |
|
|
|
route == '/historique-sorties-personnelles') ...[ |
|
|
|
Container( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), |
|
|
|
decoration: BoxDecoration( |
|
|
|
@ -544,7 +559,9 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
controller.role.isNotEmpty ? controller.role : 'Aucun rôle', |
|
|
|
controller.role.isNotEmpty |
|
|
|
? controller.role |
|
|
|
: 'Aucun rôle', |
|
|
|
style: const TextStyle( |
|
|
|
color: Colors.white70, |
|
|
|
fontSize: 12, |
|
|
|
@ -554,7 +571,8 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
if (controller.role == 'Super Admin') ...[ |
|
|
|
const SizedBox(width: 8), |
|
|
|
Container( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), |
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
horizontal: 6, vertical: 2), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.red.shade600, |
|
|
|
borderRadius: BorderRadius.circular(8), |
|
|
|
@ -586,8 +604,12 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
controller.isCacheReady ? Icons.check_circle : Icons.hourglass_empty, |
|
|
|
color: controller.isCacheReady ? Colors.green : Colors.orange, |
|
|
|
controller.isCacheReady |
|
|
|
? Icons.check_circle |
|
|
|
: Icons.hourglass_empty, |
|
|
|
color: controller.isCacheReady |
|
|
|
? Colors.green |
|
|
|
: Colors.orange, |
|
|
|
size: 12, |
|
|
|
), |
|
|
|
const SizedBox(width: 4), |
|
|
|
@ -604,7 +626,8 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
// ✅ Bouton de rafraîchissement pour les admins |
|
|
|
if (controller.role == 'Super Admin' || controller.role == 'Admin') ...[ |
|
|
|
if (controller.role == 'Super Admin' || |
|
|
|
controller.role == 'Admin') ...[ |
|
|
|
IconButton( |
|
|
|
icon: const Icon(Icons.refresh, color: Colors.white70, size: 20), |
|
|
|
onPressed: () async { |
|
|
|
@ -630,28 +653,32 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
// 🔧 Bouton de debug (à supprimer en production) |
|
|
|
if (controller.role == 'Super Admin') ...[ |
|
|
|
IconButton( |
|
|
|
icon: const Icon(Icons.bug_report, color: Colors.white70, size: 18), |
|
|
|
icon: |
|
|
|
const Icon(Icons.bug_report, color: Colors.white70, size: 18), |
|
|
|
onPressed: () { |
|
|
|
// Debug des menus |
|
|
|
final menus = controller.getUserMenus(); |
|
|
|
String debugInfo = "MENUS DEBUG:\n"; |
|
|
|
for (var i = 0; i < menus.length; i++) { |
|
|
|
final menu = menus[i]; |
|
|
|
debugInfo += "[$i] ID:${menu['id']}, Name:'${menu['name']}', Route:'${menu['route']}'\n"; |
|
|
|
debugInfo += |
|
|
|
"[$i] ID:${menu['id']}, Name:'${menu['name']}', Route:'${menu['route']}'\n"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ✅ NOUVEAU: Ajouter info sur les menus sorties personnelles |
|
|
|
debugInfo += "\n--- MENUS SORTIES PERSONNELLES ---\n"; |
|
|
|
debugInfo += "Rôle actuel: ${controller.role}\n"; |
|
|
|
debugInfo += "Menu Demande Sortie: Accessible à tous\n"; |
|
|
|
debugInfo += "Menu Historique: Accessible à tous\n"; |
|
|
|
debugInfo += "Menu Approbation: ${controller.role == 'Super Admin' ? 'Accessible (Super Admin)' : 'Non accessible'}\n"; |
|
|
|
|
|
|
|
debugInfo += |
|
|
|
"Menu Approbation: ${controller.role == 'Super Admin' ? 'Accessible (Super Admin)' : 'Non accessible'}\n"; |
|
|
|
|
|
|
|
Get.dialog( |
|
|
|
AlertDialog( |
|
|
|
title: const Text("Debug Menus"), |
|
|
|
content: SingleChildScrollView( |
|
|
|
child: Text(debugInfo, style: const TextStyle(fontSize: 12)), |
|
|
|
child: |
|
|
|
Text(debugInfo, style: const TextStyle(fontSize: 12)), |
|
|
|
), |
|
|
|
actions: [ |
|
|
|
TextButton( |
|
|
|
@ -797,4 +824,4 @@ class CustomDrawer extends StatelessWidget { |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|