|
|
@ -21,6 +21,9 @@ class CustomDrawer extends StatelessWidget { |
|
|
final prefs = await SharedPreferences.getInstance(); |
|
|
final prefs = await SharedPreferences.getInstance(); |
|
|
await prefs.remove('username'); |
|
|
await prefs.remove('username'); |
|
|
await prefs.remove('role'); |
|
|
await prefs.remove('role'); |
|
|
|
|
|
await prefs.remove('user_id'); |
|
|
|
|
|
|
|
|
|
|
|
userController.clearUserData(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
CustomDrawer({super.key}); |
|
|
CustomDrawer({super.key}); |
|
|
@ -29,274 +32,308 @@ class CustomDrawer extends StatelessWidget { |
|
|
Widget build(BuildContext context) { |
|
|
Widget build(BuildContext context) { |
|
|
return Drawer( |
|
|
return Drawer( |
|
|
backgroundColor: Colors.white, |
|
|
backgroundColor: Colors.white, |
|
|
child: ListView( |
|
|
child: FutureBuilder( |
|
|
padding: EdgeInsets.zero, |
|
|
future: _buildDrawerItems(), |
|
|
children: [ |
|
|
builder: (context, snapshot) { |
|
|
// Header avec informations utilisateur |
|
|
if (snapshot.connectionState == ConnectionState.done) { |
|
|
GetBuilder<UserController>( |
|
|
return ListView( |
|
|
builder: (controller) => Container( |
|
|
padding: EdgeInsets.zero, |
|
|
padding: const EdgeInsets.only(top: 50, left: 20, bottom: 20), |
|
|
children: snapshot.data as List<Widget>, |
|
|
decoration: const BoxDecoration( |
|
|
); |
|
|
gradient: LinearGradient( |
|
|
} else { |
|
|
colors: [Color.fromARGB(255, 4, 54, 95), Colors.blue], |
|
|
return const Center(child: CircularProgressIndicator()); |
|
|
begin: Alignment.topLeft, |
|
|
} |
|
|
end: Alignment.bottomRight, |
|
|
}, |
|
|
), |
|
|
), |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Future<List<Widget>> _buildDrawerItems() async { |
|
|
|
|
|
List<Widget> drawerItems = []; |
|
|
|
|
|
|
|
|
|
|
|
drawerItems.add( |
|
|
|
|
|
GetBuilder<UserController>( |
|
|
|
|
|
builder: (controller) => Container( |
|
|
|
|
|
padding: const EdgeInsets.only(top: 50, left: 20, bottom: 20), |
|
|
|
|
|
decoration: const BoxDecoration( |
|
|
|
|
|
gradient: LinearGradient( |
|
|
|
|
|
colors: [Color.fromARGB(255, 4, 54, 95), Colors.blue], |
|
|
|
|
|
begin: Alignment.topLeft, |
|
|
|
|
|
end: Alignment.bottomRight, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
child: Row( |
|
|
|
|
|
children: [ |
|
|
|
|
|
const CircleAvatar( |
|
|
|
|
|
radius: 30, |
|
|
|
|
|
backgroundImage: AssetImage("assets/youmaz2.png"), |
|
|
), |
|
|
), |
|
|
child: Row( |
|
|
const SizedBox(width: 15), |
|
|
|
|
|
Column( |
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
const CircleAvatar( |
|
|
Text( |
|
|
radius: 30, |
|
|
controller.name.isNotEmpty ? controller.name : 'Utilisateur', |
|
|
backgroundImage: AssetImage("assets/youmaz2.png"), |
|
|
style: const TextStyle( |
|
|
|
|
|
color: Colors.white, |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
const SizedBox(width: 15), |
|
|
Text( |
|
|
Column( |
|
|
controller.role.isNotEmpty ? controller.role : 'Aucun rôle', |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
style: const TextStyle( |
|
|
children: [ |
|
|
color: Colors.white70, |
|
|
Text( |
|
|
fontSize: 12, |
|
|
controller.name, |
|
|
), |
|
|
style: const TextStyle( |
|
|
|
|
|
color: Colors.white, |
|
|
|
|
|
fontSize: 18, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
Text( |
|
|
|
|
|
controller.email, |
|
|
|
|
|
style: const TextStyle( |
|
|
|
|
|
color: Colors.white70, |
|
|
|
|
|
fontSize: 14, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
Text( |
|
|
|
|
|
controller.role, |
|
|
|
|
|
style: const TextStyle( |
|
|
|
|
|
color: Colors.white70, |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// Section Accueil |
|
|
|
|
|
_buildDrawerItem( |
|
|
|
|
|
icon: Icons.home, |
|
|
|
|
|
title: "Accueil", |
|
|
|
|
|
color: Colors.blue, |
|
|
|
|
|
permissionAction: 'view', |
|
|
|
|
|
permissionRoute: '/accueil', |
|
|
|
|
|
onTap: () => Get.to(const AccueilPage()), |
|
|
|
|
|
), |
|
|
), |
|
|
|
|
|
), |
|
|
// Section Utilisateurs |
|
|
), |
|
|
const Padding( |
|
|
); |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
|
|
|
child: Text( |
|
|
drawerItems.add( |
|
|
"GESTION UTILISATEURS", |
|
|
await _buildDrawerItem( |
|
|
style: TextStyle( |
|
|
icon: Icons.home, |
|
|
color: Colors.grey, |
|
|
title: "Accueil", |
|
|
fontSize: 12, |
|
|
color: Colors.blue, |
|
|
fontWeight: FontWeight.bold, |
|
|
permissionAction: 'view', |
|
|
), |
|
|
permissionRoute: '/accueil', |
|
|
|
|
|
onTap: () => Get.to(const AccueilPage()), |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
List<Widget> gestionUtilisateursItems = [ |
|
|
|
|
|
await _buildDrawerItem( |
|
|
|
|
|
icon: Icons.person_add, |
|
|
|
|
|
title: "Ajouter un utilisateur", |
|
|
|
|
|
color: Colors.green, |
|
|
|
|
|
permissionAction: 'create', |
|
|
|
|
|
permissionRoute: '/ajouter-utilisateur', |
|
|
|
|
|
onTap: () => Get.to(const RegistrationPage()), |
|
|
|
|
|
), |
|
|
|
|
|
await _buildDrawerItem( |
|
|
|
|
|
icon: Icons.supervised_user_circle, |
|
|
|
|
|
title: "Gérer les utilisateurs", |
|
|
|
|
|
color: const Color.fromARGB(255, 4, 54, 95), |
|
|
|
|
|
permissionAction: 'update', |
|
|
|
|
|
permissionRoute: '/modifier-utilisateur', |
|
|
|
|
|
onTap: () => Get.to(const ListUserPage()), |
|
|
|
|
|
), |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
if (gestionUtilisateursItems.any((item) => item is ListTile)) { |
|
|
|
|
|
drawerItems.add( |
|
|
|
|
|
const Padding( |
|
|
|
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
"GESTION UTILISATEURS", |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
_buildDrawerItem( |
|
|
), |
|
|
icon: Icons.person_add, |
|
|
); |
|
|
title: "Ajouter un utilisateur", |
|
|
drawerItems.addAll(gestionUtilisateursItems); |
|
|
color: Colors.green, |
|
|
} |
|
|
permissionAction: 'create', |
|
|
|
|
|
permissionRoute: '/ajouter-utilisateur', |
|
|
List<Widget> gestionProduitsItems = [ |
|
|
onTap: () => Get.to(const RegistrationPage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.inventory, |
|
|
_buildDrawerItem( |
|
|
title: "Gestion des produits", |
|
|
icon: Icons.supervised_user_circle, |
|
|
color: Colors.indigoAccent, |
|
|
title: "Gérer les utilisateurs", |
|
|
permissionAction: 'create', |
|
|
color: Color.fromARGB(255, 4, 54, 95), |
|
|
permissionRoute: '/ajouter-produit', |
|
|
permissionAction: 'update', |
|
|
onTap: () => Get.to(const ProductManagementPage()), |
|
|
permissionRoute: '/modifier-utilisateur', |
|
|
), |
|
|
onTap: () => Get.to(const ListUserPage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.storage, |
|
|
|
|
|
title: "Gestion de stock", |
|
|
// Section Produits |
|
|
color: Colors.blueAccent, |
|
|
const Padding( |
|
|
permissionAction: 'update', |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
permissionRoute: '/gestion-stock', |
|
|
child: Text( |
|
|
onTap: () => Get.to(const GestionStockPage()), |
|
|
"GESTION PRODUITS", |
|
|
), |
|
|
style: TextStyle( |
|
|
]; |
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
if (gestionProduitsItems.any((item) => item is ListTile)) { |
|
|
fontWeight: FontWeight.bold, |
|
|
drawerItems.add( |
|
|
), |
|
|
const Padding( |
|
|
|
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
"GESTION PRODUITS", |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
_buildDrawerItem( |
|
|
), |
|
|
icon: Icons.inventory, |
|
|
); |
|
|
title: "Gestion des produits", |
|
|
drawerItems.addAll(gestionProduitsItems); |
|
|
color: Colors.indigoAccent, |
|
|
} |
|
|
permissionAction: 'create', |
|
|
|
|
|
permissionRoute: '/ajouter-produit', |
|
|
List<Widget> gestionCommandesItems = [ |
|
|
onTap: () => Get.to(const ProductManagementPage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.add_shopping_cart, |
|
|
_buildDrawerItem( |
|
|
title: "Nouvelle commande", |
|
|
icon: Icons.storage, |
|
|
color: Colors.orange, |
|
|
title: "Gestion de stock", |
|
|
permissionAction: 'create', |
|
|
color: Colors.blueAccent, |
|
|
permissionRoute: '/nouvelle-commande', |
|
|
permissionAction: 'update', |
|
|
onTap: () => Get.to(const NouvelleCommandePage()), |
|
|
permissionRoute: '/gestion-stock', |
|
|
), |
|
|
onTap: () => Get.to(const GestionStockPage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.list_alt, |
|
|
|
|
|
title: "Gérer les commandes", |
|
|
// Section Commandes |
|
|
color: Colors.deepPurple, |
|
|
const Padding( |
|
|
permissionAction: 'manage', |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
permissionRoute: '/gerer-commandes', |
|
|
child: Text( |
|
|
onTap: () => Get.to(const GestionCommandesPage()), |
|
|
"GESTION COMMANDES", |
|
|
), |
|
|
style: TextStyle( |
|
|
]; |
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
if (gestionCommandesItems.any((item) => item is ListTile)) { |
|
|
fontWeight: FontWeight.bold, |
|
|
drawerItems.add( |
|
|
), |
|
|
const Padding( |
|
|
|
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
"GESTION COMMANDES", |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
_buildDrawerItem( |
|
|
), |
|
|
icon: Icons.add_shopping_cart, |
|
|
); |
|
|
title: "Nouvelle commande", |
|
|
drawerItems.addAll(gestionCommandesItems); |
|
|
color: Colors.orange, |
|
|
} |
|
|
permissionAction: 'create', |
|
|
|
|
|
permissionRoute: '/nouvelle-commande', |
|
|
List<Widget> rapportsItems = [ |
|
|
onTap: () => Get.to(const NouvelleCommandePage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.bar_chart, |
|
|
_buildDrawerItem( |
|
|
title: "Bilan mensuel", |
|
|
icon: Icons.list_alt, |
|
|
color: Colors.teal, |
|
|
title: "Gérer les commandes", |
|
|
permissionAction: 'read', |
|
|
color: Colors.deepPurple, |
|
|
permissionRoute: '/bilan', |
|
|
permissionAction: 'manage', |
|
|
onTap: () => Get.to(const BilanMois()), |
|
|
permissionRoute: '/gerer-commandes', |
|
|
), |
|
|
onTap: () => Get.to(const GestionCommandesPage()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.history, |
|
|
|
|
|
title: "Historique", |
|
|
// Section Rapports |
|
|
color: Colors.blue, |
|
|
const Padding( |
|
|
permissionAction: 'read', |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
permissionRoute: '/historique', |
|
|
child: Text( |
|
|
onTap: () => Get.to(HistoryPage()), |
|
|
"RAPPORTS", |
|
|
), |
|
|
style: TextStyle( |
|
|
]; |
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
if (rapportsItems.any((item) => item is ListTile)) { |
|
|
fontWeight: FontWeight.bold, |
|
|
drawerItems.add( |
|
|
), |
|
|
const Padding( |
|
|
|
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
|
|
|
child: Text( |
|
|
|
|
|
"RAPPORTS", |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
color: Colors.grey, |
|
|
|
|
|
fontSize: 12, |
|
|
|
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
_buildDrawerItem( |
|
|
), |
|
|
icon: Icons.bar_chart, |
|
|
); |
|
|
title: "Bilan mensuel", |
|
|
drawerItems.addAll(rapportsItems); |
|
|
color: Colors.teal, |
|
|
} |
|
|
permissionAction: 'read', |
|
|
|
|
|
permissionRoute: '/bilan', |
|
|
List<Widget> administrationItems = [ |
|
|
onTap: () => Get.to(const BilanMois()), |
|
|
await _buildDrawerItem( |
|
|
), |
|
|
icon: Icons.admin_panel_settings, |
|
|
_buildDrawerItem( |
|
|
title: "Gérer les rôles", |
|
|
icon: Icons.history, |
|
|
color: Colors.redAccent, |
|
|
title: "Historique", |
|
|
permissionAction: 'admin', |
|
|
color: Colors.blue, |
|
|
permissionRoute: '/gerer-roles', |
|
|
permissionAction: 'read', |
|
|
onTap: () => Get.to(const RoleListPage()), |
|
|
permissionRoute: '/historique', |
|
|
), |
|
|
onTap: () => Get.to(HistoryPage()), |
|
|
]; |
|
|
), |
|
|
|
|
|
|
|
|
if (administrationItems.any((item) => item is ListTile)) { |
|
|
// Section Administration |
|
|
drawerItems.add( |
|
|
const Padding( |
|
|
const Padding( |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
padding: EdgeInsets.only(left: 20, top: 15, bottom: 5), |
|
|
child: Text( |
|
|
child: Text( |
|
|
"ADMINISTRATION", |
|
|
"ADMINISTRATION", |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
color: Colors.grey, |
|
|
color: Colors.grey, |
|
|
fontSize: 12, |
|
|
fontSize: 12, |
|
|
fontWeight: FontWeight.bold, |
|
|
fontWeight: FontWeight.bold, |
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
_buildDrawerItem( |
|
|
), |
|
|
icon: Icons.admin_panel_settings, |
|
|
); |
|
|
title: "Gérer les rôles", |
|
|
drawerItems.addAll(administrationItems); |
|
|
color: Colors.redAccent, |
|
|
} |
|
|
permissionAction: 'admin', |
|
|
|
|
|
permissionRoute: '/gerer-roles', |
|
|
drawerItems.add(const Divider()); |
|
|
onTap: () => Get.to(const RoleListPage()), |
|
|
|
|
|
), |
|
|
drawerItems.add( |
|
|
|
|
|
ListTile( |
|
|
// Déconnexion |
|
|
leading: const Icon(Icons.logout, color: Colors.red), |
|
|
const Divider(), |
|
|
title: const Text("Déconnexion"), |
|
|
_buildDrawerItem( |
|
|
onTap: () { |
|
|
icon: Icons.logout, |
|
|
Get.defaultDialog( |
|
|
title: "Déconnexion", |
|
|
title: "Déconnexion", |
|
|
color: Colors.red, |
|
|
content: const Text("Voulez-vous vraiment vous déconnecter ?"), |
|
|
onTap: () { |
|
|
actions: [ |
|
|
Get.defaultDialog( |
|
|
TextButton( |
|
|
title: "Déconnexion", |
|
|
child: const Text("Non"), |
|
|
content: const Text("Voulez-vous vraiment vous déconnecter ?"), |
|
|
onPressed: () => Get.back(), |
|
|
actions: [ |
|
|
), |
|
|
TextButton( |
|
|
ElevatedButton( |
|
|
child: const Text("Non"), |
|
|
style: ElevatedButton.styleFrom( |
|
|
onPressed: () => Get.back(), |
|
|
backgroundColor: Colors.red, |
|
|
), |
|
|
), |
|
|
ElevatedButton( |
|
|
child: const Text("Oui"), |
|
|
style: ElevatedButton.styleFrom( |
|
|
onPressed: () async { |
|
|
backgroundColor: Colors.red, |
|
|
await clearUserData(); |
|
|
), |
|
|
Get.offAll(const LoginPage()); |
|
|
child: const Text("Oui"), |
|
|
}, |
|
|
onPressed: () { |
|
|
), |
|
|
clearUserData(); |
|
|
], |
|
|
Get.offAll(const LoginPage()); |
|
|
); |
|
|
}, |
|
|
}, |
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return drawerItems; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Widget _buildDrawerItem({ |
|
|
Future<Widget> _buildDrawerItem({ |
|
|
required IconData icon, |
|
|
required IconData icon, |
|
|
required String title, |
|
|
required String title, |
|
|
required Color color, |
|
|
required Color color, |
|
|
String? permissionAction, |
|
|
String? permissionAction, |
|
|
String? permissionRoute, |
|
|
String? permissionRoute, |
|
|
required VoidCallback onTap, |
|
|
required VoidCallback onTap, |
|
|
}) { |
|
|
}) async { |
|
|
|
|
|
if (permissionAction != null && permissionRoute != null) { |
|
|
|
|
|
bool hasPermission = await userController.hasPermission(permissionAction, permissionRoute); |
|
|
|
|
|
if (!hasPermission) { |
|
|
|
|
|
return const SizedBox.shrink(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return ListTile( |
|
|
return ListTile( |
|
|
leading: Icon(icon, color: color), |
|
|
leading: Icon(icon, color: color), |
|
|
title: Text(title), |
|
|
title: Text(title), |
|
|
trailing: permissionAction != null |
|
|
trailing: permissionAction != null |
|
|
? const Icon(Icons.chevron_right, color: Colors.grey) |
|
|
? const Icon(Icons.chevron_right, color: Colors.grey) |
|
|
: null, |
|
|
: null, |
|
|
onTap: () async { |
|
|
onTap: onTap, |
|
|
if (permissionAction != null && permissionRoute != null) { |
|
|
|
|
|
bool hasPermission = await userController.hasPermission(permissionAction, permissionRoute); |
|
|
|
|
|
if (hasPermission) { |
|
|
|
|
|
onTap(); |
|
|
|
|
|
} else { |
|
|
|
|
|
Get.snackbar( |
|
|
|
|
|
"Accès refusé", |
|
|
|
|
|
"Vous n'avez pas les droits pour accéder à cette page", |
|
|
|
|
|
backgroundColor: Colors.red, |
|
|
|
|
|
colorText: Colors.white, |
|
|
|
|
|
icon: const Icon(Icons.error), |
|
|
|
|
|
duration: const Duration(seconds: 3), |
|
|
|
|
|
snackPosition: SnackPosition.TOP, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
onTap(); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|